mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
Libc: support monotonic time without RTC
Use the Timer session duration for CLOCK_MONOTONIC and CLOCK_UPTIME. Use the Genode::Duration object for passing internal time, it supports sub-millisecond time and helps disambiguate units of time. Fix #3018
This commit is contained in:
parent
6178e378c1
commit
3e5ac64ee2
@ -217,9 +217,9 @@ struct Libc::Timer
|
|||||||
|
|
||||||
Timer(Genode::Env &env) : _timer(env) { }
|
Timer(Genode::Env &env) : _timer(env) { }
|
||||||
|
|
||||||
unsigned long curr_time()
|
Genode::Duration curr_time()
|
||||||
{
|
{
|
||||||
return _timer.curr_time().trunc_to_plain_us().value/1000;
|
return _timer.curr_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Microseconds microseconds(unsigned long timeout_ms)
|
static Microseconds microseconds(unsigned long timeout_ms)
|
||||||
@ -281,22 +281,22 @@ struct Libc::Timeout
|
|||||||
|
|
||||||
void start(unsigned long timeout_ms)
|
void start(unsigned long timeout_ms)
|
||||||
{
|
{
|
||||||
unsigned long const now = _timer_accessor.timer().curr_time();
|
Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms();
|
||||||
|
|
||||||
_expired = false;
|
_expired = false;
|
||||||
_absolute_timeout_ms = now + timeout_ms;
|
_absolute_timeout_ms = now.value + timeout_ms;
|
||||||
|
|
||||||
_timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms));
|
_timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long duration_left() const
|
unsigned long duration_left() const
|
||||||
{
|
{
|
||||||
unsigned long const now = _timer_accessor.timer().curr_time();
|
Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms();
|
||||||
|
|
||||||
if (_expired || _absolute_timeout_ms < now)
|
if (_expired || _absolute_timeout_ms < now.value)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return _absolute_timeout_ms - now;
|
return _absolute_timeout_ms - now.value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -751,7 +751,7 @@ struct Libc::Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long current_time()
|
Genode::Duration current_time()
|
||||||
{
|
{
|
||||||
return _timer_accessor.timer().curr_time();
|
return _timer_accessor.timer().curr_time();
|
||||||
}
|
}
|
||||||
@ -889,7 +889,7 @@ void Libc::dispatch_pending_io_signals()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned long Libc::current_time()
|
Genode::Duration Libc::current_time()
|
||||||
{
|
{
|
||||||
return kernel->current_time();
|
return kernel->current_time();
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#ifndef _LIBC__TASK_H_
|
#ifndef _LIBC__TASK_H_
|
||||||
#define _LIBC__TASK_H_
|
#define _LIBC__TASK_H_
|
||||||
|
|
||||||
|
#include <os/duration.h>
|
||||||
#include <util/xml_node.h>
|
#include <util/xml_node.h>
|
||||||
|
|
||||||
namespace Libc {
|
namespace Libc {
|
||||||
@ -53,7 +54,7 @@ namespace Libc {
|
|||||||
/**
|
/**
|
||||||
* Get time since startup in ms
|
* Get time since startup in ms
|
||||||
*/
|
*/
|
||||||
unsigned long current_time();
|
Genode::Duration current_time();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Suspend main user context and the component entrypoint
|
* Suspend main user context and the component entrypoint
|
||||||
|
@ -24,32 +24,54 @@ namespace Libc { time_t read_rtc(); }
|
|||||||
extern "C" __attribute__((weak))
|
extern "C" __attribute__((weak))
|
||||||
int clock_gettime(clockid_t clk_id, struct timespec *ts)
|
int clock_gettime(clockid_t clk_id, struct timespec *ts)
|
||||||
{
|
{
|
||||||
if (!ts) return 0;
|
if (!ts) return Libc::Errno(EFAULT);
|
||||||
|
|
||||||
static bool initial_rtc_requested = false;
|
|
||||||
static time_t initial_rtc = 0;
|
|
||||||
static unsigned long t0 = 0;
|
|
||||||
|
|
||||||
|
/* initialize timespec just in case users do not check for errors */
|
||||||
ts->tv_sec = 0;
|
ts->tv_sec = 0;
|
||||||
ts->tv_nsec = 0;
|
ts->tv_nsec = 0;
|
||||||
|
|
||||||
/* try to read rtc once */
|
switch (clk_id) {
|
||||||
if (!initial_rtc_requested) {
|
|
||||||
initial_rtc_requested = true;
|
|
||||||
|
|
||||||
initial_rtc = Libc::read_rtc();
|
/* IRL wall-time */
|
||||||
|
case CLOCK_REALTIME:
|
||||||
|
case CLOCK_SECOND: /* FreeBSD specific */
|
||||||
|
{
|
||||||
|
static bool initial_rtc_requested = false;
|
||||||
|
static time_t initial_rtc = 0;
|
||||||
|
static unsigned long t0_ms = 0;
|
||||||
|
|
||||||
if (initial_rtc)
|
/* try to read rtc once */
|
||||||
t0 = Libc::current_time();
|
if (!initial_rtc_requested) {
|
||||||
|
initial_rtc_requested = true;
|
||||||
|
initial_rtc = Libc::read_rtc();
|
||||||
|
if (initial_rtc) {
|
||||||
|
t0_ms = Libc::current_time().trunc_to_plain_ms().value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initial_rtc) return Libc::Errno(EINVAL);
|
||||||
|
|
||||||
|
unsigned long time = Libc::current_time().trunc_to_plain_ms().value - t0_ms;
|
||||||
|
|
||||||
|
ts->tv_sec = initial_rtc + time/1000;
|
||||||
|
ts->tv_nsec = (time % 1000) * (1000*1000);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initial_rtc)
|
/* component uptime */
|
||||||
|
case CLOCK_MONOTONIC:
|
||||||
|
case CLOCK_UPTIME:
|
||||||
|
{
|
||||||
|
unsigned long us = Libc::current_time().trunc_to_plain_us().value;
|
||||||
|
|
||||||
|
ts->tv_sec = us / (1000*1000);
|
||||||
|
ts->tv_nsec = (us % (1000*1000)) * 1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
return Libc::Errno(EINVAL);
|
return Libc::Errno(EINVAL);
|
||||||
|
}
|
||||||
unsigned long time = Libc::current_time() - t0;
|
|
||||||
|
|
||||||
ts->tv_sec = initial_rtc + time/1000;
|
|
||||||
ts->tv_nsec = (time % 1000) * (1000*1000);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -62,7 +84,7 @@ int gettimeofday(struct timeval *tv, struct timezone *)
|
|||||||
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
if (int ret = clock_gettime(0, &ts))
|
if (int ret = clock_gettime(CLOCK_REALTIME, &ts))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
tv->tv_sec = ts.tv_sec;
|
tv->tv_sec = ts.tv_sec;
|
||||||
|
Loading…
Reference in New Issue
Block a user