Add support for CLOCK_MONOTONIC. From Macs N

This commit is contained in:
Gregory Nutt
2014-03-31 09:25:50 -06:00
parent 6bb8cc02df
commit 8772a4e104
3 changed files with 85 additions and 24 deletions
+2
View File
@@ -7087,4 +7087,6 @@
* libc/stdio/lib_sccanf.c: Fix a counting error in the return * libc/stdio/lib_sccanf.c: Fix a counting error in the return
value from sscanf(). Noted by kfrolov. Also, sscanf() should value from sscanf(). Noted by kfrolov. Also, sscanf() should
return EOF if no values were converted (2014-3-30). return EOF if no values were converted (2014-3-30).
* include/time.h and sched/clock_settime(): Add support for
CLOCK_REALTIME. From Macs N (2014-3-31).
+20 -9
View File
@@ -1,7 +1,7 @@
/******************************************************************************** /********************************************************************************
* include/time.h * include/time.h
* *
* Copyright (C) 2007-2011, 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -67,19 +67,23 @@
# define CLOCKS_PER_SEC (100) # define CLOCKS_PER_SEC (100)
#endif #endif
/* CLOCK_REALTIME refers to the standard time source. For most implementations, /* CLOCK_REALTIME refers to the standard time source. For most
* the standard time source is the system timer interrupt. However, if the * implementations, the standard time source is the system timer interrupt.
* platform supports an RTC, then the standard time source will be the RTC * However, if the platform supports an RTC, then the standard time source
* for the clock_gettime() and clock_settime() interfaces (the system timer * will be the RTC for the clock_gettime() and clock_settime() interfaces
* is still the time source for all of the interfaces). * (the system timer is still the time source for all of the interfaces).
*
* CLOCK_REALTIME represents the machine's best-guess as to the current
* wall-clock, time-of-day time. This means that CLOCK_REALTIME can jump
* forward and backward as the system time-of-day clock is changed.
*/ */
#define CLOCK_REALTIME 0 #define CLOCK_REALTIME 0
/* If an RTC is supported, then the non-standard CLOCK_ACTIVETIME is also /* If an RTC is supported, then the non-standard CLOCK_ACTIVETIME is also
* supported to manage time based on the system timer interrupt separately from * supported to manage time based on the system timer interrupt separately
* the RTC. This may be necessary, for example, in certain cases where the * from the RTC. This may be necessary, for example, in certain cases where
* system timer interrupt has been stopped in low power modes. * the system timer interrupt has been stopped in low power modes.
* *
* CLOCK_ACTIVETIME is only recognized by clock_gettime() and clock_settime(). * CLOCK_ACTIVETIME is only recognized by clock_gettime() and clock_settime().
*/ */
@@ -90,6 +94,13 @@
# define CLOCK_ACTIVETIME CLOCK_REALTIME # define CLOCK_ACTIVETIME CLOCK_REALTIME
#endif #endif
/* Clock that cannot be set and represents monotonic time since some
* unspecified starting point. It is not affected by changes in the
* system time-of-day clock.
*/
#define CLOCK_MONOTONIC 2
/* This is a flag that may be passed to the timer_settime() function */ /* This is a flag that may be passed to the timer_settime() function */
#define TIMER_ABSTIME 1 #define TIMER_ABSTIME 1
+63 -15
View File
@@ -1,7 +1,7 @@
/************************************************************************ /************************************************************************
* sched/clock_gettime.c * sched/clock_gettime.c
* *
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -51,7 +51,7 @@
#include "clock_internal.h" #include "clock_internal.h"
/************************************************************************ /************************************************************************
* Definitions * Pre-processor Definitions
************************************************************************/ ************************************************************************/
/************************************************************************ /************************************************************************
@@ -101,35 +101,80 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
uint32_t secs; uint32_t secs;
uint32_t nsecs; uint32_t nsecs;
#endif #endif
uint32_t carry;
int ret = OK; int ret = OK;
sdbg("clock_id=%d\n", clock_id); sdbg("clock_id=%d\n", clock_id);
DEBUGASSERT(tp != NULL); DEBUGASSERT(tp != NULL);
/* CLOCK_REALTIME - POSIX demands this to be present. This is the wall /* CLOCK_MONOTONIC is an optional under POSIX: "If the Monotonic Clock
* time clock. * option is supported, all implementations shall support a clock_id
* of CLOCK_MONOTONIC defined in <time.h>. This clock represents the
* monotonic clock for the system. For this clock, the value returned
* by clock_gettime() represents the amount of time (in seconds and
* nanoseconds) since an unspecified point in the past (for example,
* system start-up time, or the Epoch). This point does not change
* after system start-up time. The value of the CLOCK_MONOTONIC clock
* cannot be set via clock_settime(). This function shall fail if it
* is invoked with a clock_id argument of CLOCK_MONOTONIC."
*/
if (clock_id == CLOCK_MONOTONIC)
{
/* Get the time since power-on in seconds and milliseconds */
msecs = MSEC_PER_TICK * g_system_timer;
secs = msecs / MSEC_PER_SEC;
/* Return the elapsed time in seconds and nanoseconds */
nsecs = (msecs - (secs * MSEC_PER_SEC)) * NSEC_PER_MSEC;
if (nsecs > NSEC_PER_SEC)
{
carry = nsecs / NSEC_PER_SEC;
secs += carry;
nsecs -= (carry * NSEC_PER_SEC);
}
tp->tv_sec = (time_t)secs;
tp->tv_nsec = (long)nsecs;
}
/* CLOCK_REALTIME - POSIX demands this to be present. CLOCK_REALTIME
* represents the machine's best-guess as to the current wall-clock,
* time-of-day time. This means that CLOCK_REALTIME can jump forward and
* backward as the system time-of-day clock is changed.
*
* If an RTC is supported, then the non-standard CLOCK_ACTIVETIME is also
* supported to manage time based on the system timer interrupt separately
* from the RTC. This may be necessary, for example, in certain cases where
* the system timer interrupt has been stopped in low power modes.
*/ */
#ifdef CONFIG_RTC #ifdef CONFIG_RTC
if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME) else if (clock_id == CLOCK_REALTIME || clock_id == CLOCK_ACTIVETIME)
#else #else
if (clock_id == CLOCK_REALTIME) else if (clock_id == CLOCK_REALTIME)
#endif #endif
{ {
/* Do we have a high-resolution RTC that can provie us with the time? */ /* Do we have a high-resolution RTC that can provide us with the time? */
#ifdef CONFIG_RTC_HIRES #ifdef CONFIG_RTC_HIRES
if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME) if (g_rtc_enabled && clock_id != CLOCK_ACTIVETIME)
{ {
/* Yes.. Get the hi-resolution time from the RTC */ /* Yes.. Get the hi-resolution time from the RTC unless the caller
* has specifically asked for the system timer (CLOCK_ACTIVETIME)
*/
ret = up_rtc_gettime(tp); ret = up_rtc_gettime(tp);
} }
else else
#endif #endif
{ {
/* Get the elapsed time since power up (in milliseconds) biased /* Get the elapsed time since the time-of-day was last set.
* as appropriate. * g_system_timer provides the number of clock times since
* power was applied; the bias value corresponds to the time
* when the time-of-day was last set.
*/ */
msecs = MSEC_PER_TICK * (g_system_timer - g_tickbias); msecs = MSEC_PER_TICK * (g_system_timer - g_tickbias);
@@ -146,7 +191,10 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
(int)msecs, (int)g_basetime.tv_sec, (int)msecs, (int)g_basetime.tv_sec,
(int)nsecs, (int)g_basetime.tv_nsec); (int)nsecs, (int)g_basetime.tv_nsec);
/* Add the base time to this. */ /* Add the base time to this. The base time is the time-of-day
* setting. When added to the elapsed time since the time-of-day
* was last set, this gives us the current time.
*/
secs += (uint32_t)g_basetime.tv_sec; secs += (uint32_t)g_basetime.tv_sec;
nsecs += (uint32_t)g_basetime.tv_nsec; nsecs += (uint32_t)g_basetime.tv_nsec;
@@ -155,9 +203,9 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
if (nsecs > NSEC_PER_SEC) if (nsecs > NSEC_PER_SEC)
{ {
uint32_t dwCarrySecs = nsecs / NSEC_PER_SEC; carry = nsecs / NSEC_PER_SEC;
secs += dwCarrySecs; secs += carry;
nsecs -= (dwCarrySecs * NSEC_PER_SEC); nsecs -= (carry * NSEC_PER_SEC);
} }
/* And return the result to the caller. */ /* And return the result to the caller. */
@@ -172,7 +220,7 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
{ {
sdbg("Returning ERROR\n"); sdbg("Returning ERROR\n");
errno = EINVAL; set_errno(EINVAL);
ret = ERROR; ret = ERROR;
} }