libc: change time back end to re-read RTC

Issue #3450
This commit is contained in:
Josef Söntgen 2019-08-12 18:10:38 +02:00 committed by Christian Helmuth
parent 316f9e4df3
commit 9cf5da85ef
3 changed files with 74 additions and 45 deletions

View File

@ -25,8 +25,8 @@ install_config {
<start name="test-libc">
<resource name="RAM" quantum="400M"/>
<config>
<vfs> <dir name="dev"> <log/> </dir> </vfs>
<libc stdout="/dev/log" stderr="/dev/log"/>
<vfs> <dir name="dev"> <log/> <inline name="rtc">2019-08-20 15:01</inline> </dir> </vfs>
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
</config>
</start>
</config>

View File

@ -26,47 +26,82 @@
/* Genode includes */
#include <base/log.h>
#include <vfs/vfs_handle.h>
namespace Libc {
extern char const *config_rtc();
time_t read_rtc();
}
time_t Libc::read_rtc()
struct Rtc : Vfs::Watch_response_handler
{
time_t rtc = 0;
Vfs::Vfs_watch_handle *_watch_handle { nullptr };
char const *_file { nullptr };
bool _read_file { true };
time_t _rtc_value { 0 };
if (!Genode::strcmp(Libc::config_rtc(), "")) {
Genode::warning("rtc not configured, returning ", rtc);
return rtc;
Rtc(char const *rtc_file)
: _file(rtc_file)
{
if (!Genode::strcmp(_file, "")) {
Genode::warning("rtc not configured, returning ", _rtc_value);
return;
}
int fd = open(Libc::config_rtc(), O_RDONLY);
_watch_handle = Libc::watch(_file);
if (_watch_handle) {
_watch_handle->handler(this);
}
}
/******************************************
** Vfs::Watch_reponse_handler interface **
******************************************/
void watch_response() override
{
_read_file = true;
}
time_t read()
{
if (!_file) { return 0; }
/* return old value */
if (!_read_file) { return _rtc_value; }
_read_file = false;
int fd = open(_file, O_RDONLY);
if (fd == -1) {
Genode::warning(Genode::Cstring(Libc::config_rtc()), " not readable, returning ", rtc);
return rtc;
Genode::warning(Genode::Cstring(Libc::config_rtc()), " not readable, returning ", _rtc_value);
return _rtc_value;
}
char buf[32];
ssize_t n = read(fd, buf, sizeof(buf));
ssize_t n = ::read(fd, buf, sizeof(buf));
if (n > 0) {
buf[n - 1] = '\0';
struct tm tm;
Genode::memset(&tm, 0, sizeof(tm));
if (strptime(buf, "%Y-%m-%d %R", &tm)) {
rtc = mktime(&tm);
if (rtc == (time_t)-1)
rtc = 0;
_rtc_value = mktime(&tm);
if (_rtc_value == (time_t)-1)
_rtc_value = 0;
}
}
close(fd);
return rtc;
uint64_t const ts_value =
Libc::current_time().trunc_to_plain_ms().value;
_rtc_value += (time_t)ts_value / 1000;
return _rtc_value;
}
};
extern "C" __attribute__((weak))
@ -84,24 +119,14 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts)
case CLOCK_REALTIME:
case CLOCK_SECOND: /* FreeBSD specific */
{
static bool initial_rtc_requested = false;
static time_t initial_rtc = 0;
static Genode::uint64_t t0_ms = 0;
static Rtc rtc(Libc::config_rtc());
/* 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;
}
}
time_t const rtc_value = rtc.read();
if (!rtc_value) return Libc::Errno(EINVAL);
if (!initial_rtc) return Libc::Errno(EINVAL);
Genode::uint64_t const time = Libc::current_time().trunc_to_plain_ms().value;
Genode::uint64_t time = Libc::current_time().trunc_to_plain_ms().value - t0_ms;
ts->tv_sec = initial_rtc + time/1000;
ts->tv_sec = rtc_value + time/1000;
ts->tv_nsec = (time % 1000) * (1000*1000);
break;
}

View File

@ -159,9 +159,13 @@ int main(int argc, char **argv)
sleep(1);
ts.tv_sec = ts.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &ts);
printf("sleep/gettime: %.09f\n", ts.tv_sec + ts.tv_nsec / 1000000000.0);
printf("sleep/gettime(CLOCK_MONOTONIC): %.09f\n", ts.tv_sec + ts.tv_nsec / 1000000000.0);
}
ts.tv_sec = ts.tv_nsec = 0;
clock_gettime(CLOCK_REALTIME, &ts);
printf("sleep/gettime(CLOCK_REALTIME): %.09f\n", ts.tv_sec + ts.tv_nsec / 1000000000.0);
{
unsigned long long buf = 0;
getrandom(&buf, sizeof(buf), 0);