source: rtems/cpukit/include/rtems/score/todimpl.h @ 7bbbe42

Last change on this file since 7bbbe42 was 7bbbe42, checked in by Frank Kühndel <frank.kuehndel@…>, on 04/08/21 at 13:41:15

clock:_TOD_To_seconds(): Fix year 2514 overflow

This patch fixes issue #4338 by changing _TOD_Validate()
to only accept years till 2105. This requires another patch
to change the documentation of rtems_clock_set() and other
affected API functions (indicating the end date is 2105 not 2514).

I tried to support till year 2514 but it turned out that
this needs changing the Timer Manager too. That in turn
would mean to change _TOD_Seconds_since_epoch( void )
from 32 to 64 bit. Sebastian pointed out that a naive extension
leads to trouble with 32 bit processors. He deemed a safe
re-implementation too costly performance wise considering
that year 2106 is far away and current binaries using RTEMS
Classic API are unlikely to be in use by 2106.

The constant TOD_SECONDS_AT_2100_03_01_00_00 in
cpukit/rtems/src/clocktodtoseconds.c happens to be wrong by
1 hour. When setting the date 2100-Feb-28 23:59:59 and then
reading the date again you will find yourself in 2100-Feb-27.

Update #4338

  • Property mode set to 100644
File size: 10.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreTOD
5 * @ingroup RTEMSScoreTODHooks
6 *
7 * @brief This header file provides the interfaces of the
8 *   @ref RTEMSScoreTOD and the @ref RTEMSScoreTODHooks.
9 */
10
11/*
12 *  COPYRIGHT (c) 1989-2009.
13 *  On-Line Applications Research Corporation (OAR).
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#ifndef _RTEMS_SCORE_TODIMPL_H
21#define _RTEMS_SCORE_TODIMPL_H
22
23#include <rtems/score/status.h>
24#include <rtems/score/timestamp.h>
25#include <rtems/score/timecounterimpl.h>
26#include <rtems/score/watchdog.h>
27
28#include <sys/time.h>
29#include <time.h>
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35/**
36 * @defgroup RTEMSScoreTOD Time of Day Handler
37 *
38 * @ingroup RTEMSScore
39 *
40 * @brief This group contains the Time of Day Handler implementation.
41 *
42 * The following constants are related to the time of day and are
43 * independent of RTEMS.
44 *
45 * @{
46 */
47
48/**
49 *  This constant represents the number of seconds in a minute.
50 */
51#define TOD_SECONDS_PER_MINUTE (uint32_t)60
52
53/**
54 *  This constant represents the number of minutes per hour.
55 */
56#define TOD_MINUTES_PER_HOUR   (uint32_t)60
57
58/**
59 *  This constant represents the number of months in a year.
60 */
61#define TOD_MONTHS_PER_YEAR    (uint32_t)12
62
63/**
64 *  This constant represents the number of days in a non-leap year.
65 */
66#define TOD_DAYS_PER_YEAR      (uint32_t)365
67
68/**
69 *  This constant represents the number of hours per day.
70 */
71#define TOD_HOURS_PER_DAY      (uint32_t)24
72
73/**
74 *  This constant represents the number of seconds in a day which does
75 *  not include a leap second.
76 */
77#define TOD_SECONDS_PER_DAY    (uint32_t) (TOD_SECONDS_PER_MINUTE * \
78                                TOD_MINUTES_PER_HOUR   * \
79                                TOD_HOURS_PER_DAY)
80
81/**
82 *  This constant represents the number of seconds in a non-leap year.
83 */
84#define TOD_SECONDS_PER_NON_LEAP_YEAR (365 * TOD_SECONDS_PER_DAY)
85
86/**
87 *  This constant represents the number of millisecond in a second.
88 */
89#define TOD_MILLISECONDS_PER_SECOND     (uint32_t)1000
90
91/**
92 *  This constant represents the number of microseconds in a second.
93 */
94#define TOD_MICROSECONDS_PER_SECOND     (uint32_t)1000000
95
96/**
97 *  This constant represents the number of nanoseconds in a second.
98 */
99#define TOD_NANOSECONDS_PER_SECOND      (uint32_t)1000000000
100
101/**
102 *  This constant represents the number of nanoseconds in a mircosecond.
103 */
104#define TOD_NANOSECONDS_PER_MICROSECOND (uint32_t)1000
105
106/**@}*/
107
108/**
109 *  Seconds from January 1, 1970 to January 1, 1988.  Used to account for
110 *  differences between POSIX API and RTEMS core. The timespec format time
111 *  is kept in POSIX compliant form.
112 */
113#define TOD_SECONDS_1970_THROUGH_1988 \
114  (((1987 - 1970 + 1)  * TOD_SECONDS_PER_NON_LEAP_YEAR) + \
115  (4 * TOD_SECONDS_PER_DAY))
116
117/**
118 *  @brief Earliest year to which an time of day can be initialized.
119 *
120 *  The following constant define the earliest year to which an
121 *  time of day can be initialized.  This is considered the
122 *  epoch.
123 */
124#define TOD_BASE_YEAR 1988
125
126/**
127 *  @brief Latest year to which a time of day can be initialized.
128 *
129 *  The following constant defines the latest year to which an
130 *  RTEMS time of day can be set using rtems_clock_set().
131 *
132 *  32 bits can accept as latest point in time 2106-Feb-7 6:28:15
133 *  but to simplify the implementation, is was decided to only
134 *  check that the year is not greater than the year of this constant.
135 *
136 *  The internal realtime clock can run centuries longer but in
137 *  contrast to the POSIX API, the RTEMS Classic API does not
138 *  support this for efficiency reasons.
139 */
140#define TOD_LATEST_YEAR 2105
141
142/**
143 * @addtogroup RTEMSScoreTOD
144 *
145 * This handler encapsulates functionality used to manage time of day.
146 *
147 * @{
148 */
149
150/**
151 *  @brief TOD control.
152 */
153typedef struct {
154  /**
155   *  @brief Indicates if the time of day is set.
156   *
157   *  This is true if the application has set the current
158   *  time of day, and false otherwise.
159   */
160  bool is_set;
161} TOD_Control;
162
163/**
164 * @brief TOD Management information
165 */
166extern TOD_Control _TOD;
167
168/**
169 * @brief Locks the time of day mutex.
170 */
171void _TOD_Lock( void );
172
173/**
174 * @brief Unlocks the time of day mutex.
175 */
176void _TOD_Unlock( void );
177
178/**
179 * @brief Checks if api mutex is owner of the time of day mutex.
180 *
181 * @retval true It is owner of the time of day mutex.
182 * @retval false It is not owner of the time of day mutex.
183 */
184#if defined(RTEMS_DEBUG)
185bool _TOD_Is_owner( void );
186#endif
187
188/**
189 * @brief Acquires the lock context for the timecounter.
190 *
191 * @param lock_context The lock to acquire.
192 */
193static inline void _TOD_Acquire( ISR_lock_Context *lock_context )
194{
195  _Timecounter_Acquire( lock_context );
196}
197
198/**
199 * @brief Releases the lock context for the timecounter.
200 *
201 * @param lock_context The lock to release.
202 */
203static inline void _TOD_Release( ISR_lock_Context *lock_context )
204{
205  _Timecounter_Release( lock_context );
206}
207
208/**
209 * @brief Sets the time of day.
210 *
211 * The caller must be the owner of the TOD lock.
212 *
213 * @param tod The new time of day in timespec format representing
214 *   the time since UNIX Epoch.
215 * @param lock_context The ISR lock context used for the corresponding
216 *   _TOD_Acquire().  The caller must be the owner of the TOD lock.  This
217 *   function will release the TOD lock.
218 *
219 * @retval STATUS_SUCCESSFUL Successful operation.
220 * @retval other Some error occurred.
221 */
222Status_Control _TOD_Set(
223  const struct timespec *tod,
224  ISR_lock_Context      *lock_context
225);
226
227/**
228 * @brief Gets the current time in the timespec format.
229 *
230 * @param[out] time The value gathered by the request.
231 */
232static inline void _TOD_Get(
233  struct timespec *tod
234)
235{
236  _Timecounter_Nanotime( tod );
237}
238
239/**
240 * @brief Gets the system uptime with potential accuracy to the nanosecond.
241 *
242 * This routine returns the system uptime with potential accuracy
243 * to the nanosecond.
244 *
245 * The initial uptime value is undefined.
246 *
247 * @param[out] time Is a pointer to the uptime after the method call.
248 */
249static inline void _TOD_Get_uptime(
250  Timestamp_Control *time
251)
252{
253  *time = _Timecounter_Sbinuptime();
254}
255
256/**
257 * @brief Gets the system uptime with potential accuracy to the nanosecond.
258 *
259 * The initial uptime value is zero.
260 *
261 * @param[out] time Is a pointer to the uptime after the method call.
262 */
263static inline void _TOD_Get_zero_based_uptime(
264  Timestamp_Control *time
265)
266{
267  *time = _Timecounter_Sbinuptime() - SBT_1S;
268}
269
270/**
271 * @brief Gets the system uptime with potential accuracy to the nanosecond.
272 *
273 * The initial uptime value is zero.
274 *
275 * @param[out] time Is a pointer to the uptime after the method call.
276 */
277static inline void _TOD_Get_zero_based_uptime_as_timespec(
278  struct timespec *time
279)
280{
281  _Timecounter_Nanouptime( time );
282  --time->tv_sec;
283}
284
285/**
286 * @brief Returns Number of seconds Since RTEMS epoch.
287 *
288 * The following contains the number of seconds from 00:00:00
289 * January 1, TOD_BASE_YEAR until the current time of day.
290 *
291 * @return The number of seconds since RTEMS epoch.
292 */
293static inline uint32_t _TOD_Seconds_since_epoch( void )
294{
295  return (uint32_t) _Timecounter_Time_second;
296}
297
298/**
299 * @brief Gets number of ticks in a second.
300 *
301 * This method returns the number of ticks in a second.
302 *
303 * @note If the clock tick value does not multiply evenly into a second
304 *       then this number of ticks will be slightly shorter than a second.
305 *
306 * @return The number of ticks in a second.
307 */
308uint32_t TOD_TICKS_PER_SECOND_method(void);
309
310/**
311 *  @brief Gets number of ticks in a second.
312 *
313 *  This method exists to hide the fact that TOD_TICKS_PER_SECOND can not
314 *  be implemented as a macro in a .h file due to visibility issues.
315 *  The Configuration Table is not available to SuperCore .h files but
316 *  is available to their .c files.
317 */
318#define TOD_TICKS_PER_SECOND TOD_TICKS_PER_SECOND_method()
319
320/**
321 * @brief This routine returns a timeval based upon the internal timespec
322 *      format TOD.
323 *
324 * @param[out] time The timeval to be filled in by the method.
325 */
326RTEMS_INLINE_ROUTINE void _TOD_Get_timeval(
327  struct timeval *time
328)
329{
330  _Timecounter_Microtime( time );
331}
332
333/**
334 * @brief Adjusts the Time of Time.
335 *
336 * This method is used to adjust the current time of day by the
337 * specified amount.
338 *
339 * @param delta is the amount to adjust.
340 */
341void _TOD_Adjust(
342  const struct timespec *delta
343);
344
345/**
346 * @brief Check if the TOD is Set
347 *
348 * @retval true The time is set.
349 * @retval false The time is not set.
350 */
351RTEMS_INLINE_ROUTINE bool _TOD_Is_set( void )
352{
353  return _TOD.is_set;
354}
355
356/** @} */
357
358/**
359 * @defgroup RTEMSScoreTODHooks Time of Day Handler Action Hooks
360 *
361 * @ingroup RTEMSScoreTOD
362 *
363 * @brief This group contains the implementation to support Time of Day Handler
364 *   action hooks.
365 *
366 * The following support registering a hook which is invoked
367 * when the TOD is set. These can be used by a paravirtualized
368 * BSP to mirror time changes to the hosting environment or a
369 * regular BSP to program a real-time clock when the RTEMS TOD
370 * is set.
371 *
372 * @{
373 */
374
375/**
376 *  @brief Possible actions where a registered hook could be invoked
377 */
378typedef enum {
379  /**
380   *  @brief Constant to indicate the TOD is being set.
381   */
382  TOD_ACTION_SET_CLOCK
383} TOD_Action;
384
385/**
386 * @brief Structure to manage each TOD action hook
387 */
388typedef struct TOD_Hook {
389  /** This is the chain node portion of an object. */
390  Chain_Node Node;
391
392  /** This is the TOD action hook that is invoked. */
393  Status_Control ( *handler )( TOD_Action, const struct timespec * );
394} TOD_Hook;
395
396/**
397 * @brief Set of registered methods for TOD Actions
398 */
399extern Chain_Control _TOD_Hooks;
400
401/**
402 * @brief Add a TOD Action Hook
403 *
404 * This method is used to add a hook to the TOD action set.
405 *
406 * @brief hook is the action hook to register.
407 */
408void _TOD_Hook_Register(
409  TOD_Hook *hook
410);
411
412/**
413 * @brief Remove a TOD Action Hook
414 *
415 * This method is used to remove a hook from the TOD action set.
416 *
417 * @brief hook is the action hook to unregister.
418 */
419void _TOD_Hook_Unregister(
420  TOD_Hook *hook
421);
422
423/**
424 * @brief Run the TOD Action Hooks
425 *
426 * This method is used to invoke the set of TOD action hooks.
427 *
428 * @brief action The action which triggered this run.
429 * @brief tod The current time of day.
430 *
431 * @retval STATUS_SUCCESSFUL Successful operation.
432 * @retval other Some error occurred.
433 */
434Status_Control _TOD_Hook_Run(
435  TOD_Action             action,
436  const struct timespec *tod
437);
438
439
440/** @} */
441
442#ifdef __cplusplus
443}
444#endif
445
446#endif
447/* end of include file */
Note: See TracBrowser for help on using the repository browser.