void _POSIX_signals_Action_handler( Thread_Control *executing, Thread_Action *action, Per_CPU_Control *cpu, ISR_Level level ) { POSIX_API_Control *api; int signo; ISR_lock_Context lock_context; int hold_errno; (void) action; _Thread_Action_release_and_ISR_enable( cpu, level ); api = executing->API_Extensions[ THREAD_API_POSIX ]; /* * We need to ensure that if the signal handler executes a call * which overwrites the unblocking status, we restore it. */ hold_errno = executing->Wait.return_code; /* * api may be NULL in case of a thread close in progress */ if ( !api ) return; /* * If we invoke any user code, there is the possibility that * a new signal has been posted that we should process so we * restart the loop if a signal handler was invoked. * * The first thing done is to check there are any signals to be * processed at all. No point in doing this loop otherwise. */ while (1) { _POSIX_signals_Acquire( &lock_context ); if ( !(~api->signals_blocked & (api->signals_pending | _POSIX_signals_Pending)) ) { _POSIX_signals_Release( &lock_context ); break; } _POSIX_signals_Release( &lock_context ); for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } } executing->Wait.return_code = hold_errno; }
bool _POSIX_signals_Clear_signals( POSIX_API_Control *api, int signo, siginfo_t *info, bool is_global, bool check_blocked, bool do_signals_acquire_release ) { sigset_t mask; sigset_t signals_blocked; ISR_lock_Context lock_context; bool do_callout; POSIX_signals_Siginfo_node *psiginfo; mask = signo_to_mask( signo ); do_callout = false; /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK * insures that no signals are blocked and all are checked. */ if ( check_blocked ) signals_blocked = ~api->signals_blocked; else signals_blocked = SIGNAL_ALL_MASK; /* XXX is this right for siginfo type signals? */ /* XXX are we sure they can be cleared the same way? */ if ( do_signals_acquire_release ) { _POSIX_signals_Acquire( &lock_context ); } if ( is_global ) { if ( mask & (_POSIX_signals_Pending & signals_blocked) ) { if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { psiginfo = (POSIX_signals_Siginfo_node *) _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] ); _POSIX_signals_Clear_process_signals( signo ); /* * It may be impossible to get here with an empty chain * BUT until that is proven we need to be defensive and * protect against it. */ if ( psiginfo ) { *info = psiginfo->Info; _Chain_Append_unprotected( &_POSIX_signals_Inactive_siginfo, &psiginfo->Node ); } else do_callout = false; } _POSIX_signals_Clear_process_signals( signo ); do_callout = true; } } else { if ( mask & (api->signals_pending & signals_blocked) ) { api->signals_pending &= ~mask; do_callout = true; } } if ( do_signals_acquire_release ) { _POSIX_signals_Release( &lock_context ); } return do_callout; }
static void _POSIX_signals_Action_handler( Thread_Control *executing, Thread_Action *action, ISR_lock_Context *lock_context ) { POSIX_API_Control *api; int signo; uint32_t hold_errno; (void) action; _Thread_State_release( executing, lock_context ); api = executing->API_Extensions[ THREAD_API_POSIX ]; /* * We need to ensure that if the signal handler executes a call * which overwrites the unblocking status, we restore it. */ hold_errno = executing->Wait.return_code; /* * api may be NULL in case of a thread close in progress */ if ( !api ) return; /* * In case the executing thread is blocked or about to block on something * that uses the thread wait information, then this is a kernel bug. */ _Assert( ( _Thread_Wait_flags_get( executing ) & ( THREAD_WAIT_STATE_BLOCKED | THREAD_WAIT_STATE_INTEND_TO_BLOCK ) ) == 0 ); /* * If we invoke any user code, there is the possibility that * a new signal has been posted that we should process so we * restart the loop if a signal handler was invoked. * * The first thing done is to check there are any signals to be * processed at all. No point in doing this loop otherwise. */ while (1) { Thread_queue_Context queue_context; _Thread_queue_Context_initialize( &queue_context ); _POSIX_signals_Acquire( &queue_context ); if ( !(api->signals_unblocked & (api->signals_pending | _POSIX_signals_Pending)) ) { _POSIX_signals_Release( &queue_context ); break; } _POSIX_signals_Release( &queue_context ); for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } } executing->Wait.return_code = hold_errno; }