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

4.115
Last change on this file since a112364 was a112364, checked in by Sebastian Huber <sebastian.huber@…>, on 07/24/13 at 15:30:26

score: Create threadq implementation header

Move implementation specific parts of tqdata.h, threadq.h and
threadq.inl into new header file threadqimpl.h. The threadq.h contains
now only the application visible API.

Delete tqdata.h.

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