Update.
* sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare __timer_helper_thread. Declare __start_helper_thread, __helper_once, and __helper_tid. (struct timer): Remove th and bar field. * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove debugging code. Create only one helper thread. * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill helper thread. * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): Renamed. Define statically. Use thread info from siginfo. (__helper_once): New variable. (__helper_tid): New variable. (__reset_helper_control): New function. (__start_helper_thread): New function.
This commit is contained in:
parent
f07d234541
commit
5f5004df21
|
@ -1,5 +1,20 @@
|
|||
2003-03-27 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare
|
||||
__timer_helper_thread. Declare __start_helper_thread, __helper_once,
|
||||
and __helper_tid.
|
||||
(struct timer): Remove th and bar field.
|
||||
* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove
|
||||
debugging code. Create only one helper thread.
|
||||
* sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill
|
||||
helper thread.
|
||||
* sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread):
|
||||
Renamed. Define statically. Use thread info from siginfo.
|
||||
(__helper_once): New variable.
|
||||
(__helper_tid): New variable.
|
||||
(__reset_helper_control): New function.
|
||||
(__start_helper_thread): New function.
|
||||
|
||||
* pthread_create.c (start_thread): Don't use setjmp inside
|
||||
__builtin_expect to work around gcc bug.
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <sysdep.h>
|
||||
#include <kernel-features.h>
|
||||
#include <internaltypes.h>
|
||||
#include <nptl/pthreadP.h>
|
||||
#include "kernel-posix-timers.h"
|
||||
|
||||
|
||||
|
@ -138,12 +139,16 @@ timer_create (clock_id, evp, timerid)
|
|||
if (__no_posix_timers > 0)
|
||||
# endif
|
||||
{
|
||||
sigset_t ss;
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, TIMER_SIG);
|
||||
pthread_sigmask (SIG_BLOCK, &ss, NULL);
|
||||
struct timer *newp;
|
||||
/* Create the helper thread. */
|
||||
pthread_once (&__helper_once, __start_helper_thread);
|
||||
if (__helper_tid == 0)
|
||||
{
|
||||
/* No resources to start the helper thread. */
|
||||
__set_errno (EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timer *newp;
|
||||
newp = (struct timer *) malloc (sizeof (struct timer));
|
||||
if (newp == NULL)
|
||||
return -1;
|
||||
|
@ -176,57 +181,29 @@ timer_create (clock_id, evp, timerid)
|
|||
(void) pthread_attr_setdetachstate (&newp->attr,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
|
||||
/* Set up the barrier for sychronization. */
|
||||
(void) pthread_barrier_init (&newp->bar, NULL, 2);
|
||||
|
||||
/* 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_setdetachstate (&attr,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
(void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
|
||||
|
||||
/* Create the helper thread for this timer. */
|
||||
int res = pthread_create (&newp->th, &attr,
|
||||
__timer_helper_thread, newp);
|
||||
if (res != 0)
|
||||
goto err_out;
|
||||
|
||||
/* No need for the attribute anymore. */
|
||||
(void) pthread_attr_destroy (&attr);
|
||||
|
||||
/* Create the event structure for the kernel timer. */
|
||||
struct sigevent sev;
|
||||
sev.sigev_value.sival_ptr = newp;
|
||||
sev.sigev_signo = TIMER_SIG;
|
||||
sev.sigev_signo = SIGTIMER;
|
||||
sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
|
||||
/* This is the thread ID of the helper thread. */
|
||||
sev._sigev_un._pad[0] = ((struct pthread *) newp->th)->tid;
|
||||
|
||||
/* Wait until the helper thread is set up. */
|
||||
(void) pthread_barrier_wait (&newp->bar);
|
||||
|
||||
/* No need for the barrier anymore. */
|
||||
(void) pthread_barrier_destroy (&newp->bar);
|
||||
sev._sigev_un._pad[0] = __helper_tid;
|
||||
|
||||
/* Create the timer. */
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
|
||||
&newp->ktimerid);
|
||||
int res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
|
||||
&newp->ktimerid);
|
||||
if (! INTERNAL_SYSCALL_ERROR_P (res, err))
|
||||
{
|
||||
*timerid = (timer_t) newp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Something went wrong. Kill the thread. */
|
||||
pthread_cancel (newp->th);
|
||||
/* Free the resources. */
|
||||
res = INTERNAL_SYSCALL_ERRNO (res, err);
|
||||
err_out:
|
||||
free (newp);
|
||||
__set_errno (res);
|
||||
|
||||
__set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,10 +58,6 @@ timer_delete (timerid)
|
|||
__no_posix_timers = 1;
|
||||
# endif
|
||||
|
||||
/* We have to get rid of the helper thread if we created one. */
|
||||
if (kt->sigev_notify == SIGEV_THREAD)
|
||||
(void) pthread_cancel (kt->th);
|
||||
|
||||
/* Free the memory. */
|
||||
(void) free (kt);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <sysdep.h>
|
||||
#include <kernel-features.h>
|
||||
#include <nptl/pthreadP.h>
|
||||
#include "kernel-posix-timers.h"
|
||||
|
||||
|
||||
|
@ -40,24 +41,14 @@ timer_sigev_thread (void *arg)
|
|||
|
||||
|
||||
/* Helper function to support starting threads for SIGEV_THREAD. */
|
||||
void *
|
||||
attribute_hidden
|
||||
__timer_helper_thread (void *arg)
|
||||
static void *
|
||||
timer_helper_thread (void *arg)
|
||||
{
|
||||
/* Block all signals. */
|
||||
/* Block all signals. We will only wait for the signal the kernel
|
||||
will send. */
|
||||
sigset_t ss;
|
||||
|
||||
sigfillset (&ss);
|
||||
(void) pthread_sigmask (SIG_BLOCK, &ss, NULL);
|
||||
|
||||
struct timer *tk = (struct timer *) arg;
|
||||
|
||||
/* Synchronize with the parent. */
|
||||
(void) pthread_barrier_wait (&tk->bar);
|
||||
|
||||
/* We will only wait for the signal the kernel will send. */
|
||||
sigemptyset (&ss);
|
||||
sigaddset (&ss, TIMER_SIG);
|
||||
sigaddset (&ss, SIGTIMER);
|
||||
|
||||
/* Endless loop of waiting for signals. The loop is only ended when
|
||||
the thread is canceled. */
|
||||
|
@ -65,15 +56,60 @@ __timer_helper_thread (void *arg)
|
|||
{
|
||||
siginfo_t si;
|
||||
|
||||
if (sigwaitinfo (&ss, &si) > 0 && si.si_timerid == tk->ktimerid)
|
||||
if (sigwaitinfo (&ss, &si) > 0 && si.si_code == SI_TIMER)
|
||||
{
|
||||
|
||||
struct timer *tk = (struct timer *) si.si_ptr;
|
||||
|
||||
/* That the signal we are waiting for. */
|
||||
pthread_t th;
|
||||
(void) pthread_create (&th, &tk->attr, timer_sigev_thread, arg);
|
||||
(void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Control variable for helper thread creation. */
|
||||
pthread_once_t __helper_once attribute_hidden;
|
||||
|
||||
|
||||
/* TID of the helper thread. */
|
||||
pid_t __helper_tid attribute_hidden;
|
||||
|
||||
|
||||
/* Reset variables so that after a fork a new helper thread gets started. */
|
||||
static void
|
||||
reset_helper_control (void)
|
||||
{
|
||||
__helper_once = PTHREAD_ONCE_INIT;
|
||||
__helper_tid = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
attribute_hidden
|
||||
__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_STACK_MIN);
|
||||
|
||||
/* Create the helper thread for this timer. */
|
||||
pthread_t th;
|
||||
int 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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __ASSUME_POSIX_TIMERS
|
||||
|
|
Loading…
Reference in New Issue