diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-05-29 16:05:05 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-05-29 16:05:05 +0200 |
commit | 6715930654e06c4d2e66e718ea159079f71838f4 (patch) | |
tree | 6a0a19fb62f3e99cb5f6bf6c34ae541f7c30fb42 /kernel/signal.c | |
parent | ea3f01f8afd3bc5daff915cc4ea5cc5ea9e7d427 (diff) | |
parent | e490517a039a99d692cb3a5561941b0a5f576172 (diff) | |
download | blackbird-op-linux-6715930654e06c4d2e66e718ea159079f71838f4.tar.gz blackbird-op-linux-6715930654e06c4d2e66e718ea159079f71838f4.zip |
Merge commit 'linus/master' into sched-fixes-for-linus
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 72bb4f51f963..6c0958e52ea7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -231,6 +231,40 @@ void flush_signals(struct task_struct *t) spin_unlock_irqrestore(&t->sighand->siglock, flags); } +static void __flush_itimer_signals(struct sigpending *pending) +{ + sigset_t signal, retain; + struct sigqueue *q, *n; + + signal = pending->signal; + sigemptyset(&retain); + + list_for_each_entry_safe(q, n, &pending->list, list) { + int sig = q->info.si_signo; + + if (likely(q->info.si_code != SI_TIMER)) { + sigaddset(&retain, sig); + } else { + sigdelset(&signal, sig); + list_del_init(&q->list); + __sigqueue_free(q); + } + } + + sigorsets(&pending->signal, &signal, &retain); +} + +void flush_itimer_signals(void) +{ + struct task_struct *tsk = current; + unsigned long flags; + + spin_lock_irqsave(&tsk->sighand->siglock, flags); + __flush_itimer_signals(&tsk->pending); + __flush_itimer_signals(&tsk->signal->shared_pending); + spin_unlock_irqrestore(&tsk->sighand->siglock, flags); +} + void ignore_signals(struct task_struct *t) { int i; @@ -1240,17 +1274,22 @@ void sigqueue_free(struct sigqueue *q) BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); /* - * If the signal is still pending remove it from the - * pending queue. We must hold ->siglock while testing - * q->list to serialize with collect_signal(). + * We must hold ->siglock while testing q->list + * to serialize with collect_signal() or with + * __exit_signal()->flush_sigqueue(). */ spin_lock_irqsave(lock, flags); + q->flags &= ~SIGQUEUE_PREALLOC; + /* + * If it is queued it will be freed when dequeued, + * like the "regular" sigqueue. + */ if (!list_empty(&q->list)) - list_del_init(&q->list); + q = NULL; spin_unlock_irqrestore(lock, flags); - q->flags &= ~SIGQUEUE_PREALLOC; - __sigqueue_free(q); + if (q) + __sigqueue_free(q); } int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) |