]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] make __sigqueue_alloc() a general helper
authorChris Wright <chrisw@osdl.org>
Fri, 22 Oct 2004 01:18:17 +0000 (18:18 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 22 Oct 2004 01:18:17 +0000 (18:18 -0700)
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: Linus Torvalds <torvalds@osdl.org>
kernel/signal.c

index cffd995bab69a8f8c41c03b2a79e68e9edaf19b3..fb156855ed40ea2ccead7b09db646bd7ccfd62dc 100644 (file)
@@ -265,18 +265,18 @@ next_signal(struct sigpending *pending, sigset_t *mask)
        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 siginfo *info, struct task_struct *t,
           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);
 }