From: Chris Wright 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 Signed-off-by: Andrew Morton --- 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(¤t->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); } _