diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-01-31 20:45:31 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1999-01-31 20:45:31 +0000 |
commit | 07d880f4bccd3d5f26fb729ca3fca5f6bed081d3 (patch) | |
tree | aed075a8265065601128cfd8da3b946190292f0d | |
parent | New files added to ease debugging. (diff) | |
download | rtems-07d880f4bccd3d5f26fb729ca3fca5f6bed081d3.tar.bz2 |
Split psignal.c into many more files. This reduced the amount of
object code that has to be loaded just for initializing the signal
manager.
43 files changed, 2691 insertions, 1837 deletions
diff --git a/c/src/exec/posix/include/rtems/posix/psignal.h b/c/src/exec/posix/include/rtems/posix/psignal.h index 4ecba1f41c..32e403a360 100644 --- a/c/src/exec/posix/include/rtems/posix/psignal.h +++ b/c/src/exec/posix/include/rtems/posix/psignal.h @@ -5,11 +5,67 @@ #ifndef __RTEMS_POSIX_SIGNALS_h #define __RTEMS_POSIX_SIGNALS_h +#include <rtems/posix/pthread.h> + +/* + * 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 ) + +#define _States_Is_interruptible_signal( _states ) \ + ( ((_states) & \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) + +#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) + +/* + * Variables + */ + +extern sigset_t _POSIX_signals_Pending; + +extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ]; + +extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; + +extern Watchdog_Control _POSIX_signals_Alarm_timer; + +extern Thread_queue_Control _POSIX_signals_Wait_queue; + +extern Chain_Control _POSIX_signals_Inactive_siginfo; + +extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; + +/* + * POSIX internal siginfo structure + */ + typedef struct { Chain_Node Node; siginfo_t Info; } POSIX_signals_Siginfo_node; +/* + * Internal routines + */ + void _POSIX_signals_Manager_Initialization( int maximum_queued_signals ); @@ -18,5 +74,42 @@ void _POSIX_signals_Post_switch_extension( Thread_Control *the_thread ); +boolean _POSIX_signals_Unblock_thread( + Thread_Control *the_thread, + int signo, + siginfo_t *info +); + +boolean _POSIX_signals_Clear_signals( + POSIX_API_Control *api, + int signo, + siginfo_t *info, + boolean is_global, + boolean check_blocked +); + +int killinfo( + pid_t pid, + int sig, + const union sigval *value +); + +void _POSIX_signals_Set_process_signals( + sigset_t mask +); + +void _POSIX_signals_Set_process_signals( + sigset_t mask +); + +/* + * Default signal handlers + */ + +#define _POSIX_signals_Stop_handler NULL +#define _POSIX_signals_Continue_handler NULL + +void _POSIX_signals_Abormal_termination_handler( int signo ); + #endif /* end of file */ diff --git a/c/src/exec/posix/src/Makefile.in b/c/src/exec/posix/src/Makefile.in index 20d6abf580..f8148aca0e 100644 --- a/c/src/exec/posix/src/Makefile.in +++ b/c/src/exec/posix/src/Makefile.in @@ -29,8 +29,16 @@ PTHREAD_PIECES=\ pthreadattrgetinheritsched pthreadattrsetinheritsched \ pthreadattrgetscope pthreadattrsetscope -C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) psignal sched time \ +PSIGNAL_PIECES=\ + psignal alarm kill killinfo pause pthreadkill pthreadsigmask \ + sigaction sigaddset sigdelset sigemptyset sigfillset sigismember \ + sigpending sigprocmask sigqueue sigsuspend sigtimedwait sigwait \ + sigwaitinfo + +C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) \ + $(PSIGNAL_PIECES) sched time \ types unistd $(ENOSYS_C_PIECES) + C_FILES=$(C_PIECES:%=%.c) C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) diff --git a/c/src/exec/posix/src/alarm.c b/c/src/exec/posix/src/alarm.c new file mode 100644 index 0000000000..a17fd04f4e --- /dev/null +++ b/c/src/exec/posix/src/alarm.c @@ -0,0 +1,48 @@ +/* + * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +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; +} + diff --git a/c/src/exec/posix/src/kill.c b/c/src/exec/posix/src/kill.c new file mode 100644 index 0000000000..97cd17164d --- /dev/null +++ b/c/src/exec/posix/src/kill.c @@ -0,0 +1,50 @@ +/* + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int kill( + pid_t pid, + int sig +) +{ + return killinfo( pid, sig, NULL ); +} + +/* + * _kill_r + * + * This is the Newlib dependent reentrant version of kill(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _kill_r( + struct _reent *ptr, + pid_t pid, + int sig +) +{ + return kill( pid, sig ); +} +#endif + diff --git a/c/src/exec/posix/src/killinfo.c b/c/src/exec/posix/src/killinfo.c new file mode 100644 index 0000000000..442fddd3c7 --- /dev/null +++ b/c/src/exec/posix/src/killinfo.c @@ -0,0 +1,328 @@ +/* + * kill() support routine + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> +#include <assert.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/score/isr.h> + +/*PAGE + * + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. + */ + +#define _POSIX_signals_Is_interested( _api, _mask ) \ + ( ~(_api)->signals_blocked & (_mask) ) + +int killinfo( + pid_t pid, + int sig, + const union sigval *value +) +{ + sigset_t mask; + POSIX_API_Control *api; + unsigned32 the_class; + unsigned32 index; + unsigned32 maximum; + Objects_Information *the_info; + Objects_Control **object_table; + Thread_Control *the_thread; + Thread_Control *interested_thread; + Priority_Control interested_priority; + Chain_Control *the_chain; + 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). + */ + + if( pid != getpid() ) + set_errno_and_return_minus_one( ESRCH ); + + /* + * Validate the signal passed if not 0. + */ + + if ( sig && !is_valid_signo(sig) ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * If the signal is being ignored, then we are out of here. + */ + + if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) + return 0; + + /* + * P1003.1c/Draft 10, p. 33 says that certain signals should always + * be directed to the executing thread such as those caused by hardware + * faults. + */ + + switch ( sig ) { + case SIGFPE: + case SIGILL: + case SIGSEGV: + return pthread_kill( pthread_self(), sig ); + default: + break; + } + + 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(); + + /* + * Is the currently executing thread interested? If so then it will + * get it an execute it as soon as the dispatcher executes. + */ + + the_thread = _Thread_Executing; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + if ( _POSIX_signals_Is_interested( api, mask ) ) { + goto process_it; + } + + /* + * Is an interested thread waiting for this signal (sigwait())? + */ + + /* XXX violation of visibility -- need to define thread queue support */ + + for( index=0 ; + index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; + index++ ) { + + the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ]; + + for ( the_node = the_chain->first ; + !_Chain_Is_tail( the_chain, the_node ) ; + the_node = the_node->next ) { + + the_thread = (Thread_Control *)the_node; + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) { + goto process_it; + } + + } + } + + /* + * Is any other thread interested? The highest priority interested + * thread is selected. In the event of a tie, then the following + * additional criteria is used: + * + * + ready thread over blocked + * + blocked on call interruptible by signal (can return EINTR) + * + blocked on call not interruptible by signal + * + * This looks at every thread in the system regardless of the creating API. + * + * NOTES: + * + * + rtems internal threads do not receive signals. + */ + + interested_thread = NULL; + interested_priority = PRIORITY_MAXIMUM + 1; + + for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS; + the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS; + the_class++ ) { + + if ( the_class == OBJECTS_INTERNAL_THREADS ) + continue; + + the_info = _Objects_Information_table[ the_class ]; + + if ( !the_info ) /* manager not installed */ + continue; + + maximum = the_info->maximum; + object_table = the_info->local_table; + + assert( object_table ); /* always at least 1 entry */ + + for ( index = 1 ; index <= maximum ; index++ ) { + the_thread = (Thread_Control *) object_table[ index ]; + + if ( !the_thread ) + continue; + + /* + * If this thread is of lower priority than the interested thread, + * go on to the next thread. + */ + + if ( the_thread->current_priority > interested_priority ) + continue; + + /* + * If this thread is not interested, then go on to the next thread. + */ + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( !api || !_POSIX_signals_Is_interested( api, mask ) ) + continue; + + /* + * Now we know the thread under connsideration is interested. + * If the thread under consideration is of higher priority, then + * it becomes the interested thread. + */ + + if ( the_thread->current_priority < interested_priority ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + + /* + * Now the thread and the interested thread have the same priority. + * If the interested thread is ready, then we don't need to send it + * to a blocked thread. + */ + + if ( _States_Is_ready( interested_thread->current_state ) ) + continue; + + /* + * Now the interested thread is blocked. + * If the thread we are considering is not, the it becomes the + * interested thread. + */ + + if ( _States_Is_ready( the_thread->current_state ) ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + + /* + * Now we know both threads are blocked. + * If the interested thread is interruptible, then just use it. + */ + + /* XXX need a new states macro */ + if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) + continue; + + /* + * Now both threads are blocked and the interested thread is not + * interruptible. + * If the thread under consideration is interruptible by a signal, + * then it becomes the interested thread. + */ + + /* XXX need a new states macro */ + if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + } + } + } + + if ( interested_thread ) { + the_thread = interested_thread; + goto process_it; + } + + /* + * OK so no threads were interested right now. It will be left on the + * global pending until a thread receives it. The global set of threads + * can change interest in this signal in one of the following ways: + * + * + a thread is created with the signal unblocked, + * + pthread_sigmask() unblocks the signal, + * + sigprocmask() unblocks the signal, OR + * + sigaction() which changes the handler to SIG_IGN. + */ + + the_thread = NULL; + goto post_process_signal; + + /* + * We found a thread which was interested, so now we mark that this + * thread needs to do the post context switch extension so it can + * evaluate the signals pending. + */ + +process_it: + + the_thread->do_post_task_switch_extension = TRUE; + + /* + * 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(); + return 0; +} diff --git a/c/src/exec/posix/src/pause.c b/c/src/exec/posix/src/pause.c new file mode 100644 index 0000000000..a39011bef8 --- /dev/null +++ b/c/src/exec/posix/src/pause.c @@ -0,0 +1,39 @@ +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + */ + +int pause( void ) +{ + sigset_t all_signals; + int status; + + (void) sigfillset( &all_signals ); + + status = sigtimedwait( &all_signals, NULL, NULL ); + + return status; +} + diff --git a/c/src/exec/posix/src/psignal.c b/c/src/exec/posix/src/psignal.c index 1450164021..555b55d580 100644 --- a/c/src/exec/posix/src/psignal.c +++ b/c/src/exec/posix/src/psignal.c @@ -18,40 +18,19 @@ #include <rtems/posix/pthread.h> #include <rtems/posix/time.h> -/* - * 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; -void _POSIX_signals_Abormal_termination_handler( int signo ) -{ - exit( 1 ); -} +struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; -#define _POSIX_signals_Stop_handler NULL -#define _POSIX_signals_Continue_handler NULL +Watchdog_Control _POSIX_signals_Alarm_timer; -#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} } +Thread_queue_Control _POSIX_signals_Wait_queue; + +Chain_Control _POSIX_signals_Inactive_siginfo; +Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; -#define SIG_ARRAY_MAX (SIGRTMAX + 1) struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { /* NO SIGNAL 0 */ SIGACTION_IGNORE, /* SIGHUP 1 */ SIGACTION_TERMINATE, @@ -89,24 +68,16 @@ struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { /* SIGRTMAX 32 */ SIGACTION_IGNORE }; -struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; - -Watchdog_Control _POSIX_signals_Alarm_timer; - -Thread_queue_Control _POSIX_signals_Wait_queue; - -Chain_Control _POSIX_signals_Inactive_siginfo; -Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; - /*PAGE * - * XXX - move these + * _POSIX_signals_Abormal_termination_handler + * */ -#define _States_Is_interruptible_signal( _states ) \ - ( ((_states) & \ - (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ - (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) +void _POSIX_signals_Abormal_termination_handler( int signo ) +{ + exit( 1 ); +} /*PAGE * @@ -484,880 +455,3 @@ void _POSIX_signals_Manager_Initialization( sizeof( POSIX_signals_Siginfo_node ) ); } - -/* - * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 - */ - -int sigemptyset( - sigset_t *set -) -{ - if ( !set ) - set_errno_and_return_minus_one( EINVAL ); - - *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( EINVAL ); - - *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( EINVAL ); - - if ( !signo ) - return 0; - - 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( EINVAL ); - - if ( !signo ) - return 0; - - 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( EINVAL ); - - if ( !signo ) - return 0; - - 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 -) -{ - ISR_Level level; - - if ( oact ) - *oact = _POSIX_signals_Vectors[ sig ]; - - if ( !sig ) - return 0; - - if ( !is_valid_signo(sig) ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references. - * - * NOTE: Solaris documentation claims to "silently enforce" this which - * contradicts the POSIX specification. - */ - - if ( sig == SIGKILL ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * Evaluate the new action structure and set the global signal vector - * appropriately. - */ - - if ( act ) { - - /* - * Unless the user is installing the default signal actions, then - * we can just copy the provided sigaction structure into the vectors. - */ - - _ISR_Disable( level ); - if ( act->sa_handler == SIG_DFL ) { - _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ]; - } else { - _POSIX_signals_Clear_process_signals( signo_to_mask(sig) ); - _POSIX_signals_Vectors[ sig ] = *act; - } - _ISR_Enable( level ); - } - - /* - * No need to evaluate or dispatch because: - * - * + If we were ignoring the signal before, none could be pending - * now (signals not posted when SIG_IGN). - * + If we are now ignoring a signal that was previously pending, - * we clear the pending signal indicator. - */ - - return 0; -} - -/* - * 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; - - if ( !set && !oset ) - set_errno_and_return_minus_one( EINVAL ); - - api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; - - if ( oset ) - *oset = api->signals_blocked; - - if ( !set ) - return 0; - - switch ( how ) { - case SIG_BLOCK: - api->signals_blocked |= *set; - 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 ( ~api->signals_blocked & - (api->signals_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( EINVAL ); - - 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 -) -{ - sigset_t saved_signals_blocked; - sigset_t all_signals; - int status; - POSIX_API_Control *api; - - api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; - - status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked ); - - (void) sigfillset( &all_signals ); - - status = sigtimedwait( &all_signals, NULL, NULL ); - - (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL ); - - return status; -} - -/* - * 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 sigtimedwait( set, info, NULL ); -} - -/* - * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 - * - * NOTE: P1003.1c/D10, p. 39 adds sigwait(). - */ - -int _POSIX_signals_Get_highest( - sigset_t set -) -{ - int signo; - - for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { - if ( set & signo_to_mask( signo ) ) - return signo; - } - -/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */ - - for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { - if ( set & signo_to_mask( signo ) ) - return signo; - } - - return 0; -} - -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; - - 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? */ - - 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 ); - 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 ); - - if ( !info ) { - the_info->si_signo = signo; - the_info->si_code = SI_USER; - the_info->si_value.sival_int = 0; - } - } - - interval = 0; - if ( timeout ) { - - if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) - set_errno_and_return_minus_one( EINVAL ); - - interval = _POSIX_Timespec_to_interval( timeout ); - } - - 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 = (void *) the_info; - _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); - _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); - _Thread_Enable_dispatch(); - - errno = _Thread_Executing->Wait.return_code; - return the_info->si_signo; -} - -/* - * 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 -) -{ - int status; - - status = sigtimedwait( set, NULL, NULL ); - - if ( status != -1 ) { - if ( sig ) - *sig = status; - return 0; - } - - return errno; -} - -/*PAGE - * - * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 - * - * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. - */ - -#define _POSIX_signals_Is_interested( _api, _mask ) \ - ( ~(_api)->signals_blocked & (_mask) ) - -int killinfo( - pid_t pid, - int sig, - const union sigval *value -) -{ - sigset_t mask; - POSIX_API_Control *api; - unsigned32 the_class; - unsigned32 index; - unsigned32 maximum; - Objects_Information *the_info; - Objects_Control **object_table; - Thread_Control *the_thread; - Thread_Control *interested_thread; - Priority_Control interested_priority; - Chain_Control *the_chain; - 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). - */ - - if( pid != getpid() ) - set_errno_and_return_minus_one( ESRCH ); - - /* - * Validate the signal passed if not 0. - */ - - if ( sig && !is_valid_signo(sig) ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * If the signal is being ignored, then we are out of here. - */ - - if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) - return 0; - - /* - * P1003.1c/Draft 10, p. 33 says that certain signals should always - * be directed to the executing thread such as those caused by hardware - * faults. - */ - - switch ( sig ) { - case SIGFPE: - case SIGILL: - case SIGSEGV: - return pthread_kill( pthread_self(), sig ); - default: - break; - } - - 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(); - - /* - * Is the currently executing thread interested? If so then it will - * get it an execute it as soon as the dispatcher executes. - */ - - the_thread = _Thread_Executing; - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - if ( _POSIX_signals_Is_interested( api, mask ) ) { - goto process_it; - } - - /* - * Is an interested thread waiting for this signal (sigwait())? - */ - - /* XXX violation of visibility -- need to define thread queue support */ - - for( index=0 ; - index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; - index++ ) { - - the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ]; - - for ( the_node = the_chain->first ; - !_Chain_Is_tail( the_chain, the_node ) ; - the_node = the_node->next ) { - - the_thread = (Thread_Control *)the_node; - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) { - goto process_it; - } - - } - } - - /* - * Is any other thread interested? The highest priority interested - * thread is selected. In the event of a tie, then the following - * additional criteria is used: - * - * + ready thread over blocked - * + blocked on call interruptible by signal (can return EINTR) - * + blocked on call not interruptible by signal - * - * This looks at every thread in the system regardless of the creating API. - * - * NOTES: - * - * + rtems internal threads do not receive signals. - */ - - interested_thread = NULL; - interested_priority = PRIORITY_MAXIMUM + 1; - - for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS; - the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS; - the_class++ ) { - - if ( the_class == OBJECTS_INTERNAL_THREADS ) - continue; - - the_info = _Objects_Information_table[ the_class ]; - - if ( !the_info ) /* manager not installed */ - continue; - - maximum = the_info->maximum; - object_table = the_info->local_table; - - assert( object_table ); /* always at least 1 entry */ - - for ( index = 1 ; index <= maximum ; index++ ) { - the_thread = (Thread_Control *) object_table[ index ]; - - if ( !the_thread ) - continue; - - /* - * If this thread is of lower priority than the interested thread, - * go on to the next thread. - */ - - if ( the_thread->current_priority > interested_priority ) - continue; - - /* - * If this thread is not interested, then go on to the next thread. - */ - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( !api || !_POSIX_signals_Is_interested( api, mask ) ) - continue; - - /* - * Now we know the thread under connsideration is interested. - * If the thread under consideration is of higher priority, then - * it becomes the interested thread. - */ - - if ( the_thread->current_priority < interested_priority ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - continue; - } - - /* - * Now the thread and the interested thread have the same priority. - * If the interested thread is ready, then we don't need to send it - * to a blocked thread. - */ - - if ( _States_Is_ready( interested_thread->current_state ) ) - continue; - - /* - * Now the interested thread is blocked. - * If the thread we are considering is not, the it becomes the - * interested thread. - */ - - if ( _States_Is_ready( the_thread->current_state ) ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - continue; - } - - /* - * Now we know both threads are blocked. - * If the interested thread is interruptible, then just use it. - */ - - /* XXX need a new states macro */ - if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) - continue; - - /* - * Now both threads are blocked and the interested thread is not - * interruptible. - * If the thread under consideration is interruptible by a signal, - * then it becomes the interested thread. - */ - - /* XXX need a new states macro */ - if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - } - } - } - - if ( interested_thread ) { - the_thread = interested_thread; - goto process_it; - } - - /* - * OK so no threads were interested right now. It will be left on the - * global pending until a thread receives it. The global set of threads - * can change interest in this signal in one of the following ways: - * - * + a thread is created with the signal unblocked, - * + pthread_sigmask() unblocks the signal, - * + sigprocmask() unblocks the signal, OR - * + sigaction() which changes the handler to SIG_IGN. - */ - - the_thread = NULL; - goto post_process_signal; - - /* - * We found a thread which was interested, so now we mark that this - * thread needs to do the post context switch extension so it can - * evaluate the signals pending. - */ - -process_it: - - the_thread->do_post_task_switch_extension = TRUE; - - /* - * 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(); - 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 ); -} - -/* - * _kill_r - * - * This is the Newlib dependent reentrant version of kill(). - */ - -#if defined(RTEMS_NEWLIB) - -#include <reent.h> - -int _kill_r( - struct _reent *ptr, - pid_t pid, - int sig -) -{ - return kill( pid, sig ); -} -#endif - -/* - * 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 - */ - -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_flags == SA_SIGINFO ) - set_errno_and_return_minus_one( ENOSYS ); - - /* - * RTEMS does not support sending a siginfo signal to a specific thread. - */ - - the_thread = _POSIX_Threads_Get( thread, &location ); - switch ( location ) { - case OBJECTS_ERROR: - case OBJECTS_REMOTE: - set_errno_and_return_minus_one( ESRCH ); - case OBJECTS_LOCAL: - /* - * If sig == 0 then just validate arguments - */ - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( sig ) { - - if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) { - _Thread_Enable_dispatch(); - return 0; - } - - /* XXX critical section */ - - api->signals_pending |= signo_to_mask( sig ); - - (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL ); - - the_thread->do_post_task_switch_extension = TRUE; - - if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) - _ISR_Signals_to_thread_executing = TRUE; - } - _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 ) -{ - sigset_t all_signals; - int status; - - (void) sigfillset( &all_signals ); - - status = sigtimedwait( &all_signals, NULL, NULL ); - - return status; -} diff --git a/c/src/exec/posix/src/pthreadkill.c b/c/src/exec/posix/src/pthreadkill.c new file mode 100644 index 0000000000..652b3554a1 --- /dev/null +++ b/c/src/exec/posix/src/pthreadkill.c @@ -0,0 +1,79 @@ +/* + * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/score/isr.h> +#include <rtems/posix/seterr.h> + +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_flags == SA_SIGINFO ) + set_errno_and_return_minus_one( ENOSYS ); + + /* + * RTEMS does not support sending a siginfo signal to a specific thread. + */ + + the_thread = _POSIX_Threads_Get( thread, &location ); + switch ( location ) { + case OBJECTS_ERROR: + case OBJECTS_REMOTE: + set_errno_and_return_minus_one( ESRCH ); + case OBJECTS_LOCAL: + /* + * If sig == 0 then just validate arguments + */ + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( sig ) { + + if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) { + _Thread_Enable_dispatch(); + return 0; + } + + /* XXX critical section */ + + api->signals_pending |= signo_to_mask( sig ); + + (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL ); + + the_thread->do_post_task_switch_extension = TRUE; + + if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) + _ISR_Signals_to_thread_executing = TRUE; + } + _Thread_Enable_dispatch(); + return 0; + } + + return POSIX_BOTTOM_REACHED(); +} diff --git a/c/src/exec/posix/src/pthreadsigmask.c b/c/src/exec/posix/src/pthreadsigmask.c new file mode 100644 index 0000000000..1efede39c4 --- /dev/null +++ b/c/src/exec/posix/src/pthreadsigmask.c @@ -0,0 +1,71 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int pthread_sigmask( + int how, + const sigset_t *set, + sigset_t *oset +) +{ + POSIX_API_Control *api; + + if ( !set && !oset ) + set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + if ( oset ) + *oset = api->signals_blocked; + + if ( !set ) + return 0; + + switch ( how ) { + case SIG_BLOCK: + api->signals_blocked |= *set; + 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 ( ~api->signals_blocked & + (api->signals_pending | _POSIX_signals_Pending) ) { + _Thread_Executing->do_post_task_switch_extension = TRUE; + _Thread_Dispatch(); + } + + return 0; +} diff --git a/c/src/exec/posix/src/sigaction.c b/c/src/exec/posix/src/sigaction.c new file mode 100644 index 0000000000..a2d709e8e7 --- /dev/null +++ b/c/src/exec/posix/src/sigaction.c @@ -0,0 +1,85 @@ +/* + * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/score/isr.h> + +int sigaction( + int sig, + const struct sigaction *act, + struct sigaction *oact +) +{ + ISR_Level level; + + if ( oact ) + *oact = _POSIX_signals_Vectors[ sig ]; + + if ( !sig ) + return 0; + + if ( !is_valid_signo(sig) ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references. + * + * NOTE: Solaris documentation claims to "silently enforce" this which + * contradicts the POSIX specification. + */ + + if ( sig == SIGKILL ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * Evaluate the new action structure and set the global signal vector + * appropriately. + */ + + if ( act ) { + + /* + * Unless the user is installing the default signal actions, then + * we can just copy the provided sigaction structure into the vectors. + */ + + _ISR_Disable( level ); + if ( act->sa_handler == SIG_DFL ) { + _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ]; + } else { + _POSIX_signals_Clear_process_signals( signo_to_mask(sig) ); + _POSIX_signals_Vectors[ sig ] = *act; + } + _ISR_Enable( level ); + } + + /* + * No need to evaluate or dispatch because: + * + * + If we were ignoring the signal before, none could be pending + * now (signals not posted when SIG_IGN). + * + If we are now ignoring a signal that was previously pending, + * we clear the pending signal indicator. + */ + + return 0; +} + diff --git a/c/src/exec/posix/src/sigaddset.c b/c/src/exec/posix/src/sigaddset.c new file mode 100644 index 0000000000..7e8058781f --- /dev/null +++ b/c/src/exec/posix/src/sigaddset.c @@ -0,0 +1,40 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigaddset( + sigset_t *set, + int signo +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + *set |= signo_to_mask(signo); + return 0; +} diff --git a/c/src/exec/posix/src/sigdelset.c b/c/src/exec/posix/src/sigdelset.c new file mode 100644 index 0000000000..c16449c287 --- /dev/null +++ b/c/src/exec/posix/src/sigdelset.c @@ -0,0 +1,45 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +/* + * 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( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + *set &= ~signo_to_mask(signo); + return 0; +} + diff --git a/c/src/exec/posix/src/sigemptyset.c b/c/src/exec/posix/src/sigemptyset.c new file mode 100644 index 0000000000..653a840d91 --- /dev/null +++ b/c/src/exec/posix/src/sigemptyset.c @@ -0,0 +1,34 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigemptyset( + sigset_t *set +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + *set = 0; + return 0; +} + diff --git a/c/src/exec/posix/src/sigfillset.c b/c/src/exec/posix/src/sigfillset.c new file mode 100644 index 0000000000..9ccef1a201 --- /dev/null +++ b/c/src/exec/posix/src/sigfillset.c @@ -0,0 +1,34 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigfillset( + sigset_t *set +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + *set = SIGNAL_ALL_MASK; + return 0; +} + diff --git a/c/src/exec/posix/src/sigismember.c b/c/src/exec/posix/src/sigismember.c new file mode 100644 index 0000000000..f98730a0d5 --- /dev/null +++ b/c/src/exec/posix/src/sigismember.c @@ -0,0 +1,43 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigismember( + const sigset_t *set, + int signo +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + if ( *set & signo_to_mask(signo) ) + return 1; + + return 0; +} + diff --git a/c/src/exec/posix/src/sigpending.c b/c/src/exec/posix/src/sigpending.c new file mode 100644 index 0000000000..49b34c9c46 --- /dev/null +++ b/c/src/exec/posix/src/sigpending.c @@ -0,0 +1,38 @@ +/* + * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigpending( + sigset_t *set +) +{ + POSIX_API_Control *api; + + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + *set = api->signals_pending | _POSIX_signals_Pending; + + return 0; +} diff --git a/c/src/exec/posix/src/sigprocmask.c b/c/src/exec/posix/src/sigprocmask.c new file mode 100644 index 0000000000..dcbbcfca4f --- /dev/null +++ b/c/src/exec/posix/src/sigprocmask.c @@ -0,0 +1,37 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +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 ); +} diff --git a/c/src/exec/posix/src/sigqueue.c b/c/src/exec/posix/src/sigqueue.c new file mode 100644 index 0000000000..e90cf8789f --- /dev/null +++ b/c/src/exec/posix/src/sigqueue.c @@ -0,0 +1,31 @@ +/* + * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigqueue( + pid_t pid, + int signo, + const union sigval value +) +{ + return killinfo( pid, signo, &value ); +} + diff --git a/c/src/exec/posix/src/sigsuspend.c b/c/src/exec/posix/src/sigsuspend.c new file mode 100644 index 0000000000..beed3af5db --- /dev/null +++ b/c/src/exec/posix/src/sigsuspend.c @@ -0,0 +1,43 @@ +/* + * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigsuspend( + const sigset_t *sigmask +) +{ + sigset_t saved_signals_blocked; + sigset_t all_signals; + int status; + POSIX_API_Control *api; + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked ); + + (void) sigfillset( &all_signals ); + + status = sigtimedwait( &all_signals, NULL, NULL ); + + (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL ); + + return status; +} diff --git a/c/src/exec/posix/src/sigtimedwait.c b/c/src/exec/posix/src/sigtimedwait.c new file mode 100644 index 0000000000..bb35dd30d7 --- /dev/null +++ b/c/src/exec/posix/src/sigtimedwait.c @@ -0,0 +1,117 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/posix/time.h> + +int _POSIX_signals_Get_highest( + sigset_t set +) +{ + int signo; + + for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { + if ( set & signo_to_mask( signo ) ) + return signo; + } + +/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */ + + for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { + if ( set & signo_to_mask( signo ) ) + return signo; + } + + return 0; +} + +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; + + 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? */ + + 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 ); + 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 ); + + if ( !info ) { + the_info->si_signo = signo; + the_info->si_code = SI_USER; + the_info->si_value.sival_int = 0; + } + } + + interval = 0; + if ( timeout ) { + + if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) + set_errno_and_return_minus_one( EINVAL ); + + interval = _POSIX_Timespec_to_interval( timeout ); + } + + 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 = (void *) the_info; + _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); + _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); + _Thread_Enable_dispatch(); + + errno = _Thread_Executing->Wait.return_code; + return the_info->si_signo; +} diff --git a/c/src/exec/posix/src/sigwait.c b/c/src/exec/posix/src/sigwait.c new file mode 100644 index 0000000000..d0f026fb40 --- /dev/null +++ b/c/src/exec/posix/src/sigwait.c @@ -0,0 +1,43 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwait( + const sigset_t *set, + int *sig +) +{ + int status; + + status = sigtimedwait( set, NULL, NULL ); + + if ( status != -1 ) { + if ( sig ) + *sig = status; + return 0; + } + + return errno; +} + diff --git a/c/src/exec/posix/src/sigwaitinfo.c b/c/src/exec/posix/src/sigwaitinfo.c new file mode 100644 index 0000000000..ba9cd45c87 --- /dev/null +++ b/c/src/exec/posix/src/sigwaitinfo.c @@ -0,0 +1,31 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwaitinfo( + const sigset_t *set, + siginfo_t *info +) +{ + return sigtimedwait( set, info, NULL ); +} + diff --git a/cpukit/posix/include/rtems/posix/psignal.h b/cpukit/posix/include/rtems/posix/psignal.h index 4ecba1f41c..32e403a360 100644 --- a/cpukit/posix/include/rtems/posix/psignal.h +++ b/cpukit/posix/include/rtems/posix/psignal.h @@ -5,11 +5,67 @@ #ifndef __RTEMS_POSIX_SIGNALS_h #define __RTEMS_POSIX_SIGNALS_h +#include <rtems/posix/pthread.h> + +/* + * 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 ) + +#define _States_Is_interruptible_signal( _states ) \ + ( ((_states) & \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) + +#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) + +/* + * Variables + */ + +extern sigset_t _POSIX_signals_Pending; + +extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ]; + +extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; + +extern Watchdog_Control _POSIX_signals_Alarm_timer; + +extern Thread_queue_Control _POSIX_signals_Wait_queue; + +extern Chain_Control _POSIX_signals_Inactive_siginfo; + +extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; + +/* + * POSIX internal siginfo structure + */ + typedef struct { Chain_Node Node; siginfo_t Info; } POSIX_signals_Siginfo_node; +/* + * Internal routines + */ + void _POSIX_signals_Manager_Initialization( int maximum_queued_signals ); @@ -18,5 +74,42 @@ void _POSIX_signals_Post_switch_extension( Thread_Control *the_thread ); +boolean _POSIX_signals_Unblock_thread( + Thread_Control *the_thread, + int signo, + siginfo_t *info +); + +boolean _POSIX_signals_Clear_signals( + POSIX_API_Control *api, + int signo, + siginfo_t *info, + boolean is_global, + boolean check_blocked +); + +int killinfo( + pid_t pid, + int sig, + const union sigval *value +); + +void _POSIX_signals_Set_process_signals( + sigset_t mask +); + +void _POSIX_signals_Set_process_signals( + sigset_t mask +); + +/* + * Default signal handlers + */ + +#define _POSIX_signals_Stop_handler NULL +#define _POSIX_signals_Continue_handler NULL + +void _POSIX_signals_Abormal_termination_handler( int signo ); + #endif /* end of file */ diff --git a/cpukit/posix/src/alarm.c b/cpukit/posix/src/alarm.c new file mode 100644 index 0000000000..a17fd04f4e --- /dev/null +++ b/cpukit/posix/src/alarm.c @@ -0,0 +1,48 @@ +/* + * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +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; +} + diff --git a/cpukit/posix/src/kill.c b/cpukit/posix/src/kill.c new file mode 100644 index 0000000000..97cd17164d --- /dev/null +++ b/cpukit/posix/src/kill.c @@ -0,0 +1,50 @@ +/* + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int kill( + pid_t pid, + int sig +) +{ + return killinfo( pid, sig, NULL ); +} + +/* + * _kill_r + * + * This is the Newlib dependent reentrant version of kill(). + */ + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _kill_r( + struct _reent *ptr, + pid_t pid, + int sig +) +{ + return kill( pid, sig ); +} +#endif + diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c new file mode 100644 index 0000000000..442fddd3c7 --- /dev/null +++ b/cpukit/posix/src/killinfo.c @@ -0,0 +1,328 @@ +/* + * kill() support routine + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> +#include <assert.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/score/isr.h> + +/*PAGE + * + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. + */ + +#define _POSIX_signals_Is_interested( _api, _mask ) \ + ( ~(_api)->signals_blocked & (_mask) ) + +int killinfo( + pid_t pid, + int sig, + const union sigval *value +) +{ + sigset_t mask; + POSIX_API_Control *api; + unsigned32 the_class; + unsigned32 index; + unsigned32 maximum; + Objects_Information *the_info; + Objects_Control **object_table; + Thread_Control *the_thread; + Thread_Control *interested_thread; + Priority_Control interested_priority; + Chain_Control *the_chain; + 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). + */ + + if( pid != getpid() ) + set_errno_and_return_minus_one( ESRCH ); + + /* + * Validate the signal passed if not 0. + */ + + if ( sig && !is_valid_signo(sig) ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * If the signal is being ignored, then we are out of here. + */ + + if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) + return 0; + + /* + * P1003.1c/Draft 10, p. 33 says that certain signals should always + * be directed to the executing thread such as those caused by hardware + * faults. + */ + + switch ( sig ) { + case SIGFPE: + case SIGILL: + case SIGSEGV: + return pthread_kill( pthread_self(), sig ); + default: + break; + } + + 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(); + + /* + * Is the currently executing thread interested? If so then it will + * get it an execute it as soon as the dispatcher executes. + */ + + the_thread = _Thread_Executing; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + if ( _POSIX_signals_Is_interested( api, mask ) ) { + goto process_it; + } + + /* + * Is an interested thread waiting for this signal (sigwait())? + */ + + /* XXX violation of visibility -- need to define thread queue support */ + + for( index=0 ; + index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; + index++ ) { + + the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ]; + + for ( the_node = the_chain->first ; + !_Chain_Is_tail( the_chain, the_node ) ; + the_node = the_node->next ) { + + the_thread = (Thread_Control *)the_node; + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) { + goto process_it; + } + + } + } + + /* + * Is any other thread interested? The highest priority interested + * thread is selected. In the event of a tie, then the following + * additional criteria is used: + * + * + ready thread over blocked + * + blocked on call interruptible by signal (can return EINTR) + * + blocked on call not interruptible by signal + * + * This looks at every thread in the system regardless of the creating API. + * + * NOTES: + * + * + rtems internal threads do not receive signals. + */ + + interested_thread = NULL; + interested_priority = PRIORITY_MAXIMUM + 1; + + for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS; + the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS; + the_class++ ) { + + if ( the_class == OBJECTS_INTERNAL_THREADS ) + continue; + + the_info = _Objects_Information_table[ the_class ]; + + if ( !the_info ) /* manager not installed */ + continue; + + maximum = the_info->maximum; + object_table = the_info->local_table; + + assert( object_table ); /* always at least 1 entry */ + + for ( index = 1 ; index <= maximum ; index++ ) { + the_thread = (Thread_Control *) object_table[ index ]; + + if ( !the_thread ) + continue; + + /* + * If this thread is of lower priority than the interested thread, + * go on to the next thread. + */ + + if ( the_thread->current_priority > interested_priority ) + continue; + + /* + * If this thread is not interested, then go on to the next thread. + */ + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( !api || !_POSIX_signals_Is_interested( api, mask ) ) + continue; + + /* + * Now we know the thread under connsideration is interested. + * If the thread under consideration is of higher priority, then + * it becomes the interested thread. + */ + + if ( the_thread->current_priority < interested_priority ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + + /* + * Now the thread and the interested thread have the same priority. + * If the interested thread is ready, then we don't need to send it + * to a blocked thread. + */ + + if ( _States_Is_ready( interested_thread->current_state ) ) + continue; + + /* + * Now the interested thread is blocked. + * If the thread we are considering is not, the it becomes the + * interested thread. + */ + + if ( _States_Is_ready( the_thread->current_state ) ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + + /* + * Now we know both threads are blocked. + * If the interested thread is interruptible, then just use it. + */ + + /* XXX need a new states macro */ + if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) + continue; + + /* + * Now both threads are blocked and the interested thread is not + * interruptible. + * If the thread under consideration is interruptible by a signal, + * then it becomes the interested thread. + */ + + /* XXX need a new states macro */ + if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { + interested_thread = the_thread; + interested_priority = the_thread->current_priority; + } + } + } + + if ( interested_thread ) { + the_thread = interested_thread; + goto process_it; + } + + /* + * OK so no threads were interested right now. It will be left on the + * global pending until a thread receives it. The global set of threads + * can change interest in this signal in one of the following ways: + * + * + a thread is created with the signal unblocked, + * + pthread_sigmask() unblocks the signal, + * + sigprocmask() unblocks the signal, OR + * + sigaction() which changes the handler to SIG_IGN. + */ + + the_thread = NULL; + goto post_process_signal; + + /* + * We found a thread which was interested, so now we mark that this + * thread needs to do the post context switch extension so it can + * evaluate the signals pending. + */ + +process_it: + + the_thread->do_post_task_switch_extension = TRUE; + + /* + * 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(); + return 0; +} diff --git a/cpukit/posix/src/pause.c b/cpukit/posix/src/pause.c new file mode 100644 index 0000000000..a39011bef8 --- /dev/null +++ b/cpukit/posix/src/pause.c @@ -0,0 +1,39 @@ +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + */ + +int pause( void ) +{ + sigset_t all_signals; + int status; + + (void) sigfillset( &all_signals ); + + status = sigtimedwait( &all_signals, NULL, NULL ); + + return status; +} + diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c index 1450164021..555b55d580 100644 --- a/cpukit/posix/src/psignal.c +++ b/cpukit/posix/src/psignal.c @@ -18,40 +18,19 @@ #include <rtems/posix/pthread.h> #include <rtems/posix/time.h> -/* - * 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; -void _POSIX_signals_Abormal_termination_handler( int signo ) -{ - exit( 1 ); -} +struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; -#define _POSIX_signals_Stop_handler NULL -#define _POSIX_signals_Continue_handler NULL +Watchdog_Control _POSIX_signals_Alarm_timer; -#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} } +Thread_queue_Control _POSIX_signals_Wait_queue; + +Chain_Control _POSIX_signals_Inactive_siginfo; +Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; -#define SIG_ARRAY_MAX (SIGRTMAX + 1) struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { /* NO SIGNAL 0 */ SIGACTION_IGNORE, /* SIGHUP 1 */ SIGACTION_TERMINATE, @@ -89,24 +68,16 @@ struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { /* SIGRTMAX 32 */ SIGACTION_IGNORE }; -struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; - -Watchdog_Control _POSIX_signals_Alarm_timer; - -Thread_queue_Control _POSIX_signals_Wait_queue; - -Chain_Control _POSIX_signals_Inactive_siginfo; -Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; - /*PAGE * - * XXX - move these + * _POSIX_signals_Abormal_termination_handler + * */ -#define _States_Is_interruptible_signal( _states ) \ - ( ((_states) & \ - (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ - (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) +void _POSIX_signals_Abormal_termination_handler( int signo ) +{ + exit( 1 ); +} /*PAGE * @@ -484,880 +455,3 @@ void _POSIX_signals_Manager_Initialization( sizeof( POSIX_signals_Siginfo_node ) ); } - -/* - * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 - */ - -int sigemptyset( - sigset_t *set -) -{ - if ( !set ) - set_errno_and_return_minus_one( EINVAL ); - - *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( EINVAL ); - - *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( EINVAL ); - - if ( !signo ) - return 0; - - 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( EINVAL ); - - if ( !signo ) - return 0; - - 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( EINVAL ); - - if ( !signo ) - return 0; - - 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 -) -{ - ISR_Level level; - - if ( oact ) - *oact = _POSIX_signals_Vectors[ sig ]; - - if ( !sig ) - return 0; - - if ( !is_valid_signo(sig) ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references. - * - * NOTE: Solaris documentation claims to "silently enforce" this which - * contradicts the POSIX specification. - */ - - if ( sig == SIGKILL ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * Evaluate the new action structure and set the global signal vector - * appropriately. - */ - - if ( act ) { - - /* - * Unless the user is installing the default signal actions, then - * we can just copy the provided sigaction structure into the vectors. - */ - - _ISR_Disable( level ); - if ( act->sa_handler == SIG_DFL ) { - _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ]; - } else { - _POSIX_signals_Clear_process_signals( signo_to_mask(sig) ); - _POSIX_signals_Vectors[ sig ] = *act; - } - _ISR_Enable( level ); - } - - /* - * No need to evaluate or dispatch because: - * - * + If we were ignoring the signal before, none could be pending - * now (signals not posted when SIG_IGN). - * + If we are now ignoring a signal that was previously pending, - * we clear the pending signal indicator. - */ - - return 0; -} - -/* - * 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; - - if ( !set && !oset ) - set_errno_and_return_minus_one( EINVAL ); - - api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; - - if ( oset ) - *oset = api->signals_blocked; - - if ( !set ) - return 0; - - switch ( how ) { - case SIG_BLOCK: - api->signals_blocked |= *set; - 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 ( ~api->signals_blocked & - (api->signals_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( EINVAL ); - - 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 -) -{ - sigset_t saved_signals_blocked; - sigset_t all_signals; - int status; - POSIX_API_Control *api; - - api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; - - status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked ); - - (void) sigfillset( &all_signals ); - - status = sigtimedwait( &all_signals, NULL, NULL ); - - (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL ); - - return status; -} - -/* - * 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 sigtimedwait( set, info, NULL ); -} - -/* - * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 - * - * NOTE: P1003.1c/D10, p. 39 adds sigwait(). - */ - -int _POSIX_signals_Get_highest( - sigset_t set -) -{ - int signo; - - for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { - if ( set & signo_to_mask( signo ) ) - return signo; - } - -/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */ - - for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { - if ( set & signo_to_mask( signo ) ) - return signo; - } - - return 0; -} - -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; - - 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? */ - - 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 ); - 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 ); - - if ( !info ) { - the_info->si_signo = signo; - the_info->si_code = SI_USER; - the_info->si_value.sival_int = 0; - } - } - - interval = 0; - if ( timeout ) { - - if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) - set_errno_and_return_minus_one( EINVAL ); - - interval = _POSIX_Timespec_to_interval( timeout ); - } - - 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 = (void *) the_info; - _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); - _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); - _Thread_Enable_dispatch(); - - errno = _Thread_Executing->Wait.return_code; - return the_info->si_signo; -} - -/* - * 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 -) -{ - int status; - - status = sigtimedwait( set, NULL, NULL ); - - if ( status != -1 ) { - if ( sig ) - *sig = status; - return 0; - } - - return errno; -} - -/*PAGE - * - * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 - * - * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. - */ - -#define _POSIX_signals_Is_interested( _api, _mask ) \ - ( ~(_api)->signals_blocked & (_mask) ) - -int killinfo( - pid_t pid, - int sig, - const union sigval *value -) -{ - sigset_t mask; - POSIX_API_Control *api; - unsigned32 the_class; - unsigned32 index; - unsigned32 maximum; - Objects_Information *the_info; - Objects_Control **object_table; - Thread_Control *the_thread; - Thread_Control *interested_thread; - Priority_Control interested_priority; - Chain_Control *the_chain; - 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). - */ - - if( pid != getpid() ) - set_errno_and_return_minus_one( ESRCH ); - - /* - * Validate the signal passed if not 0. - */ - - if ( sig && !is_valid_signo(sig) ) - set_errno_and_return_minus_one( EINVAL ); - - /* - * If the signal is being ignored, then we are out of here. - */ - - if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) - return 0; - - /* - * P1003.1c/Draft 10, p. 33 says that certain signals should always - * be directed to the executing thread such as those caused by hardware - * faults. - */ - - switch ( sig ) { - case SIGFPE: - case SIGILL: - case SIGSEGV: - return pthread_kill( pthread_self(), sig ); - default: - break; - } - - 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(); - - /* - * Is the currently executing thread interested? If so then it will - * get it an execute it as soon as the dispatcher executes. - */ - - the_thread = _Thread_Executing; - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - if ( _POSIX_signals_Is_interested( api, mask ) ) { - goto process_it; - } - - /* - * Is an interested thread waiting for this signal (sigwait())? - */ - - /* XXX violation of visibility -- need to define thread queue support */ - - for( index=0 ; - index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; - index++ ) { - - the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ]; - - for ( the_node = the_chain->first ; - !_Chain_Is_tail( the_chain, the_node ) ; - the_node = the_node->next ) { - - the_thread = (Thread_Control *)the_node; - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) { - goto process_it; - } - - } - } - - /* - * Is any other thread interested? The highest priority interested - * thread is selected. In the event of a tie, then the following - * additional criteria is used: - * - * + ready thread over blocked - * + blocked on call interruptible by signal (can return EINTR) - * + blocked on call not interruptible by signal - * - * This looks at every thread in the system regardless of the creating API. - * - * NOTES: - * - * + rtems internal threads do not receive signals. - */ - - interested_thread = NULL; - interested_priority = PRIORITY_MAXIMUM + 1; - - for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS; - the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS; - the_class++ ) { - - if ( the_class == OBJECTS_INTERNAL_THREADS ) - continue; - - the_info = _Objects_Information_table[ the_class ]; - - if ( !the_info ) /* manager not installed */ - continue; - - maximum = the_info->maximum; - object_table = the_info->local_table; - - assert( object_table ); /* always at least 1 entry */ - - for ( index = 1 ; index <= maximum ; index++ ) { - the_thread = (Thread_Control *) object_table[ index ]; - - if ( !the_thread ) - continue; - - /* - * If this thread is of lower priority than the interested thread, - * go on to the next thread. - */ - - if ( the_thread->current_priority > interested_priority ) - continue; - - /* - * If this thread is not interested, then go on to the next thread. - */ - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( !api || !_POSIX_signals_Is_interested( api, mask ) ) - continue; - - /* - * Now we know the thread under connsideration is interested. - * If the thread under consideration is of higher priority, then - * it becomes the interested thread. - */ - - if ( the_thread->current_priority < interested_priority ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - continue; - } - - /* - * Now the thread and the interested thread have the same priority. - * If the interested thread is ready, then we don't need to send it - * to a blocked thread. - */ - - if ( _States_Is_ready( interested_thread->current_state ) ) - continue; - - /* - * Now the interested thread is blocked. - * If the thread we are considering is not, the it becomes the - * interested thread. - */ - - if ( _States_Is_ready( the_thread->current_state ) ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - continue; - } - - /* - * Now we know both threads are blocked. - * If the interested thread is interruptible, then just use it. - */ - - /* XXX need a new states macro */ - if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) - continue; - - /* - * Now both threads are blocked and the interested thread is not - * interruptible. - * If the thread under consideration is interruptible by a signal, - * then it becomes the interested thread. - */ - - /* XXX need a new states macro */ - if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) { - interested_thread = the_thread; - interested_priority = the_thread->current_priority; - } - } - } - - if ( interested_thread ) { - the_thread = interested_thread; - goto process_it; - } - - /* - * OK so no threads were interested right now. It will be left on the - * global pending until a thread receives it. The global set of threads - * can change interest in this signal in one of the following ways: - * - * + a thread is created with the signal unblocked, - * + pthread_sigmask() unblocks the signal, - * + sigprocmask() unblocks the signal, OR - * + sigaction() which changes the handler to SIG_IGN. - */ - - the_thread = NULL; - goto post_process_signal; - - /* - * We found a thread which was interested, so now we mark that this - * thread needs to do the post context switch extension so it can - * evaluate the signals pending. - */ - -process_it: - - the_thread->do_post_task_switch_extension = TRUE; - - /* - * 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(); - 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 ); -} - -/* - * _kill_r - * - * This is the Newlib dependent reentrant version of kill(). - */ - -#if defined(RTEMS_NEWLIB) - -#include <reent.h> - -int _kill_r( - struct _reent *ptr, - pid_t pid, - int sig -) -{ - return kill( pid, sig ); -} -#endif - -/* - * 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 - */ - -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_flags == SA_SIGINFO ) - set_errno_and_return_minus_one( ENOSYS ); - - /* - * RTEMS does not support sending a siginfo signal to a specific thread. - */ - - the_thread = _POSIX_Threads_Get( thread, &location ); - switch ( location ) { - case OBJECTS_ERROR: - case OBJECTS_REMOTE: - set_errno_and_return_minus_one( ESRCH ); - case OBJECTS_LOCAL: - /* - * If sig == 0 then just validate arguments - */ - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( sig ) { - - if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) { - _Thread_Enable_dispatch(); - return 0; - } - - /* XXX critical section */ - - api->signals_pending |= signo_to_mask( sig ); - - (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL ); - - the_thread->do_post_task_switch_extension = TRUE; - - if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) - _ISR_Signals_to_thread_executing = TRUE; - } - _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 ) -{ - sigset_t all_signals; - int status; - - (void) sigfillset( &all_signals ); - - status = sigtimedwait( &all_signals, NULL, NULL ); - - return status; -} diff --git a/cpukit/posix/src/pthreadkill.c b/cpukit/posix/src/pthreadkill.c new file mode 100644 index 0000000000..652b3554a1 --- /dev/null +++ b/cpukit/posix/src/pthreadkill.c @@ -0,0 +1,79 @@ +/* + * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/score/isr.h> +#include <rtems/posix/seterr.h> + +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_flags == SA_SIGINFO ) + set_errno_and_return_minus_one( ENOSYS ); + + /* + * RTEMS does not support sending a siginfo signal to a specific thread. + */ + + the_thread = _POSIX_Threads_Get( thread, &location ); + switch ( location ) { + case OBJECTS_ERROR: + case OBJECTS_REMOTE: + set_errno_and_return_minus_one( ESRCH ); + case OBJECTS_LOCAL: + /* + * If sig == 0 then just validate arguments + */ + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( sig ) { + + if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) { + _Thread_Enable_dispatch(); + return 0; + } + + /* XXX critical section */ + + api->signals_pending |= signo_to_mask( sig ); + + (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL ); + + the_thread->do_post_task_switch_extension = TRUE; + + if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) + _ISR_Signals_to_thread_executing = TRUE; + } + _Thread_Enable_dispatch(); + return 0; + } + + return POSIX_BOTTOM_REACHED(); +} diff --git a/cpukit/posix/src/pthreadsigmask.c b/cpukit/posix/src/pthreadsigmask.c new file mode 100644 index 0000000000..1efede39c4 --- /dev/null +++ b/cpukit/posix/src/pthreadsigmask.c @@ -0,0 +1,71 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int pthread_sigmask( + int how, + const sigset_t *set, + sigset_t *oset +) +{ + POSIX_API_Control *api; + + if ( !set && !oset ) + set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + if ( oset ) + *oset = api->signals_blocked; + + if ( !set ) + return 0; + + switch ( how ) { + case SIG_BLOCK: + api->signals_blocked |= *set; + 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 ( ~api->signals_blocked & + (api->signals_pending | _POSIX_signals_Pending) ) { + _Thread_Executing->do_post_task_switch_extension = TRUE; + _Thread_Dispatch(); + } + + return 0; +} diff --git a/cpukit/posix/src/sigaction.c b/cpukit/posix/src/sigaction.c new file mode 100644 index 0000000000..a2d709e8e7 --- /dev/null +++ b/cpukit/posix/src/sigaction.c @@ -0,0 +1,85 @@ +/* + * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/score/isr.h> + +int sigaction( + int sig, + const struct sigaction *act, + struct sigaction *oact +) +{ + ISR_Level level; + + if ( oact ) + *oact = _POSIX_signals_Vectors[ sig ]; + + if ( !sig ) + return 0; + + if ( !is_valid_signo(sig) ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references. + * + * NOTE: Solaris documentation claims to "silently enforce" this which + * contradicts the POSIX specification. + */ + + if ( sig == SIGKILL ) + set_errno_and_return_minus_one( EINVAL ); + + /* + * Evaluate the new action structure and set the global signal vector + * appropriately. + */ + + if ( act ) { + + /* + * Unless the user is installing the default signal actions, then + * we can just copy the provided sigaction structure into the vectors. + */ + + _ISR_Disable( level ); + if ( act->sa_handler == SIG_DFL ) { + _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ]; + } else { + _POSIX_signals_Clear_process_signals( signo_to_mask(sig) ); + _POSIX_signals_Vectors[ sig ] = *act; + } + _ISR_Enable( level ); + } + + /* + * No need to evaluate or dispatch because: + * + * + If we were ignoring the signal before, none could be pending + * now (signals not posted when SIG_IGN). + * + If we are now ignoring a signal that was previously pending, + * we clear the pending signal indicator. + */ + + return 0; +} + diff --git a/cpukit/posix/src/sigaddset.c b/cpukit/posix/src/sigaddset.c new file mode 100644 index 0000000000..7e8058781f --- /dev/null +++ b/cpukit/posix/src/sigaddset.c @@ -0,0 +1,40 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigaddset( + sigset_t *set, + int signo +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + *set |= signo_to_mask(signo); + return 0; +} diff --git a/cpukit/posix/src/sigdelset.c b/cpukit/posix/src/sigdelset.c new file mode 100644 index 0000000000..c16449c287 --- /dev/null +++ b/cpukit/posix/src/sigdelset.c @@ -0,0 +1,45 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +/* + * 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( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + *set &= ~signo_to_mask(signo); + return 0; +} + diff --git a/cpukit/posix/src/sigemptyset.c b/cpukit/posix/src/sigemptyset.c new file mode 100644 index 0000000000..653a840d91 --- /dev/null +++ b/cpukit/posix/src/sigemptyset.c @@ -0,0 +1,34 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigemptyset( + sigset_t *set +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + *set = 0; + return 0; +} + diff --git a/cpukit/posix/src/sigfillset.c b/cpukit/posix/src/sigfillset.c new file mode 100644 index 0000000000..9ccef1a201 --- /dev/null +++ b/cpukit/posix/src/sigfillset.c @@ -0,0 +1,34 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigfillset( + sigset_t *set +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + *set = SIGNAL_ALL_MASK; + return 0; +} + diff --git a/cpukit/posix/src/sigismember.c b/cpukit/posix/src/sigismember.c new file mode 100644 index 0000000000..f98730a0d5 --- /dev/null +++ b/cpukit/posix/src/sigismember.c @@ -0,0 +1,43 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigismember( + const sigset_t *set, + int signo +) +{ + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + set_errno_and_return_minus_one( EINVAL ); + + if ( *set & signo_to_mask(signo) ) + return 1; + + return 0; +} + diff --git a/cpukit/posix/src/sigpending.c b/cpukit/posix/src/sigpending.c new file mode 100644 index 0000000000..49b34c9c46 --- /dev/null +++ b/cpukit/posix/src/sigpending.c @@ -0,0 +1,38 @@ +/* + * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> + +int sigpending( + sigset_t *set +) +{ + POSIX_API_Control *api; + + if ( !set ) + set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + *set = api->signals_pending | _POSIX_signals_Pending; + + return 0; +} diff --git a/cpukit/posix/src/sigprocmask.c b/cpukit/posix/src/sigprocmask.c new file mode 100644 index 0000000000..dcbbcfca4f --- /dev/null +++ b/cpukit/posix/src/sigprocmask.c @@ -0,0 +1,37 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +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 ); +} diff --git a/cpukit/posix/src/sigqueue.c b/cpukit/posix/src/sigqueue.c new file mode 100644 index 0000000000..e90cf8789f --- /dev/null +++ b/cpukit/posix/src/sigqueue.c @@ -0,0 +1,31 @@ +/* + * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigqueue( + pid_t pid, + int signo, + const union sigval value +) +{ + return killinfo( pid, signo, &value ); +} + diff --git a/cpukit/posix/src/sigsuspend.c b/cpukit/posix/src/sigsuspend.c new file mode 100644 index 0000000000..beed3af5db --- /dev/null +++ b/cpukit/posix/src/sigsuspend.c @@ -0,0 +1,43 @@ +/* + * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigsuspend( + const sigset_t *sigmask +) +{ + sigset_t saved_signals_blocked; + sigset_t all_signals; + int status; + POSIX_API_Control *api; + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked ); + + (void) sigfillset( &all_signals ); + + status = sigtimedwait( &all_signals, NULL, NULL ); + + (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL ); + + return status; +} diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c new file mode 100644 index 0000000000..bb35dd30d7 --- /dev/null +++ b/cpukit/posix/src/sigtimedwait.c @@ -0,0 +1,117 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/seterr.h> +#include <rtems/posix/time.h> + +int _POSIX_signals_Get_highest( + sigset_t set +) +{ + int signo; + + for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { + if ( set & signo_to_mask( signo ) ) + return signo; + } + +/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */ + + for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { + if ( set & signo_to_mask( signo ) ) + return signo; + } + + return 0; +} + +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; + + 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? */ + + 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 ); + 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 ); + + if ( !info ) { + the_info->si_signo = signo; + the_info->si_code = SI_USER; + the_info->si_value.sival_int = 0; + } + } + + interval = 0; + if ( timeout ) { + + if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) + set_errno_and_return_minus_one( EINVAL ); + + interval = _POSIX_Timespec_to_interval( timeout ); + } + + 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 = (void *) the_info; + _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); + _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); + _Thread_Enable_dispatch(); + + errno = _Thread_Executing->Wait.return_code; + return the_info->si_signo; +} diff --git a/cpukit/posix/src/sigwait.c b/cpukit/posix/src/sigwait.c new file mode 100644 index 0000000000..d0f026fb40 --- /dev/null +++ b/cpukit/posix/src/sigwait.c @@ -0,0 +1,43 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwait( + const sigset_t *set, + int *sig +) +{ + int status; + + status = sigtimedwait( set, NULL, NULL ); + + if ( status != -1 ) { + if ( sig ) + *sig = status; + return 0; + } + + return errno; +} + diff --git a/cpukit/posix/src/sigwaitinfo.c b/cpukit/posix/src/sigwaitinfo.c new file mode 100644 index 0000000000..ba9cd45c87 --- /dev/null +++ b/cpukit/posix/src/sigwaitinfo.c @@ -0,0 +1,31 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwaitinfo( + const sigset_t *set, + siginfo_t *info +) +{ + return sigtimedwait( set, info, NULL ); +} + |