source: rtems/cpukit/posix/src/nanosleep.c @ 9480815a

5
Last change on this file since 9480815a 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: 3.0 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 *  Copyright (c) 2016. Gedare Bloom.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <time.h>
24
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/threadqimpl.h>
27#include <rtems/score/timespec.h>
28#include <rtems/score/timecounter.h>
29#include <rtems/score/watchdogimpl.h>
30#include <rtems/posix/posixapi.h>
31#include <rtems/seterr.h>
32
33static Thread_queue_Control _Nanosleep_Pseudo_queue =
34  THREAD_QUEUE_INITIALIZER( "Nanosleep" );
35
36/*
37 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
38 */
39int nanosleep(
40  const struct timespec  *rqtp,
41  struct timespec        *rmtp
42)
43{
44  int eno;
45
46  eno = clock_nanosleep( CLOCK_REALTIME, 0, rqtp, rmtp );
47
48  if ( eno != 0 ) {
49    rtems_set_errno_and_return_minus_one( eno );
50  }
51
52  return eno;
53}
54
55/*
56 * High Resolution Sleep with Specifiable Clock, IEEE Std 1003.1, 2001
57 */
58int clock_nanosleep(
59  clockid_t               clock_id,
60  int                     flags,
61  const struct timespec  *rqtp,
62  struct timespec        *rmtp
63)
64{
65  Thread_queue_Context   queue_context;
66  struct timespec        uptime;
67  const struct timespec *end;
68  Thread_Control        *executing;
69  int                    eno;
70
71  if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
72    return ENOTSUP;
73  }
74
75  _Thread_queue_Context_initialize( &queue_context );
76  _Thread_queue_Context_set_thread_state(
77    &queue_context,
78    STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
79  );
80
81  if ( ( flags & TIMER_ABSTIME ) != 0 ) {
82    end = rqtp;
83
84    if ( clock_id == CLOCK_REALTIME ) {
85      _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
86        &queue_context,
87        end
88      );
89    } else {
90      _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
91        &queue_context,
92        end
93      );
94    }
95  } else {
96    _Timecounter_Nanouptime( &uptime );
97    end = _Watchdog_Future_timespec( &uptime, rqtp );
98    _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
99      &queue_context,
100      end
101    );
102  }
103
104  _Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
105  executing = _Thread_Executing;
106  _Thread_queue_Enqueue(
107    &_Nanosleep_Pseudo_queue.Queue,
108    &_Thread_queue_Operations_FIFO,
109    executing,
110    &queue_context
111  );
112  eno = _POSIX_Get_error_after_wait( executing );
113
114  if ( eno == ETIMEDOUT ) {
115    eno = 0;
116  }
117
118  if ( rmtp != NULL && ( flags & TIMER_ABSTIME ) == 0 ) {
119    if ( eno == EINTR ) {
120      struct timespec actual_end;
121
122      _Timecounter_Nanouptime( &actual_end );
123
124      if ( _Timespec_Less_than( &actual_end, end ) ) {
125        _Timespec_Subtract( &actual_end, end, rmtp );
126      } else {
127        _Timespec_Set_to_zero( rmtp );
128      }
129    } else {
130      _Timespec_Set_to_zero( rmtp );
131    }
132  }
133
134  return eno;
135}
Note: See TracBrowser for help on using the repository browser.