/* * $Id$ */ #include #include #include #include #include #include #include #include #include /* * Currently 32 signals numbered 1-32 are defined */ #define SIGNAL_EMPTY_MASK 0x00000000 #define SIGNAL_ALL_MASK 0xffffffff #define signo_to_mask( _sig ) (1 << ((_sig) - 1)) #define is_valid_signo( _sig ) \ ((_sig) >= 1 && (_sig) <= 32 ) /*** PROCESS WIDE STUFF ****/ sigset_t _POSIX_signals_Pending; sigset_t _POSIX_signals_Ignored; #define _POSIX_signals_Abormal_termination_handler NULL #define _POSIX_signals_Stop_handler NULL #define _POSIX_signals_Continue_handler NULL #define SIGACTION_TERMINATE \ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} } #define SIGACTION_IGNORE \ { 0, SIGNAL_ALL_MASK, {SIG_IGN} } #define SIGACTION_STOP \ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} } #define SIGACTION_CONTINUE \ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} } #define SIG_ARRAY_MAX (SIGRTMAX + 1) struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { /* NO SIGNAL 0 */ SIGACTION_IGNORE, /* SIGABRT */ SIGACTION_TERMINATE, /* SIGALRM */ SIGACTION_TERMINATE, /* SIGFPE */ SIGACTION_TERMINATE, /* SIGHUP */ SIGACTION_TERMINATE, /* SIGILL */ SIGACTION_TERMINATE, /* SIGINT */ SIGACTION_TERMINATE, /* SIGKILL */ SIGACTION_TERMINATE, /* SIGPIPE */ SIGACTION_TERMINATE, /* SIGQUIT */ SIGACTION_TERMINATE, /* SIGSEGV */ SIGACTION_TERMINATE, /* SIGTERM */ SIGACTION_TERMINATE, /* SIGUSR1 */ SIGACTION_TERMINATE, /* SIGUSR2 */ SIGACTION_TERMINATE, /* SIGCHLD */ SIGACTION_IGNORE, /* SIGCONT */ SIGACTION_CONTINUE, /* SIGSTOP */ SIGACTION_STOP, /* SIGTSTP */ SIGACTION_STOP, /* SIGTTIN */ SIGACTION_STOP, /* SIGTTOU */ SIGACTION_STOP, /* SIGBUS */ SIGACTION_TERMINATE, /* SIGRTMIN 21 */ SIGACTION_IGNORE, /* SIGRT 22 */ SIGACTION_IGNORE, /* SIGRT 23 */ SIGACTION_IGNORE, /* SIGRT 24 */ SIGACTION_IGNORE, /* SIGRT 25 */ SIGACTION_IGNORE, /* SIGRT 26 */ SIGACTION_IGNORE, /* SIGRT 27 */ SIGACTION_IGNORE, /* SIGRT 28 */ SIGACTION_IGNORE, /* SIGRT 29 */ SIGACTION_IGNORE, /* SIGRT 30 */ SIGACTION_IGNORE, /* SIGRT 31 */ SIGACTION_IGNORE, /* SIGRTMAX 32 */ SIGACTION_IGNORE }; struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; Watchdog_Control _POSIX_signals_Alarm_timer; typedef struct { Chain_Node Node; siginfo_t Info; } POSIX_signals_Siginfo_node; Chain_Control _POSIX_signals_Inactive_siginfo; Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; /*PAGE * * XXX */ boolean _POSIX_signals_Check_signal( POSIX_API_Control *api, int signo, boolean is_global ) { sigset_t mask; ISR_Level level; boolean do_callout; siginfo_t *siginfo = NULL; /* really needs to be set below */ siginfo_t siginfo_struct; mask = signo_to_mask( signo ); do_callout = FALSE; _ISR_Disable( level ); if ( is_global ) { ; /* XXX check right place for thread versus global */ } else { if ( mask & (api->signals_pending & ~api->signals_blocked ) ) { api->signals_pending &= ~mask; do_callout = TRUE; } } _ISR_Enable( level ); if ( !do_callout ) return FALSE; switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { case SA_SIGINFO: assert( 0 ); /* XXX we haven't completely implemented this yet */ 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)( signo, siginfo, NULL /* context is undefined per 1003.1b-1993, p. 66 */ ); break; default: (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo ); break; } return TRUE; } void _POSIX_signals_Run_Them( Thread_Control *the_thread ) { POSIX_API_Control *api; int signo; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * If we invoke any user code, there is the possibility that * a new signal has been posted that we should process. */ /* XXX somewhere we need to see if all pending signals are gone and clear */ /* XXX do_post_switch_extension */ restart: for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { if ( _POSIX_signals_Check_signal( api, signo, FALSE ) ) goto restart; if ( _POSIX_signals_Check_signal( api, signo, TRUE ) ) goto restart; } for ( signo = SIGABRT ; signo <= SIGBUS ; signo++ ) { if ( _POSIX_signals_Check_signal( api, signo, FALSE ) ) goto restart; if ( _POSIX_signals_Check_signal( api, signo, TRUE ) ) goto restart; } } /*PAGE * * _POSIX_signals_Alarm_TSR */ void _POSIX_signals_Alarm_TSR( Objects_Id id, void *argument ) { kill( getpid(), SIGALRM ); } /*PAGE * * _POSIX_signals_Manager_Initialization */ void _POSIX_signals_Manager_Initialization( void ) { unsigned32 signo; /* * Insure we have the same number of vectors and default vector entries */ assert( sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors) ); memcpy( _POSIX_signals_Vectors, _POSIX_signals_Default_vectors, sizeof( _POSIX_signals_Vectors ) ); /* * Initialize the set of pending signals for the entire process */ sigemptyset( &_POSIX_signals_Pending ); /* * Calculate the mask for the set of signals which are being ignored. */ sigemptyset( &_POSIX_signals_Ignored ); for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) if ( _POSIX_signals_Default_vectors[ signo ].sa_handler == SIG_IGN ) sigaddset( &_POSIX_signals_Ignored, signo ); /* * Initialize the timer used to implement alarm(). */ _Watchdog_Initialize( &_POSIX_signals_Alarm_timer, _POSIX_signals_Alarm_TSR, 0, NULL ); /* * XXX Allocate the siginfo pools. */ for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); /* XXX especially the inactive pool */ } /* * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 */ int sigemptyset( sigset_t *set ) { if ( !set ) set_errno_and_return_minus_one( EFAULT ); *set = 0; return 0; } /* * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 */ int sigfillset( sigset_t *set ) { if ( !set ) set_errno_and_return_minus_one( EFAULT ); *set = SIGNAL_ALL_MASK; return 0; } /* * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 */ int sigaddset( sigset_t *set, int signo ) { if ( !set ) set_errno_and_return_minus_one( EFAULT ); if ( !is_valid_signo(signo) ) set_errno_and_return_minus_one( EINVAL ); *set |= signo_to_mask(signo); return 0; } /* * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 */ int sigdelset( sigset_t *set, int signo ) { if ( !set ) set_errno_and_return_minus_one( EFAULT ); if ( !is_valid_signo(signo) ) set_errno_and_return_minus_one( EINVAL ); *set &= ~signo_to_mask(signo); return 0; } /* * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 */ int sigismember( const sigset_t *set, int signo ) { if ( !set ) set_errno_and_return_minus_one( EFAULT ); if ( !is_valid_signo(signo) ) set_errno_and_return_minus_one( EINVAL ); if ( *set & signo_to_mask(signo) ) return 1; return 0; } /* * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70 */ int sigaction( int sig, const struct sigaction *act, struct sigaction *oact ) { if ( !act ) set_errno_and_return_minus_one( EFAULT ); if ( !is_valid_signo(sig) ) set_errno_and_return_minus_one( EINVAL ); if ( oact ) *oact = _POSIX_signals_Vectors[ sig ]; /* XXX need to interpret some stuff here */ /* XXX some signals cannot be ignored */ _POSIX_signals_Vectors[ sig ] = *act; return POSIX_NOT_IMPLEMENTED(); } /* * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 * * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). * */ int sigprocmask( int how, const sigset_t *set, sigset_t *oset ) { /* * P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask. */ return pthread_sigmask( how, set, oset ); } /* * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 * * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). */ int pthread_sigmask( int how, const sigset_t *set, sigset_t *oset ) { POSIX_API_Control *api; boolean evaluate_signals; /* XXX some signals can not be ignored */ if ( !set && !oset ) set_errno_and_return_minus_one( EFAULT ); api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; if ( oset ) *oset = api->signals_blocked; if ( !set ) set_errno_and_return_minus_one( EFAULT ); evaluate_signals = TRUE; switch ( how ) { case SIG_BLOCK: api->signals_blocked |= *set; evaluate_signals = FALSE; break; case SIG_UNBLOCK: api->signals_blocked &= ~*set; break; case SIG_SETMASK: api->signals_blocked = *set; break; default: set_errno_and_return_minus_one( EINVAL ); } /* XXX are there critical section problems here? */ /* XXX evaluate the new set */ if ( evaluate_signals == TRUE ) { if ( ~api->signals_blocked & (api->signals_pending | _POSIX_signals_Pending) ) { api->signals_global_pending &= _POSIX_signals_Pending; _Thread_Executing->do_post_task_switch_extension = TRUE; _Thread_Dispatch(); } } return 0; } /* * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75 */ int sigpending( sigset_t *set ) { POSIX_API_Control *api; if ( !set ) set_errno_and_return_minus_one( EFAULT ); api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; *set = api->signals_pending | _POSIX_signals_Pending; return 0; } /* * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75 */ int sigsuspend( const sigset_t *sigmask ) { return POSIX_NOT_IMPLEMENTED(); } /* * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 * * NOTE: P1003.1c/D10, p. 39 adds sigwait(). */ int sigwaitinfo( const sigset_t *set, siginfo_t *info ) { return POSIX_NOT_IMPLEMENTED(); } /* * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 * * NOTE: P1003.1c/D10, p. 39 adds sigwait(). */ int sigtimedwait( const sigset_t *set, siginfo_t *info, const struct timespec *timeout ) { return POSIX_NOT_IMPLEMENTED(); } /* * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 * * NOTE: P1003.1c/D10, p. 39 adds sigwait(). */ int sigwait( const sigset_t *set, int *sig ) { return POSIX_NOT_IMPLEMENTED(); } /* * 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 * * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. */ int kill( pid_t pid, int sig ) { /* * Only supported for the "calling process" (i.e. this node). */ if( pid != getpid() ); set_errno_and_return_minus_one( ESRCH ); if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) return 0; /* SIGABRT comes from abort via assert and must work no matter what */ if ( sig == SIGABRT ) { exit( 1 ); } return POSIX_NOT_IMPLEMENTED(); } /* * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 */ int pthread_kill( pthread_t thread, int sig ) { POSIX_API_Control *api; Thread_Control *the_thread; Objects_Locations location; if ( sig && !is_valid_signo(sig) ) set_errno_and_return_minus_one( EINVAL ); if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) return 0; the_thread = _POSIX_Threads_Get( thread, &location ); switch ( location ) { case OBJECTS_ERROR: case OBJECTS_REMOTE: return ESRCH; case OBJECTS_LOCAL: /* * If sig == 0 then just validate arguments */ api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; if ( sig ) { /* XXX critical section */ api->signals_pending |= signo_to_mask( sig ); if ( api->signals_pending & ~api->signals_blocked ) { the_thread->do_post_task_switch_extension = TRUE; /* XXX may have to unblock the task */ } } _Thread_Enable_dispatch(); return 0; } return POSIX_BOTTOM_REACHED(); } /* * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79 */ Watchdog_Control _POSIX_signals_Alarm_timer; unsigned int alarm( unsigned int seconds ) { unsigned int remaining = 0; Watchdog_Control *the_timer; the_timer = &_POSIX_signals_Alarm_timer; switch ( _Watchdog_Remove( the_timer ) ) { case WATCHDOG_INACTIVE: case WATCHDOG_BEING_INSERTED: break; case WATCHDOG_ACTIVE: case WATCHDOG_REMOVE_IT: remaining = the_timer->initial - (the_timer->stop_time - the_timer->start_time); break; } _Watchdog_Insert_seconds( the_timer, seconds ); return remaining; } /* * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 */ int pause( void ) { return POSIX_NOT_IMPLEMENTED(); }