aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2021-06-25 10:51:31 +0200
committerFlorian Weimer <fweimer@redhat.com>2021-06-25 12:21:12 +0200
commit2c16cb88a6e5ace0fb7cedca86860ea7bde522a7 (patch)
tree8e7aa16a33590ccd27050ef3d3b00607b7f15751 /sysdeps
parent1a5a653be2f95d4d9485d08672dc5083c74c39d8 (diff)
downloadglibc-2c16cb88a6e5ace0fb7cedca86860ea7bde522a7.tar
glibc-2c16cb88a6e5ace0fb7cedca86860ea7bde522a7.tar.gz
glibc-2c16cb88a6e5ace0fb7cedca86860ea7bde522a7.tar.bz2
glibc-2c16cb88a6e5ace0fb7cedca86860ea7bde522a7.zip
Linux: Move timer helper routines from librt to libc
This adds several temporary GLIBC_PRIVATE exports. The symbol names are changed so that they all start with __timer_. It is now possible to invoke the fork handler directly, so pthread_atfork is no longer necessary. The associated error cannot happen anymore, and cancellation handling can be removed from the helper thread routine. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/nptl/Makefile2
-rw-r--r--sysdeps/nptl/fork.h2
-rw-r--r--sysdeps/unix/sysv/linux/Versions5
-rw-r--r--sysdeps/unix/sysv/linux/kernel-posix-timers.h22
-rw-r--r--sysdeps/unix/sysv/linux/timer_create.c14
-rw-r--r--sysdeps/unix/sysv/linux/timer_delete.c10
-rw-r--r--sysdeps/unix/sysv/linux/timer_routines.c59
7 files changed, 64 insertions, 50 deletions
diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile
index 0707f130eb..27aa41af3c 100644
--- a/sysdeps/nptl/Makefile
+++ b/sysdeps/nptl/Makefile
@@ -17,7 +17,7 @@
# <https://www.gnu.org/licenses/>.
ifeq ($(subdir),rt)
-librt-sysdep_routines += timer_routines
+sysdep_routines += timer_routines
tests += tst-mqueue8x
CFLAGS-tst-mqueue8x.c += -fexceptions
diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h
index 1fc3a83bd3..8278ab6d11 100644
--- a/sysdeps/nptl/fork.h
+++ b/sysdeps/nptl/fork.h
@@ -20,6 +20,7 @@
#define _FORK_H
#include <assert.h>
+#include <kernel-posix-timers.h>
#include <ldsodefs.h>
#include <list.h>
#include <mqueue.h>
@@ -44,6 +45,7 @@ fork_system_setup_after_fork (void)
__default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
call_function_static_weak (__mq_notify_fork_subprocess);
+ call_function_static_weak (__timer_fork_subprocess);
}
/* In case of a fork() call the memory allocation in the child will be
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 051ecf9390..47d4357b9f 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -282,6 +282,11 @@ libc {
__pread64_nocancel;
__close_nocancel;
__sigtimedwait;
+ __timer_active_sigev_thread;
+ __timer_active_sigev_thread_lock;
+ __timer_helper_once;
+ __timer_helper_tid;
+ __timer_start_helper_thread;
# functions used by nscd
__netlink_assert_response;
}
diff --git a/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/sysdeps/unix/sysv/linux/kernel-posix-timers.h
index 959a81a4d2..17fc32d48f 100644
--- a/sysdeps/unix/sysv/linux/kernel-posix-timers.h
+++ b/sysdeps/unix/sysv/linux/kernel-posix-timers.h
@@ -26,19 +26,27 @@
extern int __no_posix_timers attribute_hidden;
/* Callback to start helper thread. */
-extern void __start_helper_thread (void) attribute_hidden;
+extern void __timer_start_helper_thread (void);
+libc_hidden_proto (__timer_start_helper_thread)
/* Control variable for helper thread creation. */
-extern pthread_once_t __helper_once attribute_hidden;
+extern pthread_once_t __timer_helper_once;
+libc_hidden_proto (__timer_helper_once)
+
+/* Called from fork so that the new subprocess re-creates the
+ notification thread if necessary. */
+void __timer_fork_subprocess (void) attribute_hidden;
/* TID of the helper thread. */
-extern pid_t __helper_tid attribute_hidden;
+extern pid_t __timer_helper_tid;
+libc_hidden_proto (__timer_helper_tid)
/* List of active SIGEV_THREAD timers. */
-extern struct timer *__active_timer_sigev_thread attribute_hidden;
-/* Lock for the __active_timer_sigev_thread. */
-extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden;
-
+extern struct timer *__timer_active_sigev_thread;
+libc_hidden_proto (__timer_active_sigev_thread)
+/* Lock for __timer_active_sigev_thread. */
+extern pthread_mutex_t __timer_active_sigev_thread_lock;
+libc_hidden_proto (__timer_active_sigev_thread_lock)
/* Type of timers in the kernel. */
typedef int kernel_timer_t;
diff --git a/sysdeps/unix/sysv/linux/timer_create.c b/sysdeps/unix/sysv/linux/timer_create.c
index 1ea0086487..b21b0ca949 100644
--- a/sysdeps/unix/sysv/linux/timer_create.c
+++ b/sysdeps/unix/sysv/linux/timer_create.c
@@ -74,8 +74,8 @@ timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
else
{
/* Create the helper thread. */
- pthread_once (&__helper_once, __start_helper_thread);
- if (__helper_tid == 0)
+ pthread_once (&__timer_helper_once, __timer_start_helper_thread);
+ if (__timer_helper_tid == 0)
{
/* No resources to start the helper thread. */
__set_errno (EAGAIN);
@@ -118,7 +118,7 @@ timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
{ .sigev_value.sival_ptr = newp,
.sigev_signo = SIGTIMER,
.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID,
- ._sigev_un = { ._pad = { [0] = __helper_tid } } };
+ ._sigev_un = { ._pad = { [0] = __timer_helper_tid } } };
/* Create the timer. */
int res;
@@ -132,10 +132,10 @@ timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
}
/* Add to the queue of active timers with thread delivery. */
- pthread_mutex_lock (&__active_timer_sigev_thread_lock);
- newp->next = __active_timer_sigev_thread;
- __active_timer_sigev_thread = newp;
- pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+ pthread_mutex_lock (&__timer_active_sigev_thread_lock);
+ newp->next = __timer_active_sigev_thread;
+ __timer_active_sigev_thread = newp;
+ pthread_mutex_unlock (&__timer_active_sigev_thread_lock);
*timerid = timer_to_timerid (newp);
}
diff --git a/sysdeps/unix/sysv/linux/timer_delete.c b/sysdeps/unix/sysv/linux/timer_delete.c
index 50aac8fc27..a7a183591e 100644
--- a/sysdeps/unix/sysv/linux/timer_delete.c
+++ b/sysdeps/unix/sysv/linux/timer_delete.c
@@ -42,12 +42,12 @@ timer_delete (timer_t timerid)
struct timer *kt = timerid_to_timer (timerid);
/* Remove the timer from the list. */
- pthread_mutex_lock (&__active_timer_sigev_thread_lock);
- if (__active_timer_sigev_thread == kt)
- __active_timer_sigev_thread = kt->next;
+ pthread_mutex_lock (&__timer_active_sigev_thread_lock);
+ if (__timer_active_sigev_thread == kt)
+ __timer_active_sigev_thread = kt->next;
else
{
- struct timer *prevp = __active_timer_sigev_thread;
+ struct timer *prevp = __timer_active_sigev_thread;
while (prevp->next != NULL)
if (prevp->next == kt)
{
@@ -57,7 +57,7 @@ timer_delete (timer_t timerid)
else
prevp = prevp->next;
}
- pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+ pthread_mutex_unlock (&__timer_active_sigev_thread_lock);
free (kt);
}
diff --git a/sysdeps/unix/sysv/linux/timer_routines.c b/sysdeps/unix/sysv/linux/timer_routines.c
index 4098da8a5f..e0bb169370 100644
--- a/sysdeps/unix/sysv/linux/timer_routines.c
+++ b/sysdeps/unix/sysv/linux/timer_routines.c
@@ -26,10 +26,13 @@
/* List of active SIGEV_THREAD timers. */
-struct timer *__active_timer_sigev_thread;
-/* Lock for the __active_timer_sigev_thread. */
-pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+struct timer *__timer_active_sigev_thread __attribute__ ((nocommon));
+libc_hidden_data_def (__timer_active_sigev_thread)
+/* Lock for _timer_active_sigev_thread. */
+pthread_mutex_t __timer_active_sigev_thread_lock __attribute__ ((nocommon))
+ = PTHREAD_MUTEX_INITIALIZER;
+libc_hidden_data_def (__timer_active_sigev_thread_lock)
struct thread_start_data
{
@@ -59,7 +62,7 @@ timer_sigev_thread (void *arg)
/* Helper function to support starting threads for SIGEV_THREAD. */
-static void *
+static _Noreturn void *
timer_helper_thread (void *arg)
{
/* Endless loop of waiting for signals. The loop is only ended when
@@ -68,16 +71,16 @@ timer_helper_thread (void *arg)
{
siginfo_t si;
- while (sigwaitinfo (&sigtimer_set, &si) < 0);
+ while (__sigwaitinfo (&sigtimer_set, &si) < 0);
if (si.si_code == SI_TIMER)
{
struct timer *tk = (struct timer *) si.si_ptr;
/* Check the timer is still used and will not go away
while we are reading the values here. */
- pthread_mutex_lock (&__active_timer_sigev_thread_lock);
+ __pthread_mutex_lock (&__timer_active_sigev_thread_lock);
- struct timer *runp = __active_timer_sigev_thread;
+ struct timer *runp = __timer_active_sigev_thread;
while (runp != NULL)
if (runp == tk)
break;
@@ -96,45 +99,44 @@ timer_helper_thread (void *arg)
td->sival = tk->sival;
pthread_t th;
- pthread_create (&th, &tk->attr, timer_sigev_thread, td);
+ __pthread_create (&th, &tk->attr, timer_sigev_thread, td);
}
}
- pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+ __pthread_mutex_unlock (&__timer_active_sigev_thread_lock);
}
- else if (si.si_code == SI_TKILL)
- /* The thread is canceled. */
- pthread_exit (NULL);
}
}
/* Control variable for helper thread creation. */
-pthread_once_t __helper_once attribute_hidden;
+pthread_once_t __timer_helper_once __attribute__ ((nocommon))
+ = PTHREAD_ONCE_INIT;
+libc_hidden_data_def (__timer_helper_once)
/* TID of the helper thread. */
-pid_t __helper_tid attribute_hidden;
+pid_t __timer_helper_tid __attribute__ ((nocommon));
+libc_hidden_data_def (__timer_helper_tid)
/* Reset variables so that after a fork a new helper thread gets started. */
-static void
-reset_helper_control (void)
+void
+__timer_fork_subprocess (void)
{
- __helper_once = PTHREAD_ONCE_INIT;
- __helper_tid = 0;
+ __timer_helper_once = PTHREAD_ONCE_INIT;
+ __timer_helper_tid = 0;
}
void
-attribute_hidden
-__start_helper_thread (void)
+__timer_start_helper_thread (void)
{
/* The helper thread needs only very little resources
and should go away automatically when canceled. */
pthread_attr_t attr;
- (void) pthread_attr_init (&attr);
- (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr));
+ __pthread_attr_init (&attr);
+ __pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr));
/* Block all signals in the helper thread but SIGSETXID. */
sigset_t ss;
@@ -143,21 +145,18 @@ __start_helper_thread (void)
int res = __pthread_attr_setsigmask_internal (&attr, &ss);
if (res != 0)
{
- pthread_attr_destroy (&attr);
+ __pthread_attr_destroy (&attr);
return;
}
/* Create the helper thread for this timer. */
pthread_t th;
- res = pthread_create (&th, &attr, timer_helper_thread, NULL);
+ res = __pthread_create (&th, &attr, timer_helper_thread, NULL);
if (res == 0)
/* We managed to start the helper thread. */
- __helper_tid = ((struct pthread *) th)->tid;
+ __timer_helper_tid = ((struct pthread *) th)->tid;
/* No need for the attribute anymore. */
- (void) pthread_attr_destroy (&attr);
-
- /* We have to make sure that after fork()ing a new helper thread can
- be created. */
- pthread_atfork (NULL, NULL, reset_helper_control);
+ __pthread_attr_destroy (&attr);
}
+libc_hidden_def (__timer_start_helper_thread)