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

4.104.114.84.95
Last change on this file since f3e19146 was f3e19146, checked in by Joel Sherrill <joel.sherrill@…>, on 08/15/96 at 18:58:09

clock_gettime: changed assert condition to a standard error code

clock_getres: now checking for a null pointer being passed in

  • Property mode set to 100644
File size: 6.9 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
250  if ( !rqtp )
251    set_errno_and_return_minus_one( EINVAL );
252
253  /*
254   *  Return EAGAIN if the delay interval is negative. 
255   *
256   *  NOTE:  This behavior is beyond the POSIX specification. 
257   *         FSU pthreads shares this behavior.
258   */
259
260  if ( rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 )
261    set_errno_and_return_minus_one( EAGAIN );
262
263  if ( rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
264    set_errno_and_return_minus_one( EINVAL );
265 
266  ticks = _POSIX_Timespec_to_interval( rqtp );
267
268  /*
269   *  This behavior is also beyond the POSIX specification but is
270   *  consistent with the RTEMS api and yields desirable behavior.
271   */
272
273  if ( !ticks ) {
274    _Thread_Yield_processor();
275    _Thread_Dispatch();
276    if ( rmtp ) {
277       rmtp->tv_sec = 0;
278       rmtp->tv_nsec = 0;
279    }
280    return 0;
281  }
282 
283  _Thread_Disable_dispatch();
284    _Thread_Set_state(
285      _Thread_Executing,
286      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
287    );
288    _Watchdog_Initialize(
289      &_Thread_Executing->Timer,
290      _Thread_Delay_ended,
291      _Thread_Executing->Object.id,
292      NULL
293    );
294    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
295  _Thread_Enable_dispatch();
296
297  /* calculate time remaining */
298
299  if ( rmtp ) {
300    ticks -=
301      _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
302
303    _POSIX_Interval_to_timespec( ticks, rmtp );
304
305    /*
306     *  If there is time remaining, then we were interrupted by a signal.
307     */
308
309    if ( ticks )
310      set_errno_and_return_minus_one( EINTR );
311  }
312
313  return 0;
314}
315
316/*PAGE
317 *
318 *  20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
319 */
320
321int clock_getcpuclockid(
322  pid_t      pid,
323  clockid_t *clock_id
324)
325{
326  return POSIX_NOT_IMPLEMENTED();
327}
328
329/*PAGE
330 *
331 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
332 */
333
334int clock_setenable_attr(
335  clockid_t    clock_id,
336  int          attr
337)
338{
339  return POSIX_NOT_IMPLEMENTED();
340}
341
342/*PAGE
343 *
344 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
345 */
346
347int clock_getenable_attr(
348  clockid_t    clock_id,
349  int         *attr
350)
351{
352  return POSIX_NOT_IMPLEMENTED();
353}
Note: See TracBrowser for help on using the repository browser.