]> git.ipfire.org Git - thirdparty/glibc.git/commit
linux: Do not spawn a new thread for SIGEV_THREAD (BZ 30558, 27895, 29705, 32833) azanella/bz30558-posix_timer
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 19 Jun 2023 17:11:58 +0000 (14:11 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 4 Apr 2025 17:57:36 +0000 (14:57 -0300)
commit5bc7f090051c094656b71c9cbeb737040c1aedf6
tree5b1b74c3b9dc4987699b416b51d12a2f43be7dfa
parentc8e73a1492b01b9b0c189d6a5c53a5a697827bae
linux: Do not spawn a new thread for SIGEV_THREAD (BZ 30558, 27895, 29705, 32833)

The current timer_create SIGEV_THREAD implementation has some
downsides:

  1. There is no way to report failure at thread creation when a
     timer triggers.  It means that it might occur unreported and with
     missed events depending of the system load.

  2. The backgroup thread also kept in backgroun even when there is no
     more timers, consuming resources and also misleading memory
     profile tools (BZ 29705).

  3. There is a lot of metadata that required to be kept: a control
     variable for helper thread creation, a list of active SIGEV_THREAD
     timers, atfork handlers to cleanup the list.

  4. timer_create does not propagate all thread attributes to the new
     thread (BZ 27895).

  5. Kernel might deliver in-flight events for a timer after it was
     destroyed by timer_delete.  The timer_helper_thread mechanism to
     handle it does not cover all possible issue, which leads to
     callbacks being wrong triggered (BZ 32833).

This new implementation moves the thread creation to timer_create, so
any failure is reported to the caller.  Also, the same thread will
issues the multiple timers, thus there is no unreported missed events.
Also, avoiding parallel timer activation also avoid possible parallel
timer invocation to see the same overrun value.

To implement using SIGTIMER internally as SIGCANCEL, it requires to
mask out SIGCANCEL on thread creation.  It essentially disable async
thread cancellation, but POSIX requires that SIGEV_THREAD is always
created in detached mode and cancelling detached thread s UB (glibc
check the internal tid, but the memory referenced by pthread_t might
not always be valid as the momento of pthread_cancel call).

And to avoid the need to recreate the thread for pthread_exit call
(and having possible unreported missed due failed thread creation),
the SIGEV_THREAD install a cleanup handler that reset all internal
thread state.

It also prevents the re-use issue when a newly-allocated timer has
in-flight event being delivered by the kernel (BZ 32833).

Performance-wise it see it uses less CPU timer for multiple thread
activation, although each thread now requires a sigwaitinfo which
generate more context-switches/page-faults (check comment 7 from
BZ 30558).  I would expect that latency should improve, since it
avoid a thread creation for each timer expiration.

Checked on x86_64-linux-gnu and i686-linux-gnu.
12 files changed:
nptl/descr.h
rt/Makefile
rt/tst-timer-sigmask.c
rt/tst-timer6.c [new file with mode: 0644]
sysdeps/nptl/Makefile
sysdeps/nptl/fork.h
sysdeps/unix/sysv/linux/internal-signals.h
sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h
sysdeps/unix/sysv/linux/kernel-posix-timers.h
sysdeps/unix/sysv/linux/timer_create.c
sysdeps/unix/sysv/linux/timer_delete.c
sysdeps/unix/sysv/linux/timer_routines.c [deleted file]