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);
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/queue.h>
|
||||
|
||||
#include "clock/clock.h"
|
||||
#include "sched/sched.h"
|
||||
@ -44,172 +43,142 @@
|
||||
# include "clock/clock_timekeeping.h"
|
||||
#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
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxclock_gettime
|
||||
*
|
||||
* Description:
|
||||
* Get the current value of the specified time clock.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nxclock_gettime(clockid_t clock_id, FAR struct timespec *tp)
|
||||
{
|
||||
if (clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_BOOTTIME)
|
||||
{
|
||||
/* The the time elapsed since the timer was initialized at power on
|
||||
* reset.
|
||||
*/
|
||||
|
||||
clock_systime_timespec(tp);
|
||||
}
|
||||
else if (clock_id == CLOCK_REALTIME)
|
||||
{
|
||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||
struct timespec ts;
|
||||
irqstate_t flags;
|
||||
|
||||
clock_systime_timespec(&ts);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
clock_timespec_add(&g_basetime, &ts, tp);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
#else
|
||||
clock_timekeeping_get_wall_time(tp);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#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)
|
||||
{
|
||||
up_perf_convert(tcb->run_time, tp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: clock_gettime
|
||||
*
|
||||
* Description:
|
||||
* Clock Functions based on POSIX APIs
|
||||
*
|
||||
* 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."
|
||||
*
|
||||
* 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, struct timespec *tp)
|
||||
int clock_gettime(clockid_t clock_id, FAR struct timespec *tp)
|
||||
{
|
||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||
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)
|
||||
if (tp == NULL || clock_id < 0 || clock_id > CLOCK_BOOTTIME)
|
||||
{
|
||||
/* The the time elapsed since the timer was initialized at power on
|
||||
* reset.
|
||||
*/
|
||||
|
||||
ret = clock_systime_timespec(tp);
|
||||
set_errno(EINVAL);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
clock_timespec_add(&g_basetime, &ts, tp);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
#endif /* CONFIG_CLOCK_TIMEKEEPING */
|
||||
}
|
||||
#ifdef CONFIG_SCHED_CRITMONITOR
|
||||
else if (clock_type == CLOCK_THREAD_CPUTIME_ID)
|
||||
{
|
||||
FAR struct tcb_s *tcb;
|
||||
|
||||
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
|
||||
else
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Check for errors and set the errno value if necessary */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
nxclock_gettime(clock_id, tp);
|
||||
return OK;
|
||||
}
|
||||
|
@ -44,105 +44,83 @@
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||
struct timespec bias;
|
||||
irqstate_t flags;
|
||||
# ifdef CONFIG_CLOCK_ADJTIME
|
||||
const struct timeval zerodelta = {
|
||||
0, 0
|
||||
};
|
||||
# endif
|
||||
|
||||
/* Interrupts are disabled here so that the in-memory time
|
||||
* representation and the RTC setting will be as close as
|
||||
* possible.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Get the elapsed time since power up (in milliseconds). This is a
|
||||
* bias value that we need to use to correct the base time.
|
||||
*/
|
||||
|
||||
clock_systime_timespec(&bias);
|
||||
clock_timespec_subtract(tp, &bias, &g_basetime);
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Setup the RTC (lo- or high-res) */
|
||||
|
||||
# ifdef CONFIG_RTC
|
||||
if (g_rtc_enabled)
|
||||
{
|
||||
up_rtc_settime(tp);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_CLOCK_ADJTIME
|
||||
/* Cancel any ongoing adjustment */
|
||||
|
||||
adjtime(&zerodelta, NULL);
|
||||
# endif
|
||||
#else
|
||||
clock_timekeeping_set_wall_time(tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||
struct timespec bias;
|
||||
irqstate_t flags;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLOCK_ADJTIME
|
||||
const struct timeval zerodelta = {
|
||||
0, 0
|
||||
};
|
||||
|
||||
#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)
|
||||
if (clock_id != CLOCK_REALTIME || tp == NULL ||
|
||||
tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
|
||||
{
|
||||
#ifndef CONFIG_CLOCK_TIMEKEEPING
|
||||
/* Interrupts are disabled here so that the in-memory time
|
||||
* representation and the RTC setting will be as close as
|
||||
* possible.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Get the elapsed time since power up (in milliseconds). This is a
|
||||
* bias value that we need to use to correct the base time.
|
||||
*/
|
||||
|
||||
clock_systime_timespec(&bias);
|
||||
|
||||
/* Save the new base time. */
|
||||
|
||||
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) */
|
||||
|
||||
#ifdef CONFIG_RTC
|
||||
if (g_rtc_enabled)
|
||||
{
|
||||
up_rtc_settime(tp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLOCK_ADJTIME
|
||||
/* Cancel any ongoing adjustment */
|
||||
|
||||
adjtime(&zerodelta, NULL);
|
||||
#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
|
||||
ret = clock_timekeeping_set_wall_time(tp);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
serr("Returning ERROR\n");
|
||||
set_errno(EINVAL);
|
||||
ret = ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
nxclock_settime(clock_id, tp);
|
||||
return OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user