mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +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) { }
|
||||
|
||||
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)
|
||||
@ -281,22 +281,22 @@ struct Libc::Timeout
|
||||
|
||||
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;
|
||||
_absolute_timeout_ms = now + timeout_ms;
|
||||
_absolute_timeout_ms = now.value + timeout_ms;
|
||||
|
||||
_timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms));
|
||||
}
|
||||
|
||||
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 _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();
|
||||
}
|
||||
@ -889,7 +889,7 @@ void Libc::dispatch_pending_io_signals()
|
||||
}
|
||||
|
||||
|
||||
unsigned long Libc::current_time()
|
||||
Genode::Duration Libc::current_time()
|
||||
{
|
||||
return kernel->current_time();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#ifndef _LIBC__TASK_H_
|
||||
#define _LIBC__TASK_H_
|
||||
|
||||
#include <os/duration.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Libc {
|
||||
@ -53,7 +54,7 @@ namespace Libc {
|
||||
/**
|
||||
* Get time since startup in ms
|
||||
*/
|
||||
unsigned long current_time();
|
||||
Genode::Duration current_time();
|
||||
|
||||
/**
|
||||
* Suspend main user context and the component entrypoint
|
||||
|
@ -24,32 +24,54 @@ namespace Libc { time_t read_rtc(); }
|
||||
extern "C" __attribute__((weak))
|
||||
int clock_gettime(clockid_t clk_id, struct timespec *ts)
|
||||
{
|
||||
if (!ts) return 0;
|
||||
|
||||
static bool initial_rtc_requested = false;
|
||||
static time_t initial_rtc = 0;
|
||||
static unsigned long t0 = 0;
|
||||
if (!ts) return Libc::Errno(EFAULT);
|
||||
|
||||
/* initialize timespec just in case users do not check for errors */
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 0;
|
||||
|
||||
/* try to read rtc once */
|
||||
if (!initial_rtc_requested) {
|
||||
initial_rtc_requested = true;
|
||||
switch (clk_id) {
|
||||
|
||||
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)
|
||||
t0 = Libc::current_time();
|
||||
/* try to read rtc once */
|
||||
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);
|
||||
|
||||
unsigned long time = Libc::current_time() - t0;
|
||||
|
||||
ts->tv_sec = initial_rtc + time/1000;
|
||||
ts->tv_nsec = (time % 1000) * (1000*1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -62,7 +84,7 @@ int gettimeofday(struct timeval *tv, struct timezone *)
|
||||
|
||||
struct timespec ts;
|
||||
|
||||
if (int ret = clock_gettime(0, &ts))
|
||||
if (int ret = clock_gettime(CLOCK_REALTIME, &ts))
|
||||
return ret;
|
||||
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
|
Loading…
Reference in New Issue
Block a user