source: rtems/cpukit/posix/src/nanosleep.c @ aa05cfbb

4.115
Last change on this file since aa05cfbb was aa05cfbb, checked in by Sebastian Huber <sebastian.huber@…>, on 05/11/15 at 12:56:49

score: Replace _Thread_Delay_ended()

Use _Thread_Timeout() instead. Use pseudo thread queue for nanosleep()
to deal with signals.

Close #2130.

  • Property mode set to 100644
File size: 2.8 KB
Line 
1/**
2 * @file
3 *
4 * @brief Suspends Execution of calling thread until Time elapses
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2015.
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 <time.h>
22#include <errno.h>
23
24#include <rtems/seterr.h>
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/threadqimpl.h>
27#include <rtems/score/timespec.h>
28#include <rtems/score/watchdogimpl.h>
29
30static Thread_queue_Control _Nanosleep_Pseudo_queue =
31  THREAD_QUEUE_FIFO_INITIALIZER( _Nanosleep_Pseudo_queue, "Nanosleep" );
32
33/*
34 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
35 */
36int nanosleep(
37  const struct timespec  *rqtp,
38  struct timespec        *rmtp
39)
40{
41  /*
42   * It is critical to obtain the executing thread after thread dispatching is
43   * disabled on SMP configurations.
44   */
45  Thread_Control  *executing;
46  Per_CPU_Control *cpu_self;
47
48  Watchdog_Interval  ticks;
49  Watchdog_Interval  elapsed;
50
51
52  /*
53   *  Return EINVAL if the delay interval is negative.
54   *
55   *  NOTE:  This behavior is beyond the POSIX specification.
56   *         FSU and GNU/Linux pthreads shares this behavior.
57   */
58  if ( !_Timespec_Is_valid( rqtp ) )
59    rtems_set_errno_and_return_minus_one( EINVAL );
60
61  /*
62   * Convert the timespec delay into the appropriate number of clock ticks.
63   */
64  ticks = _Timespec_To_ticks( rqtp );
65
66  executing = _Thread_Get_executing();
67
68  /*
69   *  A nanosleep for zero time is implemented as a yield.
70   *  This behavior is also beyond the POSIX specification but is
71   *  consistent with the RTEMS API and yields desirable behavior.
72   */
73  if ( !ticks ) {
74    cpu_self = _Thread_Dispatch_disable();
75      _Thread_Yield( executing );
76    _Thread_Dispatch_enable( cpu_self );
77    if ( rmtp ) {
78       rmtp->tv_sec = 0;
79       rmtp->tv_nsec = 0;
80    }
81    return 0;
82  }
83
84  /*
85   *  Block for the desired amount of time
86   */
87  _Thread_queue_Enqueue(
88    &_Nanosleep_Pseudo_queue,
89    executing,
90    STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL,
91    ticks,
92    0
93  );
94
95  /*
96   * Calculate the time that passed while we were sleeping and how
97   * much remains from what we requested.
98   */
99  elapsed = executing->Timer.stop_time - executing->Timer.start_time;
100  if ( elapsed >= ticks )
101    ticks = 0;
102  else
103    ticks -= elapsed;
104
105  /*
106   * If the user wants the time remaining, do the conversion.
107   */
108  if ( rmtp ) {
109    _Timespec_From_ticks( ticks, rmtp );
110  }
111
112  /*
113   *  Only when POSIX is enabled, can a sleep be interrupted.
114   */
115  #if defined(RTEMS_POSIX_API)
116    /*
117     *  If there is time remaining, then we were interrupted by a signal.
118     */
119    if ( ticks )
120      rtems_set_errno_and_return_minus_one( EINTR );
121  #endif
122
123  return 0;
124}
Note: See TracBrowser for help on using the repository browser.