bool _POSIX_signals_Check_signal( POSIX_API_Control *api, int signo, bool is_global ) { siginfo_t siginfo_struct; sigset_t saved_signals_blocked; if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct, is_global, true ) ) return false; /* * Since we made a union of these, only one test is necessary but this is * safer. */ #if defined(RTEMS_DEBUG) assert( _POSIX_signals_Vectors[ signo ].sa_handler || _POSIX_signals_Vectors[ signo ].sa_sigaction ); #endif /* * Just to prevent sending a signal which is currently being ignored. */ if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN ) return false; /* * Block the signals requested in sa_mask */ saved_signals_blocked = api->signals_blocked; api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask; /* * Here, the signal handler function executes */ switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { case SA_SIGINFO: (*_POSIX_signals_Vectors[ signo ].sa_sigaction)( signo, &siginfo_struct, NULL /* context is undefined per 1003.1b-1993, p. 66 */ ); break; default: (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo ); break; } /* * Restore the previous set of blocked signals */ api->signals_blocked = saved_signals_blocked; return true; }
void *POSIX_Init( void *argument ) { struct sigaction act; siginfo_t info; bool bc; TEST_BEGIN(); act.sa_handler = NULL; act.sa_sigaction = Signal_handler; act.sa_flags = SA_SIGINFO; sigaction( SIGNAL_ONE, &act, NULL ); sigaction( SIGNAL_TWO, &act, NULL ); printf( "Init - _POSIX_signals_Clear_signals when signals pending but\n" "Init - not queued on SA_SIGINFO configured signal.\n" ); /* cheat and put signal directly in */ _POSIX_signals_Pending |= signo_to_mask( SIGUSR1 ); bc = _POSIX_signals_Clear_signals( _Thread_Get_executing()->API_Extensions[ THREAD_API_POSIX ], SIGNAL_ONE, &info, true, /* is_global */ false, /* check_blocked */ true /* do_signals_acquire_release */ ); rtems_test_assert( bc ); TEST_END(); rtems_test_exit(0); return NULL; /* just so the compiler thinks we returned something */ }
int sigtimedwait( const sigset_t *set, siginfo_t *info, const struct timespec *timeout ) { Thread_Control *the_thread; POSIX_API_Control *api; Watchdog_Interval interval; siginfo_t signal_information; siginfo_t *the_info; int signo; ISR_Level level; /* * Error check parameters before disabling interrupts. */ if ( !set ) rtems_set_errno_and_return_minus_one( EINVAL ); /* NOTE: This is very specifically a RELATIVE not ABSOLUTE time * in the Open Group specification. */ interval = 0; if ( timeout ) { if ( !_Timespec_Is_valid( timeout ) ) rtems_set_errno_and_return_minus_one( EINVAL ); interval = _Timespec_To_ticks( timeout ); if ( !interval ) rtems_set_errno_and_return_minus_one( EINVAL ); } /* * Initialize local variables. */ the_info = ( info ) ? info : &signal_information; the_thread = _Thread_Executing; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * What if they are already pending? */ /* API signals pending? */ _ISR_Disable( level ); if ( *set & api->signals_pending ) { /* XXX real info later */ the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending ); _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false ); _ISR_Enable( level ); the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; return the_info->si_signo; } /* Process pending signals? */ if ( *set & _POSIX_signals_Pending ) { signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending ); _POSIX_signals_Clear_signals( api, signo, the_info, true, false ); _ISR_Enable( level ); the_info->si_signo = signo; the_info->si_code = SI_USER; the_info->si_value.sival_int = 0; return signo; } the_info->si_signo = -1; _Thread_Disable_dispatch(); the_thread->Wait.queue = &_POSIX_signals_Wait_queue; the_thread->Wait.return_code = EINTR; the_thread->Wait.option = *set; the_thread->Wait.return_argument = the_info; _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); _ISR_Enable( level ); _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); _Thread_Enable_dispatch(); /* * When the thread is set free by a signal, it is need to eliminate * the signal. */ _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false ); errno = _Thread_Executing->Wait.return_code; return the_info->si_signo; }
bool _POSIX_signals_Check_signal( POSIX_API_Control *api, int signo, bool is_global ) { siginfo_t siginfo_struct; sigset_t saved_signals_blocked; Thread_Wait_information stored_thread_wait_information; if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct, is_global, true ) ) return false; /* * Since we made a union of these, only one test is necessary but this is * safer. */ #if defined(RTEMS_DEBUG) assert( _POSIX_signals_Vectors[ signo ].sa_handler || _POSIX_signals_Vectors[ signo ].sa_sigaction ); #endif /* * Just to prevent sending a signal which is currently being ignored. */ if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN ) return false; /* * Block the signals requested in sa_mask */ saved_signals_blocked = api->signals_blocked; api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask; /* * We have to save the blocking information of the current wait queue * because the signal handler may subsequently go on and put the thread * on a wait queue, for its own purposes. */ memcpy( &stored_thread_wait_information, &_Thread_Executing->Wait, sizeof( Thread_Wait_information )); /* * Here, the signal handler function executes */ switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { case SA_SIGINFO: (*_POSIX_signals_Vectors[ signo ].sa_sigaction)( signo, &siginfo_struct, NULL /* context is undefined per 1003.1b-1993, p. 66 */ ); break; default: (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo ); break; } /* * Restore the blocking information */ memcpy( &_Thread_Executing->Wait, &stored_thread_wait_information, sizeof( Thread_Wait_information )); /* * Restore the previous set of blocked signals */ api->signals_blocked = saved_signals_blocked; return true; }