@ -21,22 +21,38 @@ weak_alias(dummy_1, __pthread_tsd_run_dtors);
static void cleanup_fromsig ( void * p )
{
pthread_t self = __pthread_self ( ) ;
__pthread_tsd_run_dtors ( self ) ;
self - > cancel = 0 ;
self - > cancelbuf = 0 ;
__pthread_tsd_run_dtors ( self ) ;
self - > canceldisable = 0 ;
self - > cancelasync = 0 ;
self - > unblock_cancel = 0 ;
longjmp ( p , 1 ) ;
}
void __sig timer_handler( pthread_t self )
static void timer_handler ( int sig , siginfo_t * si , void * ctx )
{
pthread_t self = __pthread_self ( ) ;
jmp_buf jb ;
void ( * notify ) ( union sigval ) = ( void ( * ) ( union sigval ) ) self - > start ;
union sigval val = { . sival_ptr = self - > start_arg } ;
if ( setjmp ( jb ) ) return ;
pthread_cleanup_push ( cleanup_fromsig , jb ) ;
notify ( val ) ;
pthread_cleanup_pop ( 0 ) ;
if ( ! setjmp ( jb ) & & si - > si_code = = SI_TIMER ) {
pthread_cleanup_push ( cleanup_fromsig , jb ) ;
notify ( val ) ;
pthread_cleanup_pop ( 0 ) ;
}
}
static void install_handler ( )
{
struct sigaction sa = {
. sa_sigaction = timer_handler ,
. sa_flags = SA_SIGINFO | SA_RESTART
} ;
__libc_sigaction ( SIGTIMER , & sa , 0 ) ;
sigaddset ( & sa . sa_mask , SIGTIMER ) ;
__libc_sigprocmask ( SIG_UNBLOCK , & sa . sa_mask , 0 ) ;
}
static void * start ( void * arg )
@ -58,6 +74,7 @@ static void *start(void *arg)
int timer_create ( clockid_t clk , struct sigevent * evp , timer_t * res )
{
static pthread_once_t once = PTHREAD_ONCE_INIT ;
pthread_t td ;
pthread_attr_t attr ;
int r ;
@ -80,6 +97,7 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
* res = ( void * ) timerid ;
break ;
case SIGEV_THREAD :
pthread_once ( & once , install_handler ) ;
if ( evp - > sigev_notify_attributes )
attr = * evp - > sigev_notify_attributes ;
else
@ -93,7 +111,7 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
return - 1 ;
}
ksev . sigev_value . sival_ptr = 0 ;
ksev . sigev_signo = SIGCANCEL ;
ksev . sigev_signo = SIGTIMER ;
ksev . sigev_notify = 4 ; /* SIGEV_THREAD_ID */
ksev . sigev_tid = td - > tid ;
r = syscall ( SYS_timer_create , clk , & ksev , & timerid ) ;