clock: refactor clock_gettime clock_settime
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
6a2c03732f
commit
07a4233d1d
@ -732,6 +732,29 @@ void perf_convert(clock_t elapsed, FAR struct timespec *ts);
|
|||||||
|
|
||||||
unsigned long perf_getfreq(void);
|
unsigned long perf_getfreq(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxclock_settime
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Clock Functions based on POSIX APIs
|
||||||
|
*
|
||||||
|
* CLOCK_REALTIME - POSIX demands this to be present. This is the wall
|
||||||
|
* time clock.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxclock_settime(clockid_t clock_id, FAR const struct timespec *tp);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nxclock_gettime
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the current value of the specified time clock.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nxclock_gettime(clockid_t clock_id, FAR struct timespec *tp);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/spinlock.h>
|
#include <nuttx/spinlock.h>
|
||||||
#include <nuttx/queue.h>
|
|
||||||
|
|
||||||
#include "clock/clock.h"
|
#include "clock/clock.h"
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
@ -44,75 +43,67 @@
|
|||||||
# include "clock/clock_timekeeping.h"
|
# include "clock/clock_timekeeping.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_CRITMONITOR
|
||||||
|
static clock_t clock_process_runtime(FAR struct tcb_s *tcb)
|
||||||
|
{
|
||||||
|
# ifdef HAVE_GROUP_MEMBERS
|
||||||
|
FAR struct task_group_s *group;
|
||||||
|
FAR sq_entry_t *curr;
|
||||||
|
clock_t runtime = 0;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
group = tcb->group;
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave(NULL);
|
||||||
|
sq_for_every(&group->tg_members, curr)
|
||||||
|
{
|
||||||
|
tcb = container_of(curr, struct tcb_s, member);
|
||||||
|
|
||||||
|
runtime += tcb->run_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(NULL, flags);
|
||||||
|
return runtime;
|
||||||
|
# else /* HAVE_GROUP_MEMBERS */
|
||||||
|
return tcb->run_time;
|
||||||
|
# endif /* HAVE_GROUP_MEMBERS */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: clock_gettime
|
* Name: nxclock_gettime
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clock Functions based on POSIX APIs
|
* Get the current value of the specified time clock.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int clock_gettime(clockid_t clock_id, struct timespec *tp)
|
void nxclock_gettime(clockid_t clock_id, FAR struct timespec *tp)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
if (clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_BOOTTIME)
|
||||||
struct timespec ts;
|
|
||||||
#endif
|
|
||||||
int ret = OK;
|
|
||||||
|
|
||||||
clockid_t clock_type = clock_id & CLOCK_MASK;
|
|
||||||
#ifdef CONFIG_SCHED_CRITMONITOR
|
|
||||||
pid_t pid = clock_id >> CLOCK_SHIFT;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEBUGASSERT(tp != NULL);
|
|
||||||
|
|
||||||
/* CLOCK_MONOTONIC is an optional under POSIX: "If the Monotonic 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_type == CLOCK_MONOTONIC || clock_type == CLOCK_BOOTTIME)
|
|
||||||
{
|
{
|
||||||
/* The the time elapsed since the timer was initialized at power on
|
/* The the time elapsed since the timer was initialized at power on
|
||||||
* reset.
|
* reset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = clock_systime_timespec(tp);
|
clock_systime_timespec(tp);
|
||||||
}
|
}
|
||||||
|
else if (clock_id == CLOCK_REALTIME)
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (clock_type == CLOCK_REALTIME)
|
|
||||||
{
|
|
||||||
/* Get the elapsed time since the time-of-day was last set.
|
|
||||||
* clock_systime_timespec() provides the time since power was applied;
|
|
||||||
* the bias value corresponds to the time when the time-of-day was
|
|
||||||
* last set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(CONFIG_CLOCK_TIMEKEEPING)
|
|
||||||
ret = clock_timekeeping_get_wall_time(tp);
|
|
||||||
#else
|
|
||||||
ret = clock_systime_timespec(&ts);
|
|
||||||
if (ret == OK)
|
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||||
|
struct timespec ts;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
|
clock_systime_timespec(&ts);
|
||||||
|
|
||||||
/* Add the base time to this. The base time is the time-of-day
|
/* 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
|
* setting. When added to the elapsed time since the time-of-day
|
||||||
* was last set, this gives us the current time.
|
* was last set, this gives us the current time.
|
||||||
@ -121,95 +112,73 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp)
|
|||||||
flags = spin_lock_irqsave(NULL);
|
flags = spin_lock_irqsave(NULL);
|
||||||
clock_timespec_add(&g_basetime, &ts, tp);
|
clock_timespec_add(&g_basetime, &ts, tp);
|
||||||
spin_unlock_irqrestore(NULL, flags);
|
spin_unlock_irqrestore(NULL, flags);
|
||||||
|
#else
|
||||||
|
clock_timekeeping_get_wall_time(tp);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_CLOCK_TIMEKEEPING */
|
else
|
||||||
}
|
{
|
||||||
#ifdef CONFIG_SCHED_CRITMONITOR
|
#ifdef CONFIG_SCHED_CRITMONITOR
|
||||||
|
clockid_t clock_type = clock_id & CLOCK_MASK;
|
||||||
|
pid_t pid = clock_id >> CLOCK_SHIFT;
|
||||||
|
FAR struct tcb_s *tcb;
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
tcb = this_task();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcb = nxsched_get_tcb(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcb)
|
||||||
|
{
|
||||||
|
if (clock_type == CLOCK_PROCESS_CPUTIME_ID)
|
||||||
|
{
|
||||||
|
up_perf_convert(clock_process_runtime(tcb), tp);
|
||||||
|
}
|
||||||
else if (clock_type == CLOCK_THREAD_CPUTIME_ID)
|
else if (clock_type == CLOCK_THREAD_CPUTIME_ID)
|
||||||
{
|
{
|
||||||
FAR struct tcb_s *tcb;
|
up_perf_convert(tcb->run_time, tp);
|
||||||
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
/* Fetch the THREAD_CPUTIME for current thread */
|
|
||||||
|
|
||||||
tcb = this_task();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tcb = nxsched_get_tcb(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcb != NULL)
|
|
||||||
{
|
|
||||||
perf_convert(tcb->run_time, tp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -EFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (clock_type == CLOCK_PROCESS_CPUTIME_ID)
|
|
||||||
{
|
|
||||||
unsigned long runtime;
|
|
||||||
FAR struct tcb_s *tcb;
|
|
||||||
# ifdef HAVE_GROUP_MEMBERS
|
|
||||||
FAR struct task_group_s *group;
|
|
||||||
FAR sq_entry_t *curr;
|
|
||||||
FAR sq_entry_t *next;
|
|
||||||
irqstate_t flags;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
/* Fetch the PROCESS_CPUTIME for current process */
|
|
||||||
|
|
||||||
tcb = this_task();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tcb = nxsched_get_tcb(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcb != NULL)
|
|
||||||
{
|
|
||||||
# ifdef HAVE_GROUP_MEMBERS
|
|
||||||
group = tcb->group;
|
|
||||||
runtime = 0;
|
|
||||||
|
|
||||||
flags = spin_lock_irqsave(NULL);
|
|
||||||
sq_for_every_safe(&group->tg_members, curr, next)
|
|
||||||
{
|
|
||||||
tcb = container_of(curr, struct tcb_s, member);
|
|
||||||
|
|
||||||
runtime += tcb->run_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(NULL, flags);
|
|
||||||
# else /* HAVE_GROUP_MEMBERS */
|
|
||||||
runtime = tcb->run_time;
|
|
||||||
# endif /* HAVE_GROUP_MEMBERS */
|
|
||||||
|
|
||||||
perf_convert(runtime, tp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -EFAULT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Check for errors and set the errno value if necessary */
|
|
||||||
|
/****************************************************************************
|
||||||
if (ret < 0)
|
* Name: clock_gettime
|
||||||
{
|
*
|
||||||
set_errno(-ret);
|
* Description:
|
||||||
ret = ERROR;
|
* Clock Functions based on POSIX APIs
|
||||||
}
|
*
|
||||||
|
* CLOCK_MONOTONIC is an optional under POSIX: "If the Monotonic Clock
|
||||||
return ret;
|
* 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."
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int clock_gettime(clockid_t clock_id, FAR struct timespec *tp)
|
||||||
|
{
|
||||||
|
if (tp == NULL || clock_id < 0 || clock_id > CLOCK_BOOTTIME)
|
||||||
|
{
|
||||||
|
set_errno(EINVAL);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxclock_gettime(clock_id, tp);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -45,40 +45,27 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: clock_settime
|
* Name: nxclock_settime
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Clock Functions based on POSIX APIs
|
* Clock Functions based on POSIX APIs
|
||||||
*
|
*
|
||||||
|
* CLOCK_REALTIME - POSIX demands this to be present. This is the wall
|
||||||
|
* time clock.
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int clock_settime(clockid_t clock_id, FAR const struct timespec *tp)
|
void nxclock_settime(clockid_t clock_id, FAR const struct timespec *tp)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||||
struct timespec bias;
|
struct timespec bias;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
#endif
|
# ifdef CONFIG_CLOCK_ADJTIME
|
||||||
|
|
||||||
#ifdef CONFIG_CLOCK_ADJTIME
|
|
||||||
const struct timeval zerodelta = {
|
const struct timeval zerodelta = {
|
||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int ret = OK;
|
|
||||||
|
|
||||||
sinfo("clock_id=%d\n", clock_id);
|
|
||||||
DEBUGASSERT(tp != NULL);
|
|
||||||
|
|
||||||
/* CLOCK_REALTIME - POSIX demands this to be present. This is the wall
|
|
||||||
* time clock.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (clock_id == CLOCK_REALTIME &&
|
|
||||||
tp->tv_nsec >= 0 && tp->tv_nsec < 1000000000)
|
|
||||||
{
|
|
||||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
|
||||||
/* Interrupts are disabled here so that the in-memory time
|
/* Interrupts are disabled here so that the in-memory time
|
||||||
* representation and the RTC setting will be as close as
|
* representation and the RTC setting will be as close as
|
||||||
* possible.
|
* possible.
|
||||||
@ -91,58 +78,49 @@ int clock_settime(clockid_t clock_id, FAR const struct timespec *tp)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
clock_systime_timespec(&bias);
|
clock_systime_timespec(&bias);
|
||||||
|
clock_timespec_subtract(tp, &bias, &g_basetime);
|
||||||
|
|
||||||
/* Save the new base time. */
|
leave_critical_section(flags);
|
||||||
|
|
||||||
g_basetime.tv_sec = tp->tv_sec;
|
|
||||||
g_basetime.tv_nsec = tp->tv_nsec;
|
|
||||||
|
|
||||||
/* Subtract that bias from the basetime so that when the system
|
|
||||||
* timer is again added to the base time, the result is the current
|
|
||||||
* time relative to basetime.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (g_basetime.tv_nsec < bias.tv_nsec)
|
|
||||||
{
|
|
||||||
g_basetime.tv_nsec += NSEC_PER_SEC;
|
|
||||||
g_basetime.tv_sec--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Result could be negative seconds */
|
|
||||||
|
|
||||||
g_basetime.tv_nsec -= bias.tv_nsec;
|
|
||||||
g_basetime.tv_sec -= bias.tv_sec;
|
|
||||||
|
|
||||||
/* Setup the RTC (lo- or high-res) */
|
/* Setup the RTC (lo- or high-res) */
|
||||||
|
|
||||||
#ifdef CONFIG_RTC
|
# ifdef CONFIG_RTC
|
||||||
if (g_rtc_enabled)
|
if (g_rtc_enabled)
|
||||||
{
|
{
|
||||||
up_rtc_settime(tp);
|
up_rtc_settime(tp);
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#ifdef CONFIG_CLOCK_ADJTIME
|
# ifdef CONFIG_CLOCK_ADJTIME
|
||||||
/* Cancel any ongoing adjustment */
|
/* Cancel any ongoing adjustment */
|
||||||
|
|
||||||
adjtime(&zerodelta, NULL);
|
adjtime(&zerodelta, NULL);
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
leave_critical_section(flags);
|
|
||||||
|
|
||||||
sinfo("basetime=(%ld,%lu) bias=(%ld,%lu)\n",
|
|
||||||
(long)g_basetime.tv_sec, (unsigned long)g_basetime.tv_nsec,
|
|
||||||
(long)bias.tv_sec, (unsigned long)bias.tv_nsec);
|
|
||||||
#else
|
#else
|
||||||
ret = clock_timekeeping_set_wall_time(tp);
|
clock_timekeeping_set_wall_time(tp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: clock_settime
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Clock Functions based on POSIX APIs
|
||||||
|
*
|
||||||
|
* CLOCK_REALTIME - POSIX demands this to be present. This is the wall
|
||||||
|
* time clock.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int clock_settime(clockid_t clock_id, FAR const struct timespec *tp)
|
||||||
|
{
|
||||||
|
if (clock_id != CLOCK_REALTIME || tp == NULL ||
|
||||||
|
tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
|
||||||
{
|
{
|
||||||
serr("Returning ERROR\n");
|
|
||||||
set_errno(EINVAL);
|
set_errno(EINVAL);
|
||||||
ret = ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
nxclock_settime(clock_id, tp);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user