added queued signals and cleaned up setting of process wide signals so

it occurs in only one place.
This commit is contained in:
Joel Sherrill
1996-06-13 20:46:15 +00:00
parent 25a882a611
commit c53cfd0f2d
2 changed files with 298 additions and 138 deletions

View File

@@ -11,6 +11,7 @@
#include <rtems/score/isr.h> #include <rtems/score/isr.h>
#include <rtems/score/thread.h> #include <rtems/score/thread.h>
#include <rtems/score/tqdata.h> #include <rtems/score/tqdata.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/seterr.h> #include <rtems/posix/seterr.h>
#include <rtems/posix/threadsup.h> #include <rtems/posix/threadsup.h>
#include <rtems/posix/pthread.h> #include <rtems/posix/pthread.h>
@@ -116,7 +117,7 @@ Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
*/ */
/* XXX this routine could probably be cleaned up */ /* XXX this routine could probably be cleaned up */
void _POSIX_signals_Unblock_thread( boolean _POSIX_signals_Unblock_thread(
Thread_Control *the_thread, Thread_Control *the_thread,
int signo, int signo,
siginfo_t *info siginfo_t *info
@@ -150,8 +151,14 @@ void _POSIX_signals_Unblock_thread(
} }
_Thread_queue_Extract_with_proxy( the_thread ); _Thread_queue_Extract_with_proxy( the_thread );
return TRUE;
} }
return;
/*
* This should only be reached via pthread_kill().
*/
return FALSE;
} }
if ( ~api->signals_blocked & mask ) { if ( ~api->signals_blocked & mask ) {
@@ -168,6 +175,7 @@ void _POSIX_signals_Unblock_thread(
} }
} }
} }
return FALSE;
} }
@@ -218,12 +226,12 @@ boolean _POSIX_signals_Check_signal(
boolean is_global boolean is_global
) )
{ {
sigset_t mask; sigset_t mask;
ISR_Level level; ISR_Level level;
boolean do_callout; boolean do_callout;
siginfo_t *siginfo = NULL; /* really needs to be set below */ POSIX_signals_Siginfo_node *psiginfo;
siginfo_t siginfo_struct; siginfo_t siginfo_struct;
sigset_t saved_signals_blocked; sigset_t saved_signals_blocked;
mask = signo_to_mask( signo ); mask = signo_to_mask( signo );
@@ -235,7 +243,21 @@ boolean _POSIX_signals_Check_signal(
_ISR_Disable( level ); _ISR_Disable( level );
if ( is_global ) { if ( is_global ) {
if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) { if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) {
_POSIX_signals_Clear_process_signals( mask ); if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
psiginfo = (POSIX_signals_Siginfo_node *)
_Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
_POSIX_signals_Clear_process_signals( mask );
if ( psiginfo ) {
siginfo_struct = psiginfo->Info;
_Chain_Append_unprotected(
&_POSIX_signals_Inactive_siginfo,
&psiginfo->Node
);
} else
do_callout = FALSE;
} else
_POSIX_signals_Clear_process_signals( mask );
do_callout = TRUE; do_callout = TRUE;
} }
} else { } else {
@@ -273,16 +295,11 @@ boolean _POSIX_signals_Check_signal(
switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
case SA_SIGINFO: case SA_SIGINFO:
assert( 0 ); /* XXX we haven't completely implemented this yet */ assert( is_global );
if ( !is_global ) {
siginfo = &siginfo_struct;
siginfo->si_signo = signo;
siginfo->si_code = SI_USER;
siginfo->si_value.sival_int = 0;
}
(*_POSIX_signals_Vectors[ signo ].sa_sigaction)( (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
signo, signo,
siginfo, &siginfo_struct,
NULL /* context is undefined per 1003.1b-1993, p. 66 */ NULL /* context is undefined per 1003.1b-1993, p. 66 */
); );
break; break;
@@ -371,7 +388,9 @@ void _POSIX_signals_Alarm_TSR(
* _POSIX_signals_Manager_Initialization * _POSIX_signals_Manager_Initialization
*/ */
void _POSIX_signals_Manager_Initialization( void ) void _POSIX_signals_Manager_Initialization(
int maximum_queued_signals
)
{ {
unsigned32 signo; unsigned32 signo;
@@ -420,14 +439,22 @@ void _POSIX_signals_Manager_Initialization( void )
); );
/* XXX status codes */ /* XXX status codes */
/* /*
* XXX Allocate the siginfo pools. * Allocate the siginfo pools.
*/ */
for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
_Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
/* XXX especially the inactive pool */ _Chain_Initialize(
&_POSIX_signals_Inactive_siginfo,
_Workspace_Allocate_or_fatal_error(
maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
),
maximum_queued_signals,
sizeof( POSIX_signals_Siginfo_node )
);
} }
/* /*
@@ -810,20 +837,8 @@ int sigwait(
return errno; return errno;
} }
/* /*PAGE
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 *
*/
int sigqueue(
pid_t pid,
int signo,
const union sigval value
)
{
return POSIX_NOT_IMPLEMENTED();
}
/*
* 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
* *
* NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
@@ -832,23 +847,27 @@ int sigqueue(
#define _POSIX_signals_Is_interested( _api, _mask ) \ #define _POSIX_signals_Is_interested( _api, _mask ) \
( ~(_api)->signals_blocked & (_mask) ) ( ~(_api)->signals_blocked & (_mask) )
int kill( int killinfo(
pid_t pid, pid_t pid,
int sig int sig,
const union sigval *value
) )
{ {
sigset_t mask; sigset_t mask;
POSIX_API_Control *api; POSIX_API_Control *api;
unsigned32 the_class; unsigned32 the_class;
unsigned32 index; unsigned32 index;
unsigned32 maximum; unsigned32 maximum;
Objects_Information *the_info; Objects_Information *the_info;
Objects_Control **object_table; Objects_Control **object_table;
Thread_Control *the_thread; Thread_Control *the_thread;
Thread_Control *interested_thread; Thread_Control *interested_thread;
Priority_Control interested_priority; Priority_Control interested_priority;
Chain_Control *the_chain; Chain_Control *the_chain;
Chain_Node *the_node; Chain_Node *the_node;
siginfo_t siginfo_struct;
siginfo_t *siginfo;
POSIX_signals_Siginfo_node *psiginfo;
/* /*
* Only supported for the "calling process" (i.e. this node). * Only supported for the "calling process" (i.e. this node).
@@ -881,6 +900,19 @@ int kill(
mask = signo_to_mask( sig ); mask = signo_to_mask( sig );
/*
* Build up a siginfo structure
*/
siginfo = &siginfo_struct;
siginfo->si_signo = sig;
siginfo->si_code = SI_USER;
if ( !value ) {
siginfo->si_value.sival_int = 0;
} else {
siginfo->si_value = *value;
}
_Thread_Disable_dispatch(); _Thread_Disable_dispatch();
/* /*
@@ -892,7 +924,6 @@ int kill(
api = the_thread->API_Extensions[ THREAD_API_POSIX ]; api = the_thread->API_Extensions[ THREAD_API_POSIX ];
if ( _POSIX_signals_Is_interested( api, mask ) ) { if ( _POSIX_signals_Is_interested( api, mask ) ) {
_POSIX_signals_Set_process_signals( mask );
goto process_it; goto process_it;
} }
@@ -922,13 +953,6 @@ int kill(
} }
} }
/*
* Since we did not deliver the signal to the current thread or to a
* specific thread via sigwait() we will mark it as pending.
*/
_POSIX_signals_Set_process_signals( mask );
/* /*
* Is any other thread interested? The highest priority interested * Is any other thread interested? The highest priority interested
* thread is selected. In the event of a tie, then the following * thread is selected. In the event of a tie, then the following
@@ -1061,8 +1085,8 @@ int kill(
* + sigaction() which changes the handler to SIG_IGN. * + sigaction() which changes the handler to SIG_IGN.
*/ */
_Thread_Enable_dispatch(); the_thread = NULL;
return 0; goto post_process_signal;
/* /*
* We found a thread which was interested, so now we mark that this * We found a thread which was interested, so now we mark that this
@@ -1072,22 +1096,71 @@ int kill(
process_it: process_it:
api = the_thread->API_Extensions[ THREAD_API_POSIX ];
the_thread->do_post_task_switch_extension = TRUE; the_thread->do_post_task_switch_extension = TRUE;
_POSIX_signals_Unblock_thread( the_thread, sig, NULL ); /*
* Returns TRUE if the signal was synchronously given to a thread
* blocked waiting for the signal.
*/
if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
_Thread_Enable_dispatch();
return 0;
}
post_process_signal:
/*
* We may have woken up a thread but we definitely need to post the
* signal to the process wide information set.
*/
_POSIX_signals_Set_process_signals( mask );
if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
psiginfo = (POSIX_signals_Siginfo_node *)
_Chain_Get( &_POSIX_signals_Inactive_siginfo );
if ( !psiginfo )
set_errno_and_return_minus_one( EAGAIN );
psiginfo->Info = *siginfo;
_Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
}
_Thread_Enable_dispatch(); _Thread_Enable_dispatch();
/* XXX take this out when a little more confident */
/* SIGABRT comes from abort via assert and must work no matter what */
if ( sig == SIGABRT ) {
exit( 1 );
}
return 0; return 0;
} }
/*PAGE
*
* 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
*
* NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
*/
int kill(
pid_t pid,
int sig
)
{
return killinfo( pid, sig, NULL );
}
/*
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
*/
int sigqueue(
pid_t pid,
int signo,
const union sigval value
)
{
return killinfo( pid, signo, &value );
}
/* /*
* 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
*/ */
@@ -1107,6 +1180,13 @@ int pthread_kill(
if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
return 0; return 0;
/*
* RTEMS does not support sending a siginfo signal to a specific thread.
*/
if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
return ENOSYS;
the_thread = _POSIX_Threads_Get( thread, &location ); the_thread = _POSIX_Threads_Get( thread, &location );
switch ( location ) { switch ( location ) {
case OBJECTS_ERROR: case OBJECTS_ERROR:
@@ -1125,7 +1205,7 @@ int pthread_kill(
api->signals_pending |= signo_to_mask( sig ); api->signals_pending |= signo_to_mask( sig );
_POSIX_signals_Unblock_thread( the_thread, sig, NULL ); (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
} }
_Thread_Enable_dispatch(); _Thread_Enable_dispatch();
return 0; return 0;

View File

@@ -11,6 +11,7 @@
#include <rtems/score/isr.h> #include <rtems/score/isr.h>
#include <rtems/score/thread.h> #include <rtems/score/thread.h>
#include <rtems/score/tqdata.h> #include <rtems/score/tqdata.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/seterr.h> #include <rtems/posix/seterr.h>
#include <rtems/posix/threadsup.h> #include <rtems/posix/threadsup.h>
#include <rtems/posix/pthread.h> #include <rtems/posix/pthread.h>
@@ -116,7 +117,7 @@ Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
*/ */
/* XXX this routine could probably be cleaned up */ /* XXX this routine could probably be cleaned up */
void _POSIX_signals_Unblock_thread( boolean _POSIX_signals_Unblock_thread(
Thread_Control *the_thread, Thread_Control *the_thread,
int signo, int signo,
siginfo_t *info siginfo_t *info
@@ -150,8 +151,14 @@ void _POSIX_signals_Unblock_thread(
} }
_Thread_queue_Extract_with_proxy( the_thread ); _Thread_queue_Extract_with_proxy( the_thread );
return TRUE;
} }
return;
/*
* This should only be reached via pthread_kill().
*/
return FALSE;
} }
if ( ~api->signals_blocked & mask ) { if ( ~api->signals_blocked & mask ) {
@@ -168,6 +175,7 @@ void _POSIX_signals_Unblock_thread(
} }
} }
} }
return FALSE;
} }
@@ -218,12 +226,12 @@ boolean _POSIX_signals_Check_signal(
boolean is_global boolean is_global
) )
{ {
sigset_t mask; sigset_t mask;
ISR_Level level; ISR_Level level;
boolean do_callout; boolean do_callout;
siginfo_t *siginfo = NULL; /* really needs to be set below */ POSIX_signals_Siginfo_node *psiginfo;
siginfo_t siginfo_struct; siginfo_t siginfo_struct;
sigset_t saved_signals_blocked; sigset_t saved_signals_blocked;
mask = signo_to_mask( signo ); mask = signo_to_mask( signo );
@@ -235,7 +243,21 @@ boolean _POSIX_signals_Check_signal(
_ISR_Disable( level ); _ISR_Disable( level );
if ( is_global ) { if ( is_global ) {
if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) { if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) {
_POSIX_signals_Clear_process_signals( mask ); if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
psiginfo = (POSIX_signals_Siginfo_node *)
_Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
_POSIX_signals_Clear_process_signals( mask );
if ( psiginfo ) {
siginfo_struct = psiginfo->Info;
_Chain_Append_unprotected(
&_POSIX_signals_Inactive_siginfo,
&psiginfo->Node
);
} else
do_callout = FALSE;
} else
_POSIX_signals_Clear_process_signals( mask );
do_callout = TRUE; do_callout = TRUE;
} }
} else { } else {
@@ -273,16 +295,11 @@ boolean _POSIX_signals_Check_signal(
switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
case SA_SIGINFO: case SA_SIGINFO:
assert( 0 ); /* XXX we haven't completely implemented this yet */ assert( is_global );
if ( !is_global ) {
siginfo = &siginfo_struct;
siginfo->si_signo = signo;
siginfo->si_code = SI_USER;
siginfo->si_value.sival_int = 0;
}
(*_POSIX_signals_Vectors[ signo ].sa_sigaction)( (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
signo, signo,
siginfo, &siginfo_struct,
NULL /* context is undefined per 1003.1b-1993, p. 66 */ NULL /* context is undefined per 1003.1b-1993, p. 66 */
); );
break; break;
@@ -371,7 +388,9 @@ void _POSIX_signals_Alarm_TSR(
* _POSIX_signals_Manager_Initialization * _POSIX_signals_Manager_Initialization
*/ */
void _POSIX_signals_Manager_Initialization( void ) void _POSIX_signals_Manager_Initialization(
int maximum_queued_signals
)
{ {
unsigned32 signo; unsigned32 signo;
@@ -420,14 +439,22 @@ void _POSIX_signals_Manager_Initialization( void )
); );
/* XXX status codes */ /* XXX status codes */
/* /*
* XXX Allocate the siginfo pools. * Allocate the siginfo pools.
*/ */
for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
_Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
/* XXX especially the inactive pool */ _Chain_Initialize(
&_POSIX_signals_Inactive_siginfo,
_Workspace_Allocate_or_fatal_error(
maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
),
maximum_queued_signals,
sizeof( POSIX_signals_Siginfo_node )
);
} }
/* /*
@@ -810,20 +837,8 @@ int sigwait(
return errno; return errno;
} }
/* /*PAGE
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 *
*/
int sigqueue(
pid_t pid,
int signo,
const union sigval value
)
{
return POSIX_NOT_IMPLEMENTED();
}
/*
* 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
* *
* NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
@@ -832,23 +847,27 @@ int sigqueue(
#define _POSIX_signals_Is_interested( _api, _mask ) \ #define _POSIX_signals_Is_interested( _api, _mask ) \
( ~(_api)->signals_blocked & (_mask) ) ( ~(_api)->signals_blocked & (_mask) )
int kill( int killinfo(
pid_t pid, pid_t pid,
int sig int sig,
const union sigval *value
) )
{ {
sigset_t mask; sigset_t mask;
POSIX_API_Control *api; POSIX_API_Control *api;
unsigned32 the_class; unsigned32 the_class;
unsigned32 index; unsigned32 index;
unsigned32 maximum; unsigned32 maximum;
Objects_Information *the_info; Objects_Information *the_info;
Objects_Control **object_table; Objects_Control **object_table;
Thread_Control *the_thread; Thread_Control *the_thread;
Thread_Control *interested_thread; Thread_Control *interested_thread;
Priority_Control interested_priority; Priority_Control interested_priority;
Chain_Control *the_chain; Chain_Control *the_chain;
Chain_Node *the_node; Chain_Node *the_node;
siginfo_t siginfo_struct;
siginfo_t *siginfo;
POSIX_signals_Siginfo_node *psiginfo;
/* /*
* Only supported for the "calling process" (i.e. this node). * Only supported for the "calling process" (i.e. this node).
@@ -881,6 +900,19 @@ int kill(
mask = signo_to_mask( sig ); mask = signo_to_mask( sig );
/*
* Build up a siginfo structure
*/
siginfo = &siginfo_struct;
siginfo->si_signo = sig;
siginfo->si_code = SI_USER;
if ( !value ) {
siginfo->si_value.sival_int = 0;
} else {
siginfo->si_value = *value;
}
_Thread_Disable_dispatch(); _Thread_Disable_dispatch();
/* /*
@@ -892,7 +924,6 @@ int kill(
api = the_thread->API_Extensions[ THREAD_API_POSIX ]; api = the_thread->API_Extensions[ THREAD_API_POSIX ];
if ( _POSIX_signals_Is_interested( api, mask ) ) { if ( _POSIX_signals_Is_interested( api, mask ) ) {
_POSIX_signals_Set_process_signals( mask );
goto process_it; goto process_it;
} }
@@ -922,13 +953,6 @@ int kill(
} }
} }
/*
* Since we did not deliver the signal to the current thread or to a
* specific thread via sigwait() we will mark it as pending.
*/
_POSIX_signals_Set_process_signals( mask );
/* /*
* Is any other thread interested? The highest priority interested * Is any other thread interested? The highest priority interested
* thread is selected. In the event of a tie, then the following * thread is selected. In the event of a tie, then the following
@@ -1061,8 +1085,8 @@ int kill(
* + sigaction() which changes the handler to SIG_IGN. * + sigaction() which changes the handler to SIG_IGN.
*/ */
_Thread_Enable_dispatch(); the_thread = NULL;
return 0; goto post_process_signal;
/* /*
* We found a thread which was interested, so now we mark that this * We found a thread which was interested, so now we mark that this
@@ -1072,22 +1096,71 @@ int kill(
process_it: process_it:
api = the_thread->API_Extensions[ THREAD_API_POSIX ];
the_thread->do_post_task_switch_extension = TRUE; the_thread->do_post_task_switch_extension = TRUE;
_POSIX_signals_Unblock_thread( the_thread, sig, NULL ); /*
* Returns TRUE if the signal was synchronously given to a thread
* blocked waiting for the signal.
*/
if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
_Thread_Enable_dispatch();
return 0;
}
post_process_signal:
/*
* We may have woken up a thread but we definitely need to post the
* signal to the process wide information set.
*/
_POSIX_signals_Set_process_signals( mask );
if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
psiginfo = (POSIX_signals_Siginfo_node *)
_Chain_Get( &_POSIX_signals_Inactive_siginfo );
if ( !psiginfo )
set_errno_and_return_minus_one( EAGAIN );
psiginfo->Info = *siginfo;
_Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
}
_Thread_Enable_dispatch(); _Thread_Enable_dispatch();
/* XXX take this out when a little more confident */
/* SIGABRT comes from abort via assert and must work no matter what */
if ( sig == SIGABRT ) {
exit( 1 );
}
return 0; return 0;
} }
/*PAGE
*
* 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
*
* NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
*/
int kill(
pid_t pid,
int sig
)
{
return killinfo( pid, sig, NULL );
}
/*
* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
*/
int sigqueue(
pid_t pid,
int signo,
const union sigval value
)
{
return killinfo( pid, signo, &value );
}
/* /*
* 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
*/ */
@@ -1107,6 +1180,13 @@ int pthread_kill(
if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
return 0; return 0;
/*
* RTEMS does not support sending a siginfo signal to a specific thread.
*/
if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
return ENOSYS;
the_thread = _POSIX_Threads_Get( thread, &location ); the_thread = _POSIX_Threads_Get( thread, &location );
switch ( location ) { switch ( location ) {
case OBJECTS_ERROR: case OBJECTS_ERROR:
@@ -1125,7 +1205,7 @@ int pthread_kill(
api->signals_pending |= signo_to_mask( sig ); api->signals_pending |= signo_to_mask( sig );
_POSIX_signals_Unblock_thread( the_thread, sig, NULL ); (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
} }
_Thread_Enable_dispatch(); _Thread_Enable_dispatch();
return 0; return 0;