source: rtems/c/src/exec/posix/src/time.c @ aa48536

4.104.114.84.95
Last change on this file since aa48536 was 9a5cbef0, checked in by Joel Sherrill <joel.sherrill@…>, on 09/05/96 at 20:29:07

nanosleep: negative value for tv_sec is no longer an error. It now
is changed into being a 0 delay.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <assert.h>
6#include <time.h>
7#include <errno.h>
8
9#include <rtems/system.h>
10#include <rtems/score/isr.h>
11#include <rtems/score/thread.h>
12#include <rtems/score/tod.h>
13
14#include <rtems/posix/seterr.h>
15#include <rtems/posix/time.h>
16
17/*PAGE
18 *
19 *  _POSIX_Timespec_to_interval
20 */
21
22Watchdog_Interval _POSIX_Timespec_to_interval(
23  const struct timespec *time
24)
25{
26  Watchdog_Interval  ticks;
27
28  ticks  = (time->tv_sec * TOD_MICROSECONDS_PER_SECOND) /
29             _TOD_Microseconds_per_tick;
30
31  ticks += (time->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
32             _TOD_Microseconds_per_tick;
33
34  return ticks;
35}
36
37/*PAGE
38 *
39 *  _POSIX_Interval_to_timespec
40 */
41 
42void _POSIX_Interval_to_timespec(
43  Watchdog_Interval  ticks,
44  struct timespec   *time
45)
46{
47  unsigned32  usecs;
48
49  usecs = ticks * _TOD_Microseconds_per_tick;
50
51  time->tv_sec  = usecs / TOD_MICROSECONDS_PER_SECOND;
52  time->tv_nsec = (usecs % TOD_MICROSECONDS_PER_SECOND) *
53                    TOD_NANOSECONDS_PER_MICROSECOND;
54}
55
56/*PAGE
57 *
58 *  4.5.1 Get System Time, P1003.1b-1993, p. 91
59 */
60
61time_t time(
62  time_t   *tloc
63)
64{
65  time_t  seconds_since_epoch;
66
67  /*
68   *  No error is the time of day is not set.   For RTEMS the system time
69   *  starts out at the rtems epoch.
70   */
71
72  /*
73   *  Internally the RTEMS epoch is 1988.  This must be taken into account.
74   */
75
76  seconds_since_epoch = _TOD_Seconds_since_epoch;
77     
78  seconds_since_epoch += POSIX_TIME_SECONDS_1970_THROUGH_1988;
79
80  if ( tloc )
81    *tloc = seconds_since_epoch;
82
83  return seconds_since_epoch;
84}
85
86/*PAGE
87 *
88 *  14.2.1 Clocks, P1003.1b-1993, p. 263
89 */
90
91int clock_settime(
92  clockid_t              clock_id,
93  const struct timespec *tp
94)
95{
96  struct tm         split_time;
97  TOD_Control       tod;
98  Watchdog_Interval seconds;
99
100  assert( tp );
101
102  switch ( clock_id ) {
103 
104    case CLOCK_REALTIME:
105      (void) gmtime_r( &tp->tv_sec, &split_time );
106 
107      /*
108       *  Convert the tm structure format to that used by the TOD Handler
109       *
110       *  NOTE: TOD Handler does not honor leap seconds.
111       */
112
113      tod.year   = split_time.tm_year + 1900;  /* RHS is years since 1900 */
114      tod.month  = split_time.tm_mon + 1;      /* RHS uses 0-11 */
115      tod.day    = split_time.tm_mday;
116      tod.hour   = split_time.tm_hour;
117      tod.minute = split_time.tm_min;
118      tod.second = split_time.tm_sec;  /* RHS allows 0-61 for leap seconds */
119
120      tod.ticks  = (tp->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
121                      _TOD_Microseconds_per_tick;
122
123      if ( !_TOD_Validate( &tod ) )
124        set_errno_and_return_minus_one( EINVAL );
125 
126      /*
127       *  We can't use the tp->tv_sec field because it is based on
128       *  a different EPOCH.
129       */
130
131      seconds = _TOD_To_seconds( &tod );
132      _Thread_Disable_dispatch();
133        _TOD_Set( &tod, seconds );
134      _Thread_Enable_dispatch();
135      break;
136 
137#ifdef _POSIX_CPUTIME
138    case CLOCK_PROCESS_CPUTIME:
139      return POSIX_NOT_IMPLEMENTED();
140      break;
141#endif
142 
143#ifdef _POSIX_THREAD_CPUTIME
144    case CLOCK_THREAD_CPUTIME:
145      return POSIX_NOT_IMPLEMENTED();
146      break;
147#endif
148    default:
149      set_errno_and_return_minus_one( EINVAL );
150 
151  }
152  return 0;
153}
154
155/*PAGE
156 *
157 *  14.2.1 Clocks, P1003.1b-1993, p. 263
158 */
159
160int clock_gettime(
161  clockid_t        clock_id,
162  struct timespec *tp
163)
164{
165  ISR_Level      level;
166  time_t         seconds;
167  long           ticks;
168
169  if ( !tp )
170    set_errno_and_return_minus_one( EINVAL );
171
172  switch ( clock_id ) {
173
174    case CLOCK_REALTIME:
175 
176      _ISR_Disable( level );
177        seconds = _TOD_Seconds_since_epoch;
178        ticks   = _TOD_Current.ticks;
179      _ISR_Enable( level );
180 
181      tp->tv_sec  = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
182      tp->tv_nsec = ticks * _TOD_Microseconds_per_tick *
183                      TOD_NANOSECONDS_PER_MICROSECOND;
184      break;
185
186#ifdef _POSIX_CPUTIME
187    case CLOCK_PROCESS_CPUTIME:
188      /* don't base this on _Watchdog_Ticks_since_boot--duration is too short*/
189      return POSIX_NOT_IMPLEMENTED();
190      break;
191#endif
192
193#ifdef _POSIX_THREAD_CPUTIME
194    case CLOCK_THREAD_CPUTIME:
195      return POSIX_NOT_IMPLEMENTED();
196      break;
197#endif
198    default:
199      set_errno_and_return_minus_one( EINVAL );
200
201  }
202  return 0;
203}
204
205/*PAGE
206 *
207 *  14.2.1 Clocks, P1003.1b-1993, p. 263
208 */
209
210int clock_getres(
211  clockid_t        clock_id,
212  struct timespec *res
213)
214{
215  if ( !res )
216    set_errno_and_return_minus_one( EINVAL );
217 
218  switch ( clock_id ) {
219 
220    /*
221     *  All time in rtems is based on the same clock tick.
222     */
223
224    case CLOCK_REALTIME:
225    case CLOCK_PROCESS_CPUTIME:
226    case CLOCK_THREAD_CPUTIME:
227      if ( res )
228        _POSIX_Interval_to_timespec( _TOD_Microseconds_per_tick, res );
229      break;
230 
231    default:
232      set_errno_and_return_minus_one( EINVAL );
233 
234  }
235  return 0;
236}
237
238/*PAGE
239 *
240 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
241 */
242
243int nanosleep(
244  const struct timespec  *rqtp,
245  struct timespec        *rmtp
246)
247{
248  Watchdog_Interval  ticks;
249  struct timespec   *the_rqtp;
250
251  if ( !rqtp )
252    set_errno_and_return_minus_one( EINVAL );
253
254  the_rqtp = (struct timespec *)rqtp;
255
256  /*
257   *  Return EAGAIN if the delay interval is negative. 
258   *
259   *  NOTE:  This behavior is beyond the POSIX specification. 
260   *         FSU pthreads shares this behavior.
261   */
262
263  if ( the_rqtp->tv_sec < 0 )
264    the_rqtp->tv_sec = 0;
265
266  if ( /* the_rqtp->tv_sec < 0 || */ the_rqtp->tv_nsec < 0 )
267    set_errno_and_return_minus_one( EAGAIN );
268
269  if ( the_rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
270    set_errno_and_return_minus_one( EINVAL );
271 
272  ticks = _POSIX_Timespec_to_interval( the_rqtp );
273
274  /*
275   *  This behavior is also beyond the POSIX specification but is
276   *  consistent with the RTEMS api and yields desirable behavior.
277   */
278
279  if ( !ticks ) {
280    _Thread_Yield_processor();
281    _Thread_Dispatch();
282    if ( rmtp ) {
283       rmtp->tv_sec = 0;
284       rmtp->tv_nsec = 0;
285    }
286    return 0;
287  }
288 
289  _Thread_Disable_dispatch();
290    _Thread_Set_state(
291      _Thread_Executing,
292      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
293    );
294    _Watchdog_Initialize(
295      &_Thread_Executing->Timer,
296      _Thread_Delay_ended,
297      _Thread_Executing->Object.id,
298      NULL
299    );
300    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
301  _Thread_Enable_dispatch();
302
303  /* calculate time remaining */
304
305  if ( rmtp ) {
306    ticks -=
307      _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
308
309    _POSIX_Interval_to_timespec( ticks, rmtp );
310
311    /*
312     *  If there is time remaining, then we were interrupted by a signal.
313     */
314
315    if ( ticks )
316      set_errno_and_return_minus_one( EINTR );
317  }
318
319  return 0;
320}
321
322/*PAGE
323 *
324 *  20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
325 */
326
327int clock_getcpuclockid(
328  pid_t      pid,
329  clockid_t *clock_id
330)
331{
332  return POSIX_NOT_IMPLEMENTED();
333}
334
335/*PAGE
336 *
337 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
338 */
339
340int clock_setenable_attr(
341  clockid_t    clock_id,
342  int          attr
343)
344{
345  return POSIX_NOT_IMPLEMENTED();
346}
347
348/*PAGE
349 *
350 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
351 */
352
353int clock_getenable_attr(
354  clockid_t    clock_id,
355  int         *attr
356)
357{
358  return POSIX_NOT_IMPLEMENTED();
359}
Note: See TracBrowser for help on using the repository browser.