|
@@ -510,7 +510,8 @@ int unhandled_signal(struct task_struct *tsk, int sig)
|
|
|
return !tsk->ptrace;
|
|
|
}
|
|
|
|
|
|
-static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
|
|
|
+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
|
|
|
+ bool *resched_timer)
|
|
|
{
|
|
|
struct sigqueue *q, *first = NULL;
|
|
|
|
|
@@ -532,6 +533,12 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
|
|
|
still_pending:
|
|
|
list_del_init(&first->list);
|
|
|
copy_siginfo(info, &first->info);
|
|
|
+
|
|
|
+ *resched_timer =
|
|
|
+ (first->flags & SIGQUEUE_PREALLOC) &&
|
|
|
+ (info->si_code == SI_TIMER) &&
|
|
|
+ (info->si_sys_private);
|
|
|
+
|
|
|
__sigqueue_free(first);
|
|
|
} else {
|
|
|
/*
|
|
@@ -548,12 +555,12 @@ still_pending:
|
|
|
}
|
|
|
|
|
|
static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
|
|
|
- siginfo_t *info)
|
|
|
+ siginfo_t *info, bool *resched_timer)
|
|
|
{
|
|
|
int sig = next_signal(pending, mask);
|
|
|
|
|
|
if (sig)
|
|
|
- collect_signal(sig, pending, info);
|
|
|
+ collect_signal(sig, pending, info, resched_timer);
|
|
|
return sig;
|
|
|
}
|
|
|
|
|
@@ -565,15 +572,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
|
|
|
*/
|
|
|
int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
|
|
|
{
|
|
|
+ bool resched_timer = false;
|
|
|
int signr;
|
|
|
|
|
|
/* We only dequeue private signals from ourselves, we don't let
|
|
|
* signalfd steal them
|
|
|
*/
|
|
|
- signr = __dequeue_signal(&tsk->pending, mask, info);
|
|
|
+ signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
|
|
|
if (!signr) {
|
|
|
signr = __dequeue_signal(&tsk->signal->shared_pending,
|
|
|
- mask, info);
|
|
|
+ mask, info, &resched_timer);
|
|
|
#ifdef CONFIG_POSIX_TIMERS
|
|
|
/*
|
|
|
* itimer signal ?
|
|
@@ -621,7 +629,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
|
|
|
current->jobctl |= JOBCTL_STOP_DEQUEUED;
|
|
|
}
|
|
|
#ifdef CONFIG_POSIX_TIMERS
|
|
|
- if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
|
|
|
+ if (resched_timer) {
|
|
|
/*
|
|
|
* Release the siglock to ensure proper locking order
|
|
|
* of timer locks outside of siglocks. Note, we leave
|