Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #429, OS_time_t with single tick counter #735

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 41 additions & 37 deletions src/os/inc/osapi-clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,29 @@
*/
typedef struct
{
uint32 seconds;
uint32 microsecs;
int64 ticks; /**< Ticks elapsed since reference point */
} OS_time_t;


/**
* @brief Multipliers/divisors to convert ticks into standardized units
*
* Various fixed conversion factor constants used by the conversion routines
*
* A 100ns tick time allows max intervals of about +/- 14000 years in
* a 64-bit signed integer value.
*
* @note Applications should not directly use these values, but rather use
* conversion routines below to obtain standardized units (seconds/microseconds/etc).
*/
enum
{
OS_TIME_TICK_RESOLUTION_NS = 100,
OS_TIME_TICKS_PER_SECOND = 1000000000 / OS_TIME_TICK_RESOLUTION_NS,
OS_TIME_TICKS_PER_MSEC = 1000000 / OS_TIME_TICK_RESOLUTION_NS,
OS_TIME_TICKS_PER_USEC = 1000 / OS_TIME_TICK_RESOLUTION_NS
};

/** @defgroup OSAPIClock OSAL Real Time Clock APIs
* @{
*/
Expand Down Expand Up @@ -108,7 +127,7 @@ int32 OS_SetLocalTime(const OS_time_t *time_struct);
*/
static inline int64 OS_TimeGetTotalSeconds(OS_time_t tm)
{
return (tm.seconds);
return (tm.ticks / OS_TIME_TICKS_PER_SECOND);
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -122,7 +141,7 @@ static inline int64 OS_TimeGetTotalSeconds(OS_time_t tm)
*/
static inline int64 OS_TimeGetTotalMilliseconds(OS_time_t tm)
{
return (((int64)tm.seconds * 1000) + (tm.microsecs / 1000));
return (tm.ticks / OS_TIME_TICKS_PER_MSEC);
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -136,7 +155,7 @@ static inline int64 OS_TimeGetTotalMilliseconds(OS_time_t tm)
*/
static inline int64 OS_TimeGetTotalMicroseconds(OS_time_t tm)
{
return (((int64)tm.seconds * 1000000) + tm.microsecs);
return (tm.ticks / OS_TIME_TICKS_PER_USEC);
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -154,7 +173,7 @@ static inline int64 OS_TimeGetTotalMicroseconds(OS_time_t tm)
*/
static inline int64 OS_TimeGetTotalNanoseconds(OS_time_t tm)
{
return (((int64)tm.seconds * 1000000000) + (tm.microsecs * 1000));
return (tm.ticks * OS_TIME_TICK_RESOLUTION_NS);
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -169,7 +188,7 @@ static inline int64 OS_TimeGetTotalNanoseconds(OS_time_t tm)
*/
static inline int64 OS_TimeGetFractionalPart(OS_time_t tm)
{
return (tm.microsecs);
return (tm.ticks % OS_TIME_TICKS_PER_SECOND);
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -194,7 +213,8 @@ static inline uint32 OS_TimeGetSubsecondsPart(OS_time_t tm)
* It also must round up, otherwise this may result in a value one
* less than the original when converted back to usec again.
*/
return (((OS_TimeGetFractionalPart(tm) << 26) + 15624) / 15625);
int64 frac = (OS_TimeGetFractionalPart(tm) << 30) + (OS_TIME_TICKS_PER_SECOND >> 2);
return (uint32)((frac - 1) / (OS_TIME_TICKS_PER_SECOND >> 2));
}


Expand All @@ -212,7 +232,7 @@ static inline uint32 OS_TimeGetSubsecondsPart(OS_time_t tm)
*/
static inline uint32 OS_TimeGetMillisecondsPart(OS_time_t tm)
{
return OS_TimeGetFractionalPart(tm) / 1000;
return (uint32)OS_TimeGetFractionalPart(tm) / OS_TIME_TICKS_PER_MSEC;
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -237,7 +257,7 @@ static inline uint32 OS_TimeGetMillisecondsPart(OS_time_t tm)
*/
static inline uint32 OS_TimeGetMicrosecondsPart(OS_time_t tm)
{
return OS_TimeGetFractionalPart(tm);
return (uint32)OS_TimeGetFractionalPart(tm) / OS_TIME_TICKS_PER_USEC;
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -256,7 +276,7 @@ static inline uint32 OS_TimeGetMicrosecondsPart(OS_time_t tm)
*/
static inline uint32 OS_TimeGetNanosecondsPart(OS_time_t tm)
{
return OS_TimeGetFractionalPart(tm) * 1000;
return (uint32)OS_TimeGetFractionalPart(tm) * OS_TIME_TICK_RESOLUTION_NS;
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -278,8 +298,8 @@ static inline uint32 OS_TimeGetNanosecondsPart(OS_time_t tm)
static inline OS_time_t OS_TimeAssembleFromNanoseconds(int64 seconds, uint32 nanoseconds)
{
OS_time_t result;
result.seconds = seconds;
result.microsecs = nanoseconds / 1000;
result.ticks = seconds * OS_TIME_TICKS_PER_SECOND;
result.ticks += nanoseconds / OS_TIME_TICK_RESOLUTION_NS;
return result;
}

Expand All @@ -302,8 +322,8 @@ static inline OS_time_t OS_TimeAssembleFromNanoseconds(int64 seconds, uint32 nan
static inline OS_time_t OS_TimeAssembleFromMicroseconds(int64 seconds, uint32 microseconds)
{
OS_time_t result;
result.seconds = seconds;
result.microsecs = microseconds;
result.ticks = seconds * OS_TIME_TICKS_PER_SECOND;
result.ticks += microseconds * OS_TIME_TICKS_PER_USEC;
return result;
}

Expand All @@ -326,8 +346,8 @@ static inline OS_time_t OS_TimeAssembleFromMicroseconds(int64 seconds, uint32 mi
static inline OS_time_t OS_TimeAssembleFromMilliseconds(int64 seconds, uint32 milliseconds)
{
OS_time_t result;
result.seconds = seconds;
result.microsecs = milliseconds * 1000;
result.ticks = seconds * OS_TIME_TICKS_PER_SECOND;
result.ticks += milliseconds * OS_TIME_TICKS_PER_MSEC;
return result;
}

Expand All @@ -350,9 +370,9 @@ static inline OS_time_t OS_TimeAssembleFromMilliseconds(int64 seconds, uint32 mi
static inline OS_time_t OS_TimeAssembleFromSubseconds(int64 seconds, uint32 subseconds)
{
OS_time_t result;
result.seconds = seconds;
result.ticks = seconds * OS_TIME_TICKS_PER_SECOND;
/* this should not round in any way, as the 32-bit input value has higher precision */
result.microsecs = ((int64)subseconds * 15625) >> 26;
result.ticks += ((int64)subseconds * (OS_TIME_TICKS_PER_SECOND >> 2)) >> 30;
return result;
}

Expand All @@ -367,15 +387,7 @@ static inline OS_time_t OS_TimeAssembleFromSubseconds(int64 seconds, uint32 subs
*/
static inline OS_time_t OS_TimeAdd(OS_time_t time1, OS_time_t time2)
{
OS_time_t result = time1;
result.seconds += time2.seconds;
result.microsecs += time2.microsecs;
if (result.microsecs >= 1000000)
{
++result.seconds;
result.microsecs -= 1000000;
}
return result;
return ((OS_time_t) { time1.ticks + time2.ticks });
}

/*-------------------------------------------------------------------------------------*/
Expand All @@ -389,15 +401,7 @@ static inline OS_time_t OS_TimeAdd(OS_time_t time1, OS_time_t time2)
*/
static inline OS_time_t OS_TimeSubtract(OS_time_t time1, OS_time_t time2)
{
OS_time_t result = time1;
result.seconds -= time2.seconds;
result.microsecs -= time2.microsecs;
if (result.microsecs >= 1000000)
{
--result.seconds;
result.microsecs += 1000000;
}
return result;
return ((OS_time_t) { time1.ticks - time2.ticks });
}


Expand Down
12 changes: 6 additions & 6 deletions src/unit-test-coverage/shared/src/coveragetest-clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,14 @@ void Test_OS_TimeAccessConversions(void)
UtAssert_UINT32_EQ(OS_TimeGetTotalMicroseconds(t4), 1901000);

/* Note: Nanoseconds/Subseconds may not be exact due to limitations of OS_time_t resolution */
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t1), 1234567000);
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t2), 2528888000);
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t1), 1234567800);
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t2), 2528888800);
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t3), 45678000);
UtAssert_UINT32_EQ(OS_TimeGetTotalNanoseconds(t4), 1901000000);

/* These functions only return the fractional part, not the whole part */
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t1), 0x3c0c953a);
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t2), 0x87653438);
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t1), 0x3c0ca2a6);
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t2), 0x876541a4);
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t3), 0x0bb18dad);
UtAssert_UINT32_EQ(OS_TimeGetSubsecondsPart(t4), 0xe6a7ef9e);

Expand All @@ -139,8 +139,8 @@ void Test_OS_TimeAccessConversions(void)
UtAssert_UINT32_EQ(OS_TimeGetMicrosecondsPart(t3), 45678);
UtAssert_UINT32_EQ(OS_TimeGetMicrosecondsPart(t4), 901000);

UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t1), 234567000);
UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t2), 528888000);
UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t1), 234567800);
UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t2), 528888800);
UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t3), 45678000);
UtAssert_UINT32_EQ(OS_TimeGetNanosecondsPart(t4), 901000000);

Expand Down