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

4.104.114.84.95
Last change on this file since f48c9068 was f48c9068, checked in by Joel Sherrill <joel.sherrill@…>, on 08/13/96 at 14:24:00

removed errors for TOD not set yet.

made nanosleep return -1/EINTR for being interrupted for a signal.

  • 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  assert( tp );
170
171  switch ( clock_id ) {
172
173    case CLOCK_REALTIME:
174 
175      _ISR_Disable( level );
176        seconds = _TOD_Seconds_since_epoch;
177        ticks   = _TOD_Current.ticks;
178      _ISR_Enable( level );
179 
180      tp->tv_sec  = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
181      tp->tv_nsec = ticks * _TOD_Microseconds_per_tick *
182                      TOD_NANOSECONDS_PER_MICROSECOND;
183      break;
184
185#ifdef _POSIX_CPUTIME
186    case CLOCK_PROCESS_CPUTIME:
187      /* don't base this on _Watchdog_Ticks_since_boot--duration is too short*/
188      return POSIX_NOT_IMPLEMENTED();
189      break;
190#endif
191
192#ifdef _POSIX_THREAD_CPUTIME
193    case CLOCK_THREAD_CPUTIME:
194      return POSIX_NOT_IMPLEMENTED();
195      break;
196#endif
197    default:
198      set_errno_and_return_minus_one( EINVAL );
199
200  }
201  return 0;
202}
203
204/*PAGE
205 *
206 *  14.2.1 Clocks, P1003.1b-1993, p. 263
207 */
208
209int clock_getres(
210  clockid_t        clock_id,
211  struct timespec *res
212)
213{
214  if ( !res )
215      set_errno_and_return_minus_one( EINVAL );
216 
217  switch ( clock_id ) {
218 
219    /*
220     *  All time in rtems is based on the same clock tick.
221     */
222
223    case CLOCK_REALTIME:
224    case CLOCK_PROCESS_CPUTIME:
225    case CLOCK_THREAD_CPUTIME:
226      if ( res )
227        _POSIX_Interval_to_timespec( _TOD_Microseconds_per_tick, res );
228      break;
229 
230    default:
231      set_errno_and_return_minus_one( EINVAL );
232 
233  }
234  return 0;
235}
236
237/*PAGE
238 *
239 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
240 */
241
242int nanosleep(
243  const struct timespec  *rqtp,
244  struct timespec        *rmtp
245)
246{
247  Watchdog_Interval ticks;
248
249  if ( !rqtp )
250    set_errno_and_return_minus_one( EINVAL );
251
252  /*
253   *  Return EAGAIN if the delay interval is negative. 
254   *
255   *  NOTE:  This behavior is beyond the POSIX specification. 
256   *         FSU pthreads shares this behavior.
257   */
258
259  if ( rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 )
260    set_errno_and_return_minus_one( EAGAIN );
261
262  if ( rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
263    set_errno_and_return_minus_one( EINVAL );
264 
265  ticks = _POSIX_Timespec_to_interval( rqtp );
266
267  /*
268   *  This behavior is also beyond the POSIX specification but is
269   *  consistent with the RTEMS api and yields desirable behavior.
270   */
271
272  if ( !ticks ) {
273    _Thread_Yield_processor();
274    _Thread_Dispatch();
275    if ( rmtp ) {
276       rmtp->tv_sec = 0;
277       rmtp->tv_nsec = 0;
278    }
279    return 0;
280  }
281 
282  _Thread_Disable_dispatch();
283    _Thread_Set_state(
284      _Thread_Executing,
285      STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
286    );
287    _Watchdog_Initialize(
288      &_Thread_Executing->Timer,
289      _Thread_Delay_ended,
290      _Thread_Executing->Object.id,
291      NULL
292    );
293    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
294  _Thread_Enable_dispatch();
295
296  /* calculate time remaining */
297
298  if ( rmtp ) {
299    ticks -=
300      _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
301
302    _POSIX_Interval_to_timespec( ticks, rmtp );
303
304    /*
305     *  If there is time remaining, then we were interrupted by a signal.
306     */
307
308    if ( ticks )
309      set_errno_and_return_minus_one( EINTR );
310  }
311
312  return 0;
313}
314
315/*PAGE
316 *
317 *  20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
318 */
319
320int clock_getcpuclockid(
321  pid_t      pid,
322  clockid_t *clock_id
323)
324{
325  return POSIX_NOT_IMPLEMENTED();
326}
327
328/*PAGE
329 *
330 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
331 */
332
333int clock_setenable_attr(
334  clockid_t    clock_id,
335  int          attr
336)
337{
338  return POSIX_NOT_IMPLEMENTED();
339}
340
341/*PAGE
342 *
343 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
344 */
345
346int clock_getenable_attr(
347  clockid_t    clock_id,
348  int         *attr
349)
350{
351  return POSIX_NOT_IMPLEMENTED();
352}
Note: See TracBrowser for help on using the repository browser.