source: rtems/cpukit/posix/src/sigtimedwait.c @ ecdbb42

4.104.11
Last change on this file since ecdbb42 was ecdbb42, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 3, 2009 at 6:40:31 PM

2009-07-03 Joel Sherrill <joel.sherrill@…>

  • posix/src/sigtimedwait.c: Restructure to improve coverage. Improve comments.
  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
3 *
4 *  COPYRIGHT (c) 1989-2008.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <pthread.h>
19#include <signal.h>
20#include <errno.h>
21
22#include <rtems/system.h>
23#include <rtems/posix/pthread.h>
24#include <rtems/posix/psignal.h>
25#include <rtems/seterr.h>
26#include <rtems/posix/time.h>
27#include <rtems/score/isr.h>
28
29int _POSIX_signals_Get_highest(
30  sigset_t   set
31)
32{
33  int signo;
34
35  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
36    if ( set & signo_to_mask( signo ) ) {
37      goto found_it;
38    }
39  }
40
41  /*
42   *  We assume SIGHUP == 1 and is the first non-real-time signal.
43   */
44
45  #if (SIGHUP != 1)
46    #error "Assumption that SIGHUP==1 violated!!"
47  #endif
48  for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
49    if ( set & signo_to_mask( signo ) ) {
50      goto found_it;
51    }
52  }
53
54  /*
55   *  This is structured this way to eliminate the need to have
56   *  a return 0.  This routine will NOT be called unless a signal
57   *  is pending in the set passed in.
58   */
59found_it:
60  return signo;
61}
62
63int sigtimedwait(
64  const sigset_t         *set,
65  siginfo_t              *info,
66  const struct timespec  *timeout
67)
68{
69  Thread_Control    *the_thread;
70  POSIX_API_Control *api;
71  Watchdog_Interval  interval;
72  siginfo_t          signal_information;
73  siginfo_t         *the_info;
74  int                signo;
75  ISR_Level          level;
76
77  /*
78   *  Error check parameters before disabling interrupts.
79   */
80  if ( !set )
81    rtems_set_errno_and_return_minus_one( EINVAL );
82 
83  /*  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
84   *        in the Open Group specification.
85   */
86
87  interval = 0;
88  if ( timeout ) {
89
90    if ( !_Timespec_Is_valid( timeout ) )
91      rtems_set_errno_and_return_minus_one( EINVAL );
92
93    interval = _Timespec_To_ticks( timeout );
94
95    if ( !interval )
96      rtems_set_errno_and_return_minus_one( EINVAL );
97  }
98
99  /*
100   *  Initialize local variables.
101   */
102
103  the_info = ( info ) ? info : &signal_information;
104
105  the_thread = _Thread_Executing;
106
107  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
108
109  /*
110   *  What if they are already pending?
111   */
112
113  /* API signals pending? */
114
115  _ISR_Disable( level );
116  if ( *set & api->signals_pending ) {
117    /* XXX real info later */
118    the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );
119    _POSIX_signals_Clear_signals(
120      api,
121      the_info->si_signo,
122      the_info,
123      false,
124      false
125    );
126    _ISR_Enable( level );
127
128    the_info->si_code = SI_USER;
129    the_info->si_value.sival_int = 0;
130    return the_info->si_signo;
131  }
132
133  /* Process pending signals? */
134
135  if ( *set & _POSIX_signals_Pending ) {
136    signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );
137    _POSIX_signals_Clear_signals( api, signo, the_info, true, false );
138    _ISR_Enable( level );
139
140    the_info->si_signo = signo;
141    the_info->si_code = SI_USER;
142    the_info->si_value.sival_int = 0;
143    return signo;
144  }
145
146  the_info->si_signo = -1;
147
148  _Thread_Disable_dispatch();
149    the_thread->Wait.queue           = &_POSIX_signals_Wait_queue;
150    the_thread->Wait.return_code     = EINTR;
151    the_thread->Wait.option          = *set;
152    the_thread->Wait.return_argument = the_info;
153    _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );
154    _ISR_Enable( level );
155    _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );
156  _Thread_Enable_dispatch();
157
158  /*
159   * When the thread is set free by a signal, it is need to eliminate
160   * the signal.
161   */
162
163  _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false );
164  errno = _Thread_Executing->Wait.return_code;
165  return the_info->si_signo;
166}
Note: See TracBrowser for help on using the repository browser.