diff --git a/repos/libports/run/libc.run b/repos/libports/run/libc.run
index 6dd108b37..193b6f4f2 100644
--- a/repos/libports/run/libc.run
+++ b/repos/libports/run/libc.run
@@ -25,8 +25,8 @@ install_config {
-
-
+ 2019-08-20 15:01
+
diff --git a/repos/libports/src/lib/libc/time.cc b/repos/libports/src/lib/libc/time.cc
index 6df80b385..676e88545 100644
--- a/repos/libports/src/lib/libc/time.cc
+++ b/repos/libports/src/lib/libc/time.cc
@@ -26,47 +26,82 @@
/* Genode includes */
#include
+#include
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);
- if (fd == -1) {
- Genode::warning(Genode::Cstring(Libc::config_rtc()), " not readable, returning ", rtc);
- return rtc;
- }
-
- char buf[32];
- 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;
+ _watch_handle = Libc::watch(_file);
+ if (_watch_handle) {
+ _watch_handle->handler(this);
}
}
- close(fd);
+ /******************************************
+ ** Vfs::Watch_reponse_handler interface **
+ ******************************************/
- return rtc;
-}
+ 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_value);
+ return _rtc_value;
+ }
+
+ char buf[32];
+ 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_value = mktime(&tm);
+ if (_rtc_value == (time_t)-1)
+ _rtc_value = 0;
+ }
+ }
+
+ close(fd);
+
+ 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;
}
diff --git a/repos/libports/src/test/libc/main.cc b/repos/libports/src/test/libc/main.cc
index 8f78792c8..40f184d1c 100644
--- a/repos/libports/src/test/libc/main.cc
+++ b/repos/libports/src/test/libc/main.cc
@@ -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);