source: rtems/cpukit/rtems/src/clockgettod.c

Last change on this file was c4fb617, checked in by Joel Sherrill <joel@…>, on 02/16/22 at 22:28:43

cpukit/rtems/src/[a-r]*.c: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSImplClassicClock
7 *
8 * @brief This source file contains the implementation of
9 *   rtems_clock_get_tod().
10 */
11
12/*
13 *  COPYRIGHT (c) 1989-2007.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <rtems/rtems/clock.h>
43#include <rtems/score/todimpl.h>
44#include <rtems/config.h>
45
46#define RTEMS_SECS_PER_MINUTE (60UL)
47#define RTEMS_MINUTE_PER_HOUR (60UL)
48#define RTEMS_SECS_PER_HOUR   (RTEMS_SECS_PER_MINUTE * RTEMS_MINUTE_PER_HOUR)
49#define RTEMS_HOURS_PER_DAY   (24UL)
50#define RTEMS_SECS_PER_DAY    (RTEMS_SECS_PER_HOUR * RTEMS_HOURS_PER_DAY)
51#define RTEMS_DAYS_PER_YEAR   (365UL)
52#define RTEMS_YEAR_BASE       (1970UL)
53
54static bool _Leap_year(
55  uint32_t year
56)
57{
58  return (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0);
59}
60
61static uint32_t _Leap_years_before(
62  uint32_t year
63)
64{
65  year -= 1;
66  return (year / 4) - (year / 100) + (year / 400);
67}
68
69static uint32_t _Leap_years_between(
70  uint32_t from, uint32_t to
71)
72{
73  return _Leap_years_before( to ) - _Leap_years_before( from + 1 );
74}
75
76static uint32_t _Year_day_as_month(
77  uint32_t year, uint32_t *day
78)
79{
80  const uint16_t* days_to_date;
81  uint32_t        month = 0;
82
83  if ( _Leap_year( year ) )
84    days_to_date = _TOD_Days_to_date[0];
85  else
86    days_to_date = _TOD_Days_to_date[1];
87
88  days_to_date += 2;
89
90  while (month < 11) {
91    if (*day < *days_to_date)
92      break;
93    ++month;
94    ++days_to_date;
95  }
96
97  *day -= *(days_to_date - 1);
98
99  return month;
100}
101
102rtems_status_code rtems_clock_get_tod(
103  rtems_time_of_day  *time_of_day
104)
105{
106  struct timeval now;
107  uint32_t       days;
108  uint32_t       day_secs;
109  uint32_t       year;
110  uint32_t       year_days;
111  uint32_t       leap_years;
112
113  if ( !time_of_day )
114    return RTEMS_INVALID_ADDRESS;
115
116  if ( !_TOD_Is_set() )
117    return RTEMS_NOT_DEFINED;
118
119  /* Obtain the current time */
120  _TOD_Get_timeval( &now );
121
122  /*
123   * How many days and how many seconds in the day?
124   *
125   * A 32-bit integer can represent enough days for several 1000 years.  When
126   * the current time is valid, the integer conversions below are well defined.
127   */
128  days = (uint32_t) ( now.tv_sec / RTEMS_SECS_PER_DAY );
129  day_secs = (uint32_t) ( now.tv_sec % RTEMS_SECS_PER_DAY );
130
131  /* How many non-leap year years ? */
132  year = ( days / RTEMS_DAYS_PER_YEAR ) + RTEMS_YEAR_BASE;
133
134  /* Determine the number of leap years. */
135  leap_years = _Leap_years_between( RTEMS_YEAR_BASE, year );
136
137  /* Adjust the remaining number of days based on the leap years. */
138  year_days = ( days - leap_years ) % RTEMS_DAYS_PER_YEAR;
139
140  /* Adjust the year and days in the year if in the leap year overflow. */
141  if ( leap_years > ( days % RTEMS_DAYS_PER_YEAR ) ) {
142    year -= 1;
143    if ( _Leap_year( year ) ) {
144      year_days += 1;
145    }
146  }
147
148  time_of_day->year   = year;
149  time_of_day->month  = _Year_day_as_month( year, &year_days ) + 1;
150  time_of_day->day    = year_days + 1;
151  time_of_day->hour   = day_secs / RTEMS_SECS_PER_HOUR;
152  time_of_day->minute = day_secs % RTEMS_SECS_PER_HOUR;
153  time_of_day->second = time_of_day->minute % RTEMS_SECS_PER_MINUTE;
154  time_of_day->minute = time_of_day->minute / RTEMS_SECS_PER_MINUTE;
155  time_of_day->ticks  = now.tv_usec /
156    rtems_configuration_get_microseconds_per_tick( );
157
158  return RTEMS_SUCCESSFUL;
159}
Note: See TracBrowser for help on using the repository browser.