Skip to content

Commit bcb7ee7

Browse files
dvyukovKAGA-KOKO
authored andcommitted
posix-timers: Prefer delivery of signals to the current thread
POSIX timers using the CLOCK_PROCESS_CPUTIME_ID clock prefer the main thread of a thread group for signal delivery. However, this has a significant downside: it requires waking up a potentially idle thread. Instead, prefer to deliver signals to the current thread (in the same thread group) if SIGEV_THREAD_ID is not set by the user. This does not change guaranteed semantics, since POSIX process CPU time timers have never guaranteed that signal delivery is to a specific thread (without SIGEV_THREAD_ID set). The effect is that queueing the signal no longer wakes up potentially idle threads, and the kernel is no longer biased towards delivering the timer signal to any particular thread (which better distributes the timer signals esp. when multiple timers fire concurrently). Suggested-by: Oleg Nesterov <[email protected]> Signed-off-by: Dmitry Vyukov <[email protected]> Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Oleg Nesterov <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent aff6927 commit bcb7ee7

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

kernel/signal.c

+18-3
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,7 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type)
10031003
/*
10041004
* Now find a thread we can wake up to take the signal off the queue.
10051005
*
1006-
* If the main thread wants the signal, it gets first crack.
1007-
* Probably the least surprising to the average bear.
1006+
* Try the suggested task first (may or may not be the main thread).
10081007
*/
10091008
if (wants_signal(sig, p))
10101009
t = p;
@@ -1970,8 +1969,24 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
19701969

19711970
ret = -1;
19721971
rcu_read_lock();
1972+
1973+
/*
1974+
* This function is used by POSIX timers to deliver a timer signal.
1975+
* Where type is PIDTYPE_PID (such as for timers with SIGEV_THREAD_ID
1976+
* set), the signal must be delivered to the specific thread (queues
1977+
* into t->pending).
1978+
*
1979+
* Where type is not PIDTYPE_PID, signals must be delivered to the
1980+
* process. In this case, prefer to deliver to current if it is in
1981+
* the same thread group as the target process, which avoids
1982+
* unnecessarily waking up a potentially idle task.
1983+
*/
19731984
t = pid_task(pid, type);
1974-
if (!t || !likely(lock_task_sighand(t, &flags)))
1985+
if (!t)
1986+
goto ret;
1987+
if (type != PIDTYPE_PID && same_thread_group(t, current))
1988+
t = current;
1989+
if (!likely(lock_task_sighand(t, &flags)))
19751990
goto ret;
19761991

19771992
ret = 1; /* the signal is ignored */

0 commit comments

Comments
 (0)