source: rtems/cpukit/posix/src/sigtimedwait.c @ 259d885

Last change on this file since 259d885 was 259d885, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 28, 2016 at 4:55:16 AM

posix: Remove superfluous thread dispatch disable

The _Thread_queue_Enqueue_critical() already deals with thread
dispatching.

Update #2555.

  • Property mode set to 100644
File size: 4.3 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 <pthread.h>
22#include <signal.h>
23#include <errno.h>
24
25#include <rtems/posix/pthreadimpl.h>
26#include <rtems/posix/psignalimpl.h>
27#include <rtems/score/threadqimpl.h>
28#include <rtems/seterr.h>
29#include <rtems/score/isr.h>
30
31static int _POSIX_signals_Get_lowest(
32  sigset_t   set
33)
34{
35  int signo;
36
37  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
38    if ( set & signo_to_mask( signo ) ) {
39      goto found_it;
40    }
41  }
42
43  /*
44   *  We assume SIGHUP == 1 and is the first non-real-time signal.
45   */
46
47  #if (SIGHUP != 1)
48    #error "Assumption that SIGHUP==1 violated!!"
49  #endif
50  for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
51    if ( set & signo_to_mask( signo ) ) {
52      goto found_it;
53    }
54  }
55
56  /*
57   *  This is structured this way to eliminate the need to have
58   *  a return 0.  This routine will NOT be called unless a signal
59   *  is pending in the set passed in.
60   */
61found_it:
62  return signo;
63}
64
65/**
66 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
67 */
68int sigtimedwait(
69  const sigset_t         *__restrict set,
70  siginfo_t              *__restrict info,
71  const struct timespec  *__restrict timeout
72)
73{
74  Thread_Control    *executing;
75  POSIX_API_Control *api;
76  Watchdog_Interval  interval;
77  siginfo_t          signal_information;
78  siginfo_t         *the_info;
79  int                signo;
80  ISR_lock_Context   lock_context;
81
82  /*
83   *  Error check parameters before disabling interrupts.
84   */
85  if ( !set )
86    rtems_set_errno_and_return_minus_one( EINVAL );
87
88  /*  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
89   *        in the Open Group specification.
90   */
91
92  interval = 0;
93  if ( timeout ) {
94
95    if ( !_Timespec_Is_valid( timeout ) )
96      rtems_set_errno_and_return_minus_one( EINVAL );
97
98    interval = _Timespec_To_ticks( timeout );
99
100    if ( !interval )
101      rtems_set_errno_and_return_minus_one( EINVAL );
102  }
103
104  /*
105   *  Initialize local variables.
106   */
107
108  the_info = ( info ) ? info : &signal_information;
109
110  executing = _Thread_Get_executing();
111  api = executing->API_Extensions[ THREAD_API_POSIX ];
112
113  /*
114   *  What if they are already pending?
115   */
116
117  /* API signals pending? */
118
119  _POSIX_signals_Acquire( &lock_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( &lock_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( &lock_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.return_code     = EINTR;
154  executing->Wait.option          = *set;
155  executing->Wait.return_argument = the_info;
156  _Thread_queue_Enqueue_critical(
157    &_POSIX_signals_Wait_queue.Queue,
158    POSIX_SIGNALS_TQ_OPERATIONS,
159    executing,
160    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
161    interval,
162    EAGAIN,
163    &lock_context
164  );
165
166  /*
167   * When the thread is set free by a signal, it is need to eliminate
168   * the signal.
169   */
170
171  _POSIX_signals_Clear_signals(
172    api,
173    the_info->si_signo,
174    the_info,
175    false,
176    false,
177    true
178  );
179
180  /* Set errno only if return code is not EINTR or
181   * if EINTR was caused by a signal being caught, which
182   * was not in our set.
183   */
184
185  if ( (executing->Wait.return_code != EINTR)
186       || !(*set & signo_to_mask( the_info->si_signo )) ) {
187    errno = executing->Wait.return_code;
188    return -1;
189  }
190
191  return the_info->si_signo;
192}
Note: See TracBrowser for help on using the repository browser.