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"> <start name="test-libc">
<resource name="RAM" quantum="400M"/> <resource name="RAM" quantum="400M"/>
<config> <config>
<vfs> <dir name="dev"> <log/> </dir> </vfs> <vfs> <dir name="dev"> <log/> <inline name="rtc">2019-08-20 15:01</inline> </dir> </vfs>
<libc stdout="/dev/log" stderr="/dev/log"/> <libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
</config> </config>
</start> </start>
</config> </config>

View File

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

View File

@ -159,9 +159,13 @@ int main(int argc, char **argv)
sleep(1); sleep(1);
ts.tv_sec = ts.tv_nsec = 0; ts.tv_sec = ts.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &ts); 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; unsigned long long buf = 0;
getrandom(&buf, sizeof(buf), 0); getrandom(&buf, sizeof(buf), 0);