
From: Chris Wright <chrisw@osdl.org>

Posix timers preallocate siqueue structures during timer creation and keep
them for reuse.  This allocation happens in user context with no locks
held, however it's designated as an atomic allocation.  Loosen this
restriction, and while we're at it let's do a bit of code consolidation so
signal sending uses same __sigqueue_alloc() helper.

Signed-off-by: Chris Wright <chrisw@osdl.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/kernel/signal.c |   20 +++++++-------------
 1 files changed, 7 insertions(+), 13 deletions(-)

diff -puN kernel/signal.c~make-__sigqueue_alloc-a-general-helper kernel/signal.c
--- 25/kernel/signal.c~make-__sigqueue_alloc-a-general-helper	2004-10-21 21:11:38.600292664 -0700
+++ 25-akpm/kernel/signal.c	2004-10-21 21:11:38.614290536 -0700
@@ -265,18 +265,18 @@ next_signal(struct sigpending *pending, 
 	return sig;
 }
 
-static struct sigqueue *__sigqueue_alloc(void)
+static inline struct sigqueue *__sigqueue_alloc(struct task_struct *t, int flags)
 {
 	struct sigqueue *q = NULL;
 
-	if (atomic_read(&current->user->sigpending) <
-			current->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
-		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
+	if (atomic_read(&t->user->sigpending) <
+			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
+		q = kmem_cache_alloc(sigqueue_cachep, flags);
 	if (q) {
 		INIT_LIST_HEAD(&q->list);
 		q->flags = 0;
 		q->lock = NULL;
-		q->user = get_uid(current->user);
+		q->user = get_uid(t->user);
 		atomic_inc(&q->user->sigpending);
 	}
 	return(q);
@@ -764,14 +764,8 @@ static int send_signal(int sig, struct s
 	   make sure at least one signal gets delivered and don't
 	   pass on the info struct.  */
 
-	if (atomic_read(&t->user->sigpending) <
-			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
-		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
-
+	q = __sigqueue_alloc(t, GFP_ATOMIC);
 	if (q) {
-		q->flags = 0;
-		q->user = get_uid(t->user);
-		atomic_inc(&q->user->sigpending);
 		list_add_tail(&q->list, &signals->list);
 		switch ((unsigned long) info) {
 		case 0:
@@ -1298,7 +1292,7 @@ struct sigqueue *sigqueue_alloc(void)
 {
 	struct sigqueue *q;
 
-	if ((q = __sigqueue_alloc()))
+	if ((q = __sigqueue_alloc(current, GFP_KERNEL)))
 		q->flags |= SIGQUEUE_PREALLOC;
 	return(q);
 }
_
