mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
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:
@ -1,5 +1,20 @@
|
|||||||
2003-03-27 Ulrich Drepper <drepper@redhat.com>
|
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
|
* pthread_create.c (start_thread): Don't use setjmp inside
|
||||||
__builtin_expect to work around gcc bug.
|
__builtin_expect to work around gcc bug.
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
#include <kernel-features.h>
|
#include <kernel-features.h>
|
||||||
#include <internaltypes.h>
|
#include <internaltypes.h>
|
||||||
|
#include <nptl/pthreadP.h>
|
||||||
#include "kernel-posix-timers.h"
|
#include "kernel-posix-timers.h"
|
||||||
|
|
||||||
|
|
||||||
@ -138,12 +139,16 @@ timer_create (clock_id, evp, timerid)
|
|||||||
if (__no_posix_timers > 0)
|
if (__no_posix_timers > 0)
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
sigset_t ss;
|
/* Create the helper thread. */
|
||||||
sigemptyset (&ss);
|
pthread_once (&__helper_once, __start_helper_thread);
|
||||||
sigaddset (&ss, TIMER_SIG);
|
if (__helper_tid == 0)
|
||||||
pthread_sigmask (SIG_BLOCK, &ss, NULL);
|
{
|
||||||
struct timer *newp;
|
/* No resources to start the helper thread. */
|
||||||
|
__set_errno (EAGAIN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timer *newp;
|
||||||
newp = (struct timer *) malloc (sizeof (struct timer));
|
newp = (struct timer *) malloc (sizeof (struct timer));
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@ -176,57 +181,29 @@ timer_create (clock_id, evp, timerid)
|
|||||||
(void) pthread_attr_setdetachstate (&newp->attr,
|
(void) pthread_attr_setdetachstate (&newp->attr,
|
||||||
PTHREAD_CREATE_DETACHED);
|
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. */
|
/* Create the event structure for the kernel timer. */
|
||||||
struct sigevent sev;
|
struct sigevent sev;
|
||||||
sev.sigev_value.sival_ptr = newp;
|
sev.sigev_value.sival_ptr = newp;
|
||||||
sev.sigev_signo = TIMER_SIG;
|
sev.sigev_signo = SIGTIMER;
|
||||||
sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
|
sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
|
||||||
/* This is the thread ID of the helper thread. */
|
/* This is the thread ID of the helper thread. */
|
||||||
sev._sigev_un._pad[0] = ((struct pthread *) newp->th)->tid;
|
sev._sigev_un._pad[0] = __helper_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);
|
|
||||||
|
|
||||||
/* Create the timer. */
|
/* Create the timer. */
|
||||||
INTERNAL_SYSCALL_DECL (err);
|
INTERNAL_SYSCALL_DECL (err);
|
||||||
res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
|
int res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
|
||||||
&newp->ktimerid);
|
&newp->ktimerid);
|
||||||
if (! INTERNAL_SYSCALL_ERROR_P (res, err))
|
if (! INTERNAL_SYSCALL_ERROR_P (res, err))
|
||||||
{
|
{
|
||||||
*timerid = (timer_t) newp;
|
*timerid = (timer_t) newp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Something went wrong. Kill the thread. */
|
|
||||||
pthread_cancel (newp->th);
|
|
||||||
/* Free the resources. */
|
/* Free the resources. */
|
||||||
res = INTERNAL_SYSCALL_ERRNO (res, err);
|
|
||||||
err_out:
|
|
||||||
free (newp);
|
free (newp);
|
||||||
__set_errno (res);
|
|
||||||
|
__set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,10 +58,6 @@ timer_delete (timerid)
|
|||||||
__no_posix_timers = 1;
|
__no_posix_timers = 1;
|
||||||
# endif
|
# 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. */
|
/* Free the memory. */
|
||||||
(void) free (kt);
|
(void) free (kt);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
#include <kernel-features.h>
|
#include <kernel-features.h>
|
||||||
|
#include <nptl/pthreadP.h>
|
||||||
#include "kernel-posix-timers.h"
|
#include "kernel-posix-timers.h"
|
||||||
|
|
||||||
|
|
||||||
@ -40,24 +41,14 @@ timer_sigev_thread (void *arg)
|
|||||||
|
|
||||||
|
|
||||||
/* Helper function to support starting threads for SIGEV_THREAD. */
|
/* Helper function to support starting threads for SIGEV_THREAD. */
|
||||||
void *
|
static void *
|
||||||
attribute_hidden
|
timer_helper_thread (void *arg)
|
||||||
__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;
|
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);
|
sigemptyset (&ss);
|
||||||
sigaddset (&ss, TIMER_SIG);
|
sigaddset (&ss, SIGTIMER);
|
||||||
|
|
||||||
/* Endless loop of waiting for signals. The loop is only ended when
|
/* Endless loop of waiting for signals. The loop is only ended when
|
||||||
the thread is canceled. */
|
the thread is canceled. */
|
||||||
@ -65,15 +56,60 @@ __timer_helper_thread (void *arg)
|
|||||||
{
|
{
|
||||||
siginfo_t si;
|
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. */
|
/* That the signal we are waiting for. */
|
||||||
pthread_t th;
|
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
|
#endif
|
||||||
|
|
||||||
#ifndef __ASSUME_POSIX_TIMERS
|
#ifndef __ASSUME_POSIX_TIMERS
|
||||||
|
Reference in New Issue
Block a user