summaryrefslogtreecommitdiffstats
path: root/c/src/exec/rtems/src/clock.c
blob: 01f61374cfe44af016a23de0430fe5921ea4f38e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 *  Clock Manager
 *
 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
 *  On-Line Applications Research Corporation (OAR).
 *  All rights assigned to U.S. Government, 1994.
 *
 *  This material may be reproduced by or for the U.S. Government pursuant
 *  to the copyright license under the clause at DFARS 252.227-7013.  This
 *  notice must appear in all copies of this file and its derivatives.
 *
 *  $Id$
 */

#include <rtems/system.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/clock.h>
#include <rtems/core/isr.h>
#include <rtems/core/thread.h>
#include <rtems/core/tod.h>
#include <rtems/core/watchdog.h>

/*PAGE
 *
 *  rtems_clock_get
 *
 *  This directive returns the current date and time.  If the time has
 *  not been set by a tm_set then an error is returned.
 *
 *  Input parameters:
 *    option      - which value to return
 *    time_buffer - pointer to output buffer (a time and date structure
 *                  or an interval)
 *
 *  Output parameters:
 *    time_buffer      - output filled in
 *    RTEMS_SUCCESSFUL - if successful
 *    error code       - if unsuccessful
 */

rtems_status_code rtems_clock_get(
  rtems_clock_get_options  option,
  void                    *time_buffer
)
{
  ISR_Level      level;
  rtems_interval tmp;

  switch ( option ) {
    case RTEMS_CLOCK_GET_TOD:
      if ( !_TOD_Is_set() )
        return RTEMS_NOT_DEFINED;

      *(rtems_time_of_day *)time_buffer = _TOD_Current;
      return RTEMS_SUCCESSFUL;

    case RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH:
      if ( !_TOD_Is_set() )
        return RTEMS_NOT_DEFINED;

      *(rtems_interval *)time_buffer = _TOD_Seconds_since_epoch;
      return RTEMS_SUCCESSFUL;

    case RTEMS_CLOCK_GET_TICKS_SINCE_BOOT:
      *(rtems_interval *)time_buffer = _TOD_Ticks_since_boot;
      return RTEMS_SUCCESSFUL;

    case RTEMS_CLOCK_GET_TICKS_PER_SECOND:
      *(rtems_interval *)time_buffer = _TOD_Ticks_per_second;
      return RTEMS_SUCCESSFUL;

    case RTEMS_CLOCK_GET_TIME_VALUE:
      if ( !_TOD_Is_set() )
        return RTEMS_NOT_DEFINED;

      _ISR_Disable( level );
        ((rtems_clock_time_value *)time_buffer)->seconds =
          _TOD_Seconds_since_epoch;
        tmp = _TOD_Current.ticks;
      _ISR_Enable( level );

      tmp *= _TOD_Microseconds_per_tick;
      ((rtems_clock_time_value *)time_buffer)->microseconds = tmp;

      return RTEMS_SUCCESSFUL;
  }

  return RTEMS_INTERNAL_ERROR;   /* should never get here */

}

/*PAGE
 *
 *  rtems_clock_set
 *
 *  This directive sets the date and time for this node.
 *
 *  Input parameters:
 *    time_buffer - pointer to the time and date structure
 *
 *  Output parameters:
 *    RTEMS_SUCCESSFUL - if successful
 *    error code        - if unsuccessful
 */

rtems_status_code rtems_clock_set(
  rtems_time_of_day *time_buffer
)
{
  rtems_interval     seconds;

  if ( _TOD_Validate( time_buffer ) ) {
    seconds = _TOD_To_seconds( time_buffer );
    _Thread_Disable_dispatch();
      _TOD_Set( time_buffer, seconds );
    _Thread_Enable_dispatch();
    return RTEMS_SUCCESSFUL;
  }
  return RTEMS_INVALID_CLOCK;
}

/*PAGE
 *
 *  rtems_clock_tick
 *
 *  This directive notifies the executve that a tick has occurred.
 *  When the tick occurs the time manager updates and maintains
 *  the calendar time, timeslicing, and any timeout delays.
 *
 *  Input parameters:  NONE
 *
 *  Output parameters:
 *    RTEMS_SUCCESSFUL - always succeeds
 *
 *  NOTE: This routine only works for leap-years through 2099.
 */

rtems_status_code rtems_clock_tick( void )
{
  _TOD_Tickle_ticks();

  _Watchdog_Tickle_ticks();

  _Thread_Tickle_timeslice();

  if ( _Thread_Is_context_switch_necessary() &&
       _Thread_Is_dispatching_enabled() )
    _Thread_Dispatch();

  return RTEMS_SUCCESSFUL;
}