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

5
Last change on this file since d5cc9fd6 was 1e1a91ed, checked in by Sebastian Huber <sebastian.huber@…>, on 03/23/16 at 09:01:31

score: Remove Thread_queue_Queue::operations field

Remove the Thread_queue_Queue::operations field to reduce the size of
this structure. Add a thread queue operations parameter to the
_Thread_queue_First(), _Thread_queue_First_locked(),
_Thread_queue_Enqueue(), _Thread_queue_Dequeue() and
_Thread_queue_Flush() functions. This is a preparation patch to reduce
the size of several synchronization objects.

  • 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  _Thread_Disable_dispatch();
154    executing->Wait.return_code     = EINTR;
155    executing->Wait.option          = *set;
156    executing->Wait.return_argument = the_info;
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      interval,
163      EAGAIN,
164      &lock_context
165    );
166  _Thread_Enable_dispatch();
167
168  /*
169   * When the thread is set free by a signal, it is need to eliminate
170   * the signal.
171   */
172
173  _POSIX_signals_Clear_signals(
174    api,
175    the_info->si_signo,
176    the_info,
177    false,
178    false,
179    true
180  );
181
182  /* Set errno only if return code is not EINTR or
183   * if EINTR was caused by a signal being caught, which
184   * was not in our set.
185   */
186
187  if ( (executing->Wait.return_code != EINTR)
188       || !(*set & signo_to_mask( the_info->si_signo )) ) {
189    errno = executing->Wait.return_code;
190    return -1;
191  }
192
193  return the_info->si_signo;
194}
Note: See TracBrowser for help on using the repository browser.