source: rtems/cpukit/posix/src/sigtimedwait.c @ 77fbbd6

5
Last change on this file since 77fbbd6 was 9480815a, checked in by Sebastian Huber <sebastian.huber@…>, on 12/21/17 at 13:36:52

score: Introduce new monotonic clock

Rename PER_CPU_WATCHDOG_MONOTONIC to PER_CPU_WATCHDOG_TICKS. Add new
PER_CPU_WATCHDOG_MONOTONIC which is based on the system uptime (measured
by timecounter).

Close #3264.

  • Property mode set to 100644
File size: 4.6 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/todimpl.h>
28#include <rtems/score/watchdogimpl.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  siginfo_t             signal_information;
77  siginfo_t            *the_info;
78  int                   signo;
79  struct timespec       uptime;
80  Thread_queue_Context  queue_context;
81  int                   error;
82
83  /*
84   *  Error check parameters before disabling interrupts.
85   */
86  if ( !set )
87    rtems_set_errno_and_return_minus_one( EINVAL );
88
89  _Thread_queue_Context_initialize( &queue_context );
90
91  /*  NOTE: This is very specifically a RELATIVE not ABSOLUTE time
92   *        in the Open Group specification.
93   */
94
95  if ( timeout != NULL ) {
96    const struct timespec *end;
97
98    _Timecounter_Nanouptime( &uptime );
99    end = _Watchdog_Future_timespec( &uptime, timeout );
100    _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
101      &queue_context,
102      end
103    );
104  } else {
105    _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
106  }
107
108  /*
109   *  Initialize local variables.
110   */
111
112  the_info = ( info ) ? info : &signal_information;
113
114  executing = _Thread_Get_executing();
115  api = executing->API_Extensions[ THREAD_API_POSIX ];
116
117  /*
118   *  What if they are already pending?
119   */
120
121  /* API signals pending? */
122
123  _POSIX_signals_Acquire( &queue_context );
124  if ( *set & api->signals_pending ) {
125    /* XXX real info later */
126    the_info->si_signo = _POSIX_signals_Get_lowest( api->signals_pending );
127    _POSIX_signals_Clear_signals(
128      api,
129      the_info->si_signo,
130      the_info,
131      false,
132      false,
133      false
134    );
135    _POSIX_signals_Release( &queue_context );
136
137    the_info->si_code = SI_USER;
138    the_info->si_value.sival_int = 0;
139    return the_info->si_signo;
140  }
141
142  /* Process pending signals? */
143
144  if ( *set & _POSIX_signals_Pending ) {
145    signo = _POSIX_signals_Get_lowest( _POSIX_signals_Pending );
146    _POSIX_signals_Clear_signals( api, signo, the_info, true, false, false );
147    _POSIX_signals_Release( &queue_context );
148
149    the_info->si_signo = signo;
150    the_info->si_code = SI_USER;
151    the_info->si_value.sival_int = 0;
152    return signo;
153  }
154
155  the_info->si_signo = -1;
156
157  executing->Wait.option          = *set;
158  executing->Wait.return_argument = the_info;
159  _Thread_queue_Context_set_thread_state(
160    &queue_context,
161    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL
162  );
163  _Thread_queue_Enqueue(
164    &_POSIX_signals_Wait_queue.Queue,
165    POSIX_SIGNALS_TQ_OPERATIONS,
166    executing,
167    &queue_context
168  );
169
170  /*
171   * When the thread is set free by a signal, it is need to eliminate
172   * the signal.
173   */
174
175  _POSIX_signals_Clear_signals(
176    api,
177    the_info->si_signo,
178    the_info,
179    false,
180    false,
181    true
182  );
183
184  /* Set errno only if return code is not EINTR or
185   * if EINTR was caused by a signal being caught, which
186   * was not in our set.
187   */
188
189  error = _POSIX_Get_error_after_wait( executing );
190
191  if (
192    error != EINTR
193     || ( *set & signo_to_mask( the_info->si_signo ) ) == 0
194  ) {
195    if ( error == ETIMEDOUT ) {
196      error = EAGAIN;
197    }
198
199    rtems_set_errno_and_return_minus_one( error );
200  }
201
202  return the_info->si_signo;
203}
Note: See TracBrowser for help on using the repository browser.