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. --- bsps/bfin/shared/dev/rtc.c | 9 ++---- cpukit/include/rtems/score/todimpl.h | 31 ++++++++++++++++-- cpukit/rtems/src/clockgettod.c | 6 ++-- cpukit/rtems/src/clocktodtoseconds.c | 33 +++++-------------- cpukit/rtems/src/clocktodvalidate.c | 18 +++++------ testsuites/sptests/sp2038/init.c | 43 +++---------------------- testsuites/sptests/spclock_err02/init.c | 8 ++--- 7 files changed, 58 insertions(+), 90 deletions(-) diff --git a/bsps/bfin/shared/dev/rtc.c b/bsps/bfin/shared/dev/rtc.c index cb15ca0607..e3fb48b4bf 100644 --- a/bsps/bfin/shared/dev/rtc.c +++ b/bsps/bfin/shared/dev/rtc.c @@ -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; diff --git a/cpukit/include/rtems/score/todimpl.h b/cpukit/include/rtems/score/todimpl.h index f85689fd9c..acfec00186 100644 --- a/cpukit/include/rtems/score/todimpl.h +++ b/cpukit/include/rtems/score/todimpl.h @@ -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(). * diff --git a/cpukit/rtems/src/clockgettod.c b/cpukit/rtems/src/clockgettod.c index dea136d477..5058b42375 100644 --- a/cpukit/rtems/src/clockgettod.c +++ b/cpukit/rtems/src/clockgettod.c @@ -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; diff --git a/cpukit/rtems/src/clocktodtoseconds.c b/cpukit/rtems/src/clocktodtoseconds.c index 86e89f86eb..43bf6c59c5 100644 --- a/cpukit/rtems/src/clocktodtoseconds.c +++ b/cpukit/rtems/src/clocktodtoseconds.c @@ -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 ); diff --git a/cpukit/rtems/src/clocktodvalidate.c b/cpukit/rtems/src/clocktodvalidate.c index ddf310c3c0..9c94c16931 100644 --- a/cpukit/rtems/src/clocktodvalidate.c +++ b/cpukit/rtems/src/clocktodvalidate.c @@ -26,17 +26,18 @@ /* * 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( const rtems_time_of_day *the_tod ) { + size_t leap_year_index; uint32_t days_in_month; if ( the_tod == NULL ) { @@ -71,11 +72,8 @@ rtems_status_code _TOD_Validate( const rtems_time_of_day *the_tod ) 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; diff --git a/testsuites/sptests/sp2038/init.c b/testsuites/sptests/sp2038/init.c index 035b9a9b9b..9dc4306a77 100644 --- a/testsuites/sptests/sp2038/init.c +++ b/testsuites/sptests/sp2038/init.c @@ -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); - rtems_test_assert(test_status == RTEMS_SUCCESSFUL); + rtems_test_assert(test_status == RTEMS_INVALID_CLOCK); test_status = _TOD_Validate(problem2); 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]; diff --git a/testsuites/sptests/spclock_err02/init.c b/testsuites/sptests/spclock_err02/init.c index c879c4ce1f..2200b24ec6 100644 --- a/testsuites/sptests/spclock_err02/init.c +++ b/testsuites/sptests/spclock_err02/init.c @@ -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" ); -- 2.26.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel