source: rtems/cpukit/posix/src/time.c @ df8d1440

4.104.114.84.95
Last change on this file since df8d1440 was df8d1440, checked in by Joel Sherrill <joel.sherrill@…>, on 07/02/96 at 18:13:59

* empty log message *

  • Property mode set to 100644
File size: 6.7 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  if ( !_TOD_Is_set() )
68    set_errno_and_return_minus_one( EINVAL );
69
70  /*
71   *  Internally the RTEMS epoch is 1988.  This must be taken into account.
72   */
73
74  seconds_since_epoch = _TOD_Seconds_since_epoch;
75     
76  seconds_since_epoch += POSIX_TIME_SECONDS_1970_THROUGH_1988;
77
78  if ( tloc )
79    *tloc = seconds_since_epoch;
80
81  return seconds_since_epoch;
82}
83
84/*
85 *  14.2.1 Clocks, P1003.1b-1993, p. 263
86 */
87
88int clock_settime(
89  clockid_t              clock_id,
90  const struct timespec *tp
91)
92{
93  struct tm         split_time;
94  TOD_Control       tod;
95  Watchdog_Interval seconds;
96
97  assert( tp );
98
99  switch ( clock_id ) {
100 
101    case CLOCK_REALTIME:
102      (void) gmtime_r( &tp->tv_sec, &split_time );
103 
104      /*
105       *  Convert the tm structure format to that used by the TOD Handler
106       *
107       *  NOTE: TOD Handler does not honor leap seconds.
108       */
109
110      tod.year   = split_time.tm_year + 1900;  /* RHS is years since 1900 */
111      tod.month  = split_time.tm_mon + 1;      /* RHS uses 0-11 */
112      tod.day    = split_time.tm_mday;
113      tod.hour   = split_time.tm_hour;
114      tod.minute = split_time.tm_min;
115      tod.second = split_time.tm_sec;  /* RHS allows 0-61 for leap seconds */
116
117      tod.ticks  = (tp->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
118                      _TOD_Microseconds_per_tick;
119
120      if ( !_TOD_Validate( &tod ) )
121        set_errno_and_return_minus_one( EINVAL );
122 
123      /*
124       *  We can't use the tp->tv_sec field because it is based on
125       *  a different EPOCH.
126       */
127
128      seconds = _TOD_To_seconds( &tod );
129      _Thread_Disable_dispatch();
130        _TOD_Set( &tod, seconds );
131      _Thread_Enable_dispatch();
132      break;
133 
134#ifdef _POSIX_CPUTIME
135    case CLOCK_PROCESS_CPUTIME:
136      return POSIX_NOT_IMPLEMENTED();
137      break;
138#endif
139 
140#ifdef _POSIX_THREAD_CPUTIME
141    case CLOCK_THREAD_CPUTIME:
142      return POSIX_NOT_IMPLEMENTED();
143      break;
144#endif
145    default:
146      set_errno_and_return_minus_one( EINVAL );
147 
148  }
149  return 0;
150}
151
152/*
153 *  14.2.1 Clocks, P1003.1b-1993, p. 263
154 */
155
156int clock_gettime(
157  clockid_t        clock_id,
158  struct timespec *tp
159)
160{
161  ISR_Level      level;
162  time_t         seconds;
163  long           ticks;
164
165  assert( tp );
166
167  switch ( clock_id ) {
168
169    case CLOCK_REALTIME:
170      if ( !_TOD_Is_set() )    /* XXX does posix allow it to not be set? */
171        set_errno_and_return_minus_one( EINVAL );
172 
173      _ISR_Disable( level );
174        seconds = _TOD_Seconds_since_epoch;
175        ticks   = _TOD_Current.ticks;
176      _ISR_Enable( level );
177 
178      tp->tv_sec  = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
179      tp->tv_nsec = ticks * _TOD_Microseconds_per_tick *
180                      TOD_NANOSECONDS_PER_MICROSECOND;
181      break;
182
183#ifdef _POSIX_CPUTIME
184    case CLOCK_PROCESS_CPUTIME:
185      /* don't base this on _Watchdog_Ticks_since_boot--duration is too short*/
186      return POSIX_NOT_IMPLEMENTED();
187      break;
188#endif
189
190#ifdef _POSIX_THREAD_CPUTIME
191    case CLOCK_THREAD_CPUTIME:
192      return POSIX_NOT_IMPLEMENTED();
193      break;
194#endif
195    default:
196      set_errno_and_return_minus_one( EINVAL );
197
198  }
199  return 0;
200}
201
202/*
203 *  14.2.1 Clocks, P1003.1b-1993, p. 263
204 */
205
206int clock_getres(
207  clockid_t        clock_id,
208  struct timespec *res
209)
210{
211  switch ( clock_id ) {
212 
213    /*
214     *  All time in rtems is based on the same clock tick.
215     */
216
217    case CLOCK_REALTIME:
218    case CLOCK_PROCESS_CPUTIME:
219    case CLOCK_THREAD_CPUTIME:
220      if ( res )
221        _POSIX_Interval_to_timespec( _TOD_Microseconds_per_tick, res );
222      break;
223 
224    default:
225      set_errno_and_return_minus_one( EINVAL );
226 
227  }
228  return 0;
229}
230
231/*
232 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
233 */
234
235int nanosleep(
236  const struct timespec  *rqtp,
237  struct timespec        *rmtp
238)
239{
240  Watchdog_Interval ticks;
241
242  /*
243   *  Return EAGAIN if the delay interval is negative. 
244   *
245   *  NOTE:  This behavior is beyond the POSIX specification. 
246   *         FSU pthreads shares this behavior.
247   */
248
249  if ( rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 )
250    set_errno_and_return_minus_one( EAGAIN );
251
252  if ( rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
253    set_errno_and_return_minus_one( EINVAL );
254 
255/* XXX this is interruptible by a posix signal */
256
257  ticks = _POSIX_Timespec_to_interval( rqtp );
258
259  /*
260   *  This behavior is also beyond the POSIX specification but is
261   *  consistent with the RTEMS api and yields desirable behavior.
262   */
263
264  if ( !ticks ) {
265    _Thread_Yield_processor();
266    _Thread_Dispatch();
267    return 0;
268  }
269 
270  _Thread_Disable_dispatch();
271    _Thread_Set_state(
272      _Thread_Executing,
273      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
274    );
275    _Watchdog_Initialize(
276      &_Thread_Executing->Timer,
277      _Thread_Delay_ended,          /* XXX may need to be POSIX specific */
278      _Thread_Executing->Object.id,
279      NULL
280    );
281    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
282  _Thread_Enable_dispatch();
283
284  /* calculate time remaining */
285
286  if ( rmtp ) {
287    ticks -=
288      _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
289
290    _POSIX_Interval_to_timespec( ticks, rmtp );
291  }
292
293  return 0;                    /* XXX should account for signal */
294
295}
296
297/*
298 *  20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
299 */
300
301int clock_getcpuclockid(
302  pid_t      pid,
303  clockid_t *clock_id
304)
305{
306  return POSIX_NOT_IMPLEMENTED();
307}
308
309/*
310 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
311 */
312
313int clock_setenable_attr(
314  clockid_t    clock_id,
315  int          attr
316)
317{
318  return POSIX_NOT_IMPLEMENTED();
319}
320
321/*
322 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
323 */
324
325int clock_getenable_attr(
326  clockid_t    clock_id,
327  int         *attr
328)
329{
330  return POSIX_NOT_IMPLEMENTED();
331}
Note: See TracBrowser for help on using the repository browser.