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 /cpukit/posix/src/sigtimedwait.c | |
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.
Diffstat (limited to 'cpukit/posix/src/sigtimedwait.c')
-rw-r--r-- | cpukit/posix/src/sigtimedwait.c | 117 |
1 files changed, 117 insertions, 0 deletions
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; +} |