Commit abed516f authored by Chris Wright's avatar Chris Wright Committed by Linus Torvalds

[PATCH] make __sigqueue_alloc() a general helper

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: default avatarChris Wright <chrisw@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 57f0ee4d
...@@ -265,18 +265,18 @@ next_signal(struct sigpending *pending, sigset_t *mask) ...@@ -265,18 +265,18 @@ next_signal(struct sigpending *pending, sigset_t *mask)
return sig; return sig;
} }
static struct sigqueue *__sigqueue_alloc(void) static inline struct sigqueue *__sigqueue_alloc(struct task_struct *t, int flags)
{ {
struct sigqueue *q = NULL; struct sigqueue *q = NULL;
if (atomic_read(&current->user->sigpending) < if (atomic_read(&t->user->sigpending) <
current->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC); q = kmem_cache_alloc(sigqueue_cachep, flags);
if (q) { if (q) {
INIT_LIST_HEAD(&q->list); INIT_LIST_HEAD(&q->list);
q->flags = 0; q->flags = 0;
q->lock = NULL; q->lock = NULL;
q->user = get_uid(current->user); q->user = get_uid(t->user);
atomic_inc(&q->user->sigpending); atomic_inc(&q->user->sigpending);
} }
return(q); return(q);
...@@ -764,14 +764,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, ...@@ -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 make sure at least one signal gets delivered and don't
pass on the info struct. */ pass on the info struct. */
if (atomic_read(&t->user->sigpending) < q = __sigqueue_alloc(t, GFP_ATOMIC);
t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
if (q) { if (q) {
q->flags = 0;
q->user = get_uid(t->user);
atomic_inc(&q->user->sigpending);
list_add_tail(&q->list, &signals->list); list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) { switch ((unsigned long) info) {
case 0: case 0:
...@@ -1298,7 +1292,7 @@ struct sigqueue *sigqueue_alloc(void) ...@@ -1298,7 +1292,7 @@ struct sigqueue *sigqueue_alloc(void)
{ {
struct sigqueue *q; struct sigqueue *q;
if ((q = __sigqueue_alloc())) if ((q = __sigqueue_alloc(current, GFP_KERNEL)))
q->flags |= SIGQUEUE_PREALLOC; q->flags |= SIGQUEUE_PREALLOC;
return(q); return(q);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment