mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-21 17:36:15 +08:00
score: Change TOD_LATEST_YEAR to 2099
This simplifies the implementation a bit. Declare _TOD_Days_to_date[] in <rtems/score/todimpl.h>. Make _TOD_Days_per_month[] and _TOD_Days_since_last_leap_year[] static. Update #4338.
This commit is contained in:
@@ -22,11 +22,6 @@
|
||||
#include <rtems/score/todimpl.h>
|
||||
#include <rtems/rtems/clockimpl.h>
|
||||
|
||||
/* The following are inside RTEMS -- we are violating visibility!!!
|
||||
* Perhaps an API could be defined to get days since 1 Jan.
|
||||
*/
|
||||
extern const uint16_t _TOD_Days_to_date[2][13];
|
||||
|
||||
/*
|
||||
* Prototypes and routines used below
|
||||
*/
|
||||
@@ -75,7 +70,7 @@ int setRealTime(
|
||||
tod_temp = *tod;
|
||||
|
||||
days = (tod_temp.year - TOD_BASE_YEAR) * 365 + \
|
||||
_TOD_Days_to_date[0][tod_temp.month] + tod_temp.day - 1;
|
||||
_TOD_Days_to_date[1][tod_temp.month] + tod_temp.day - 1;
|
||||
if (tod_temp.month < 3)
|
||||
days += Leap_years_until_now (tod_temp.year - 1);
|
||||
else
|
||||
@@ -115,7 +110,7 @@ void getRealTime(
|
||||
|
||||
/* finding month and day */
|
||||
Leap_year = (((!(tod_temp.year%4)) && (tod_temp.year%100)) ||
|
||||
(!(tod_temp.year%400)))?1:0;
|
||||
(!(tod_temp.year%400)))?0:1;
|
||||
for (n=1; n<=12; n++) {
|
||||
if (days <= _TOD_Days_to_date[Leap_year][n+1]) {
|
||||
tod_temp.month = n;
|
||||
|
||||
@@ -142,12 +142,16 @@ extern "C" {
|
||||
* 32 bits can accept as latest point in time 2106-Feb-7 6:28:15
|
||||
* but to simplify the implementation, is was decided to only
|
||||
* check that the year is not greater than the year of this constant.
|
||||
* The year 2099 was chosen because all years evenly divisible by 4 from 1988
|
||||
* to 2099 are leap years. In this time frame, years evenly divisible by 100
|
||||
* are no leap years unless they are evenly divisible by 400. Thus the year
|
||||
* 2000 is a leap year.
|
||||
*
|
||||
* The internal realtime clock can run centuries longer but in
|
||||
* The internal CLOCK_REALTIME can run centuries longer but in
|
||||
* contrast to the POSIX API, the RTEMS Classic API does not
|
||||
* support this for efficiency reasons.
|
||||
*/
|
||||
#define TOD_LATEST_YEAR 2105
|
||||
#define TOD_LATEST_YEAR 2099
|
||||
|
||||
/**
|
||||
* @addtogroup RTEMSScoreTOD
|
||||
@@ -175,6 +179,14 @@ typedef struct {
|
||||
*/
|
||||
extern TOD_Control _TOD;
|
||||
|
||||
/**
|
||||
* @brief This array contains the number of days in all months up to the month
|
||||
* indicated by the index of the second dimension.
|
||||
*
|
||||
* The first dimension should be 0 for leap years, and 1 otherwise.
|
||||
*/
|
||||
extern const uint16_t _TOD_Days_to_date[ 2 ][ 13 ];
|
||||
|
||||
/**
|
||||
* @brief Locks the time of day mutex.
|
||||
*/
|
||||
@@ -215,6 +227,21 @@ static inline void _TOD_Release( ISR_lock_Context *lock_context )
|
||||
_Timecounter_Release( lock_context );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Maps the year to the leap year index.
|
||||
*
|
||||
* @param year is the year to map.
|
||||
*
|
||||
* @retval 0 The year is a leap year.
|
||||
*
|
||||
* @retval 1 The year is not a leap year.
|
||||
*/
|
||||
static inline size_t _TOD_Get_leap_year_index( uint32_t year )
|
||||
{
|
||||
_Assert( year % 4 != 0 || year % 100 != 0 || year % 400 == 0 );
|
||||
return ( ( year % 4 ) + 3 ) / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the time point is a valid new time of day for _TOD_Set().
|
||||
*
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#define RTEMS_DAYS_PER_YEAR (365UL)
|
||||
#define RTEMS_YEAR_BASE (1970UL)
|
||||
|
||||
extern const uint16_t _TOD_Days_to_date[2][13];
|
||||
|
||||
static bool _Leap_year(
|
||||
uint32_t year
|
||||
)
|
||||
@@ -64,9 +62,9 @@ static uint32_t _Year_day_as_month(
|
||||
uint32_t month = 0;
|
||||
|
||||
if ( _Leap_year( year ) )
|
||||
days_to_date = _TOD_Days_to_date[1];
|
||||
else
|
||||
days_to_date = _TOD_Days_to_date[0];
|
||||
else
|
||||
days_to_date = _TOD_Days_to_date[1];
|
||||
|
||||
days_to_date += 2;
|
||||
|
||||
|
||||
@@ -23,16 +23,9 @@
|
||||
#include <rtems/rtems/clockimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
#define TOD_SECONDS_AT_2100_03_01_00_00 4107542400UL
|
||||
|
||||
/*
|
||||
* The following array contains the number of days in all months
|
||||
* up to the month indicated by the index of the second dimension.
|
||||
* The first dimension should be 1 for leap years, and 0 otherwise.
|
||||
*/
|
||||
const uint16_t _TOD_Days_to_date[2][13] = {
|
||||
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
|
||||
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
|
||||
const uint16_t _TOD_Days_to_date[ 2 ][ 13 ] = {
|
||||
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 },
|
||||
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -48,21 +41,18 @@ Watchdog_Interval _TOD_To_seconds(
|
||||
const rtems_time_of_day *the_tod
|
||||
)
|
||||
{
|
||||
uint32_t time;
|
||||
uint32_t year_mod_4;
|
||||
uint32_t time;
|
||||
size_t leap_year_index;
|
||||
|
||||
time = the_tod->day - 1;
|
||||
year_mod_4 = the_tod->year & 3;
|
||||
|
||||
if ( year_mod_4 == 0 )
|
||||
time += _TOD_Days_to_date[ 1 ][ the_tod->month ];
|
||||
else
|
||||
time += _TOD_Days_to_date[ 0 ][ the_tod->month ];
|
||||
leap_year_index = _TOD_Get_leap_year_index( the_tod->year );
|
||||
time += _TOD_Days_to_date[ leap_year_index ][ the_tod->month ];
|
||||
|
||||
time += ( (the_tod->year - TOD_BASE_YEAR) / 4 ) *
|
||||
( (TOD_DAYS_PER_YEAR * 4) + 1);
|
||||
|
||||
time += _TOD_Days_since_last_leap_year[ year_mod_4 ];
|
||||
time += _TOD_Days_since_last_leap_year[ the_tod->year % 4 ];
|
||||
|
||||
time *= TOD_SECONDS_PER_DAY;
|
||||
|
||||
@@ -70,13 +60,6 @@ Watchdog_Interval _TOD_To_seconds(
|
||||
* TOD_SECONDS_PER_MINUTE;
|
||||
|
||||
time += the_tod->second;
|
||||
|
||||
/* The year 2100 is not a leap year */
|
||||
if ( time
|
||||
>= (TOD_SECONDS_AT_2100_03_01_00_00 - TOD_SECONDS_1970_THROUGH_1988)) {
|
||||
time -= TOD_SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
time += TOD_SECONDS_1970_THROUGH_1988;
|
||||
|
||||
return( time );
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
|
||||
/*
|
||||
* The following array contains the number of days in all months.
|
||||
* The first dimension should be 1 for leap years, and 0 otherwise.
|
||||
* The first dimension should be 0 for leap years, and 1 otherwise.
|
||||
* The second dimension should range from 1 to 12 for January to
|
||||
* February, respectively.
|
||||
* December, respectively.
|
||||
*/
|
||||
const uint32_t _TOD_Days_per_month[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
static const uint32_t _TOD_Days_per_month[ 2 ][ 13 ] = {
|
||||
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
rtems_status_code _TOD_Validate(
|
||||
@@ -40,6 +40,7 @@ rtems_status_code _TOD_Validate(
|
||||
TOD_Ticks_validation ticks_validation
|
||||
)
|
||||
{
|
||||
size_t leap_year_index;
|
||||
uint32_t days_in_month;
|
||||
uint32_t ticks_per_second;
|
||||
uint32_t ticks_mask;
|
||||
@@ -79,11 +80,8 @@ rtems_status_code _TOD_Validate(
|
||||
return RTEMS_INVALID_CLOCK;
|
||||
}
|
||||
|
||||
if (((the_tod->year % 4) == 0 && (the_tod->year % 100 != 0)) ||
|
||||
(the_tod->year % 400 == 0))
|
||||
days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ];
|
||||
else
|
||||
days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ];
|
||||
leap_year_index = _TOD_Get_leap_year_index( the_tod->year );
|
||||
days_in_month = _TOD_Days_per_month[ leap_year_index ][ the_tod->month ];
|
||||
|
||||
if ( the_tod->day > days_in_month ) {
|
||||
return RTEMS_INVALID_CLOCK;
|
||||
|
||||
@@ -143,13 +143,7 @@ static const uint32_t sample_seconds [] = {
|
||||
3979434495UL,
|
||||
4011056895UL,
|
||||
4042592895UL,
|
||||
4074128895UL,
|
||||
4105664895UL,
|
||||
4137200895UL,
|
||||
4168736895UL,
|
||||
4200272895UL,
|
||||
4231808895UL,
|
||||
4263431295UL
|
||||
4074128895UL
|
||||
};
|
||||
|
||||
static const rtems_time_of_day nearly_problem_2038 = {
|
||||
@@ -179,24 +173,6 @@ static const rtems_time_of_day tod_to_seconds_base = {
|
||||
.second = 15
|
||||
};
|
||||
|
||||
static const rtems_time_of_day nearly_problem_2106 = {
|
||||
.year = 2105,
|
||||
.month = 12,
|
||||
.day = 31,
|
||||
.hour = 23,
|
||||
.minute = 59,
|
||||
.second = 59
|
||||
};
|
||||
|
||||
static const rtems_time_of_day problem_2106 = {
|
||||
.year = 2106,
|
||||
.month = 1,
|
||||
.day = 1,
|
||||
.hour = 0,
|
||||
.minute = 0,
|
||||
.second = 0
|
||||
};
|
||||
|
||||
static const rtems_time_of_day problem_2100 = {
|
||||
.year = 2100,
|
||||
.month = 2,
|
||||
@@ -242,24 +218,15 @@ static void test_tod_to_seconds(void)
|
||||
static void test_problem_year(void)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
time_t zero = 0;
|
||||
time_t one = 1;
|
||||
time_t maybe_negative = zero - one;
|
||||
bool time_t_is_32_bit = sizeof(time_t) == 4;
|
||||
bool time_t_is_signed = maybe_negative < zero;
|
||||
|
||||
if (time_t_is_32_bit) {
|
||||
const rtems_time_of_day *nearly_problem = NULL;
|
||||
const rtems_time_of_day *problem = NULL;
|
||||
rtems_time_of_day now;
|
||||
|
||||
if (time_t_is_signed) {
|
||||
nearly_problem = &nearly_problem_2038;
|
||||
problem = &problem_2038;
|
||||
} else {
|
||||
nearly_problem = &nearly_problem_2106;
|
||||
problem = &problem_2106;
|
||||
}
|
||||
nearly_problem = &nearly_problem_2038;
|
||||
problem = &problem_2038;
|
||||
|
||||
sc = rtems_clock_set(nearly_problem);
|
||||
ASSERT_SC(sc);
|
||||
@@ -282,7 +249,7 @@ static void test_leap_year(void)
|
||||
const rtems_time_of_day *problem2 = &problem_2100_2;
|
||||
// 2100 is not a leap year, so it should have 28 days
|
||||
test_status = _TOD_Validate(problem, TOD_ENABLE_TICKS_VALIDATION);
|
||||
rtems_test_assert(test_status == RTEMS_SUCCESSFUL);
|
||||
rtems_test_assert(test_status == RTEMS_INVALID_CLOCK);
|
||||
test_status = _TOD_Validate(problem2, TOD_ENABLE_TICKS_VALIDATION);
|
||||
rtems_test_assert(test_status == RTEMS_INVALID_CLOCK);
|
||||
}
|
||||
@@ -309,7 +276,7 @@ static void test_every_day(void)
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_time_of_day now;
|
||||
|
||||
for (every_day.year = 1988; every_day.year <= 2100; ++every_day.year) {
|
||||
for (every_day.year = 1988; every_day.year <= 2099; ++every_day.year) {
|
||||
int leap_year = test_year_is_leap_year(every_day.year) ? 1 : 0;
|
||||
for (every_day.month = 1; every_day.month <= 12; ++every_day.month) {
|
||||
int days = days_per_month[leap_year][every_day.month - 1];
|
||||
|
||||
@@ -89,7 +89,7 @@ rtems_task Init(
|
||||
directive_failed( status, "rtems_clock_get_tod" );
|
||||
print_time( "TA1 - rtems_clock_get_tod - ", &time, " - RTEMS_SUCCESSFUL\n" );
|
||||
|
||||
build_time( &time, 12, 31, 2100, 23, 59, 59, 0 );
|
||||
build_time( &time, 12, 31, 2099, 23, 59, 59, 0 );
|
||||
status = rtems_clock_set( &time );
|
||||
directive_failed( status, "rtems_clock_set" );
|
||||
print_time( "TA1 - rtems_clock_set - ", &time, " - RTEMS_SUCCESSFUL\n" );
|
||||
@@ -98,10 +98,10 @@ rtems_task Init(
|
||||
directive_failed( status, "rtems_clock_set" );
|
||||
print_time( "TA1 - rtems_clock_get_tod - ", &time, " - RTEMS_SUCCESSFUL\n" );
|
||||
|
||||
build_time( &time, 12, 31, 2099, 23, 59, 59, 0 );
|
||||
build_time( &time, 1, 1, 2100, 0, 0, 0, 0 );
|
||||
status = rtems_clock_set( &time );
|
||||
directive_failed( status, "rtems_clock_set" );
|
||||
print_time( "TA1 - rtems_clock_set - ", &time, " - RTEMS_SUCCESSFUL\n" );
|
||||
fatal_directive_status( status, RTEMS_INVALID_CLOCK, "rtems_clock_set" );
|
||||
print_time( "TA1 - rtems_clock_set - ", &time, " - RTEMS_INVALID_CLOCK\n" );
|
||||
status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
|
||||
status = rtems_clock_get_tod( &time );
|
||||
directive_failed( status, "rtems_clock_set" );
|
||||
|
||||
Reference in New Issue
Block a user