source: rtems/cpukit/posix/src/sigtimedwait.c @ 127c20eb

5
Last change on this file since 127c20eb was f23d470, checked in by Gedare Bloom <gedare@…>, on 06/09/16 at 15:33:15

cpukit: Add and use Watchdog_Discipline.

Clock disciplines may be WATCHDOG_RELATIVE, WATCHDOG_ABSOLUTE,
or WATCHDOG_NO_TIMEOUT. A discipline of WATCHDOG_RELATIVE with
a timeout of WATCHDOG_NO_TIMEOUT is equivalent to a discipline
of WATCHDOG_NO_TIMEOUT.

updates #2732

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Wait for Queued Signals
5 *  @ingroup POSIXAPI
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2008.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <signal.h>
22
23#include <rtems/posix/pthreadimpl.h>
24#include <rtems/posix/psignalimpl.h>
25#include <rtems/posix/posixapi.h>
26#include <rtems/score/threadqimpl.h>
27#include <rtems/score/isr.h>
28
29static int _POSIX_signals_Get_lowest(
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
63/**
64 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
65 */
66int sigtimedwait(
67  const sigset_t         *__restrict set,
68  siginfo_t              *__restrict info,
69  const struct timespec  *__restrict timeout
70)
71{
72  Thread_Control       *executing;
73  POSIX_API_Control    *api;
74  Watchdog_Interval     interval;
75  siginfo_t             signal_information;
76  siginfo_t            *the_info;
77  int                   signo;
78  Thread_queue_Context  queue_context;
79  int                   error;
80
81  /*
82   *  Error check parameters before disabling interrupts.
83   */
84  if ( !set )
85    rtems_set_errno_and_return_minus_one( EINVAL );
86
87  /*  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
88   *        in the Open Group specification.
89   */
90
91  interval = 0;
92  if ( timeout ) {
93
94    if ( !_Timespec_Is_valid( timeout ) )
95      rtems_set_errno_and_return_minus_one( EINVAL );
96
97    interval = _Timespec_To_ticks( timeout );
98
99    if ( !interval )
100      rtems_set_errno_and_return_minus_one( EINVAL );
101  }
102
103  /*
104   *  Initialize local variables.
105   */
106
107  the_info = ( info ) ? info : &signal_information;
108
109  executing = _Thread_Get_executing();
110  api = executing->API_Extensions[ THREAD_API_POSIX ];
111
112  /*
113   *  What if they are already pending?
114   */
115
116  /* API signals pending? */
117
118  _Thread_queue_Context_initialize( &queue_context );
119  _POSIX_signals_Acquire( &queue_context );
120  if ( *set & api->signals_pending ) {
121    /* XXX real info later */
122    the_info->si_signo = _POSIX_signals_Get_lowest( api->signals_pending );
123    _POSIX_signals_Clear_signals(
124      api,
125      the_info->si_signo,
126      the_info,
127      false,
128      false,
129      false
130    );
131    _POSIX_signals_Release( &queue_context );
132
133    the_info->si_code = SI_USER;
134    the_info->si_value.sival_int = 0;
135    return the_info->si_signo;
136  }
137
138  /* Process pending signals? */
139
140  if ( *set & _POSIX_signals_Pending ) {
141    signo = _POSIX_signals_Get_lowest( _POSIX_signals_Pending );
142    _POSIX_signals_Clear_signals( api, signo, the_info, true, false, false );
143    _POSIX_signals_Release( &queue_context );
144
145    the_info->si_signo = signo;
146    the_info->si_code = SI_USER;
147    the_info->si_value.sival_int = 0;
148    return signo;
149  }
150
151  the_info->si_signo = -1;
152
153  executing->Wait.option          = *set;
154  executing->Wait.return_argument = the_info;
155  _Thread_queue_Context_set_expected_level( &queue_context, 1 );
156  _Thread_queue_Context_set_relative_timeout( &queue_context, interval );
157  _Thread_queue_Enqueue_critical(
158    &_POSIX_signals_Wait_queue.Queue,
159    POSIX_SIGNALS_TQ_OPERATIONS,
160    executing,
161    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
162    &queue_context
163  );
164
165  /*
166   * When the thread is set free by a signal, it is need to eliminate
167   * the signal.
168   */
169
170  _POSIX_signals_Clear_signals(
171    api,
172    the_info->si_signo,
173    the_info,
174    false,
175    false,
176    true
177  );
178
179  /* Set errno only if return code is not EINTR or
180   * if EINTR was caused by a signal being caught, which
181   * was not in our set.
182   */
183
184  error = _POSIX_Get_error_after_wait( executing );
185
186  if (
187    error != EINTR
188     || ( *set & signo_to_mask( the_info->si_signo ) ) == 0
189  ) {
190    if ( error == ETIMEDOUT ) {
191      error = EAGAIN;
192    }
193
194    rtems_set_errno_and_return_minus_one( error );
195  }
196
197  return the_info->si_signo;
198}
Note: See TracBrowser for help on using the repository browser.