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

4.115
Last change on this file since a0e6c73 was f9340ed7, checked in by Sebastian Huber <sebastian.huber@…>, on 12/03/12 at 10:35:43

posix: Add and use <rtems/posix/psignalimpl.h>

This file contains the parts of <rtems/posix/psignal.h> that are only
necessary for the POSIX API implementation.

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