diff --git a/repos/libports/src/lib/libc/internal/init.h b/repos/libports/src/lib/libc/internal/init.h index b698426cc..f14a162fb 100644 --- a/repos/libports/src/lib/libc/internal/init.h +++ b/repos/libports/src/lib/libc/internal/init.h @@ -34,6 +34,7 @@ namespace Libc { struct Current_time; struct Clone_connection; struct Kernel_routine_scheduler; + struct Watch; /** * Support for shared libraries @@ -98,7 +99,7 @@ namespace Libc { * Init timing facilities */ void init_sleep(Suspend &); - void init_time(Current_time &, Rtc_path const &); + void init_time(Current_time &, Rtc_path const &, Watch &); /** * Socket fs diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index 1ba2ecbc3..cce005591 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace Libc { class Kernel; } @@ -58,7 +59,8 @@ struct Libc::Kernel final : Vfs::Io_response_handler, Suspend, Select, Kernel_routine_scheduler, - Current_time + Current_time, + Watch { private: @@ -513,9 +515,9 @@ struct Libc::Kernel final : Vfs::Io_response_handler, } /** - * Alloc new watch handler for given path + * Watch interface */ - Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) + Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) override { Vfs::Vfs_watch_handle *watch_handle { nullptr }; typedef Vfs::Directory_service::Watch_result Result; diff --git a/repos/libports/src/lib/libc/internal/legacy.h b/repos/libports/src/lib/libc/internal/legacy.h index c9f927a60..cea751316 100644 --- a/repos/libports/src/lib/libc/internal/legacy.h +++ b/repos/libports/src/lib/libc/internal/legacy.h @@ -27,18 +27,6 @@ namespace Libc { */ void dispatch_pending_io_signals(); - /** - * Get watch handle for given path - * - * \param path path that should be be watched - * - * \return point to the watch handle object or a nullptr - * when the watch operation failed - * - * XXX only needed by time.cc - */ - Vfs::Vfs_watch_handle *watch(char const *path); - /* * XXX this function is solely needed to support noux fork mechanism */ diff --git a/repos/libports/src/lib/libc/internal/watch.h b/repos/libports/src/lib/libc/internal/watch.h new file mode 100644 index 000000000..77b494881 --- /dev/null +++ b/repos/libports/src/lib/libc/internal/watch.h @@ -0,0 +1,31 @@ +/* + * \brief Interface for watching files + * \author Norman Feske + * \date 2019-09-20 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _LIBC__INTERNAL__WATCH_H_ +#define _LIBC__INTERNAL__WATCH_H_ + +/* libc-internal includes */ +#include + +namespace Libc { + + struct Watch : Interface + { + /** + * Alloc new watch handler for given path + */ + virtual Vfs::Vfs_watch_handle *alloc_watch_handle(char const *path) = 0; + }; +} + +#endif /* _LIBC__INTERNAL__WATCH_H_ */ diff --git a/repos/libports/src/lib/libc/kernel.cc b/repos/libports/src/lib/libc/kernel.cc index 6fd07cd7a..75ab1c89f 100644 --- a/repos/libports/src/lib/libc/kernel.cc +++ b/repos/libports/src/lib/libc/kernel.cc @@ -322,7 +322,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap) init_plugin(*this); init_sleep(*this); init_vfs_plugin(*this); - init_time(*this, _rtc_path); + init_time(*this, _rtc_path, *this); init_poll(*this); init_select(*this, *this, *this); init_socket_fs(*this); diff --git a/repos/libports/src/lib/libc/legacy.cc b/repos/libports/src/lib/libc/legacy.cc index 1eb086697..19f518cb2 100644 --- a/repos/libports/src/lib/libc/legacy.cc +++ b/repos/libports/src/lib/libc/legacy.cc @@ -25,12 +25,6 @@ void Libc::dispatch_pending_io_signals() } -Vfs::Vfs_watch_handle *Libc::watch(char const *path) -{ - return Kernel::kernel().alloc_watch_handle(path); -} - - void Libc::schedule_suspend(void (*suspended) ()) { Kernel::kernel().schedule_suspend(suspended); diff --git a/repos/libports/src/lib/libc/time.cc b/repos/libports/src/lib/libc/time.cc index 91615ee28..cb2a3bc35 100644 --- a/repos/libports/src/lib/libc/time.cc +++ b/repos/libports/src/lib/libc/time.cc @@ -28,17 +28,22 @@ #include #include #include +#include static Libc::Current_time *_current_time_ptr; static char const *_rtc_path; +static Libc::Watch *_watch_ptr; -void Libc::init_time(Current_time ¤t_time, Rtc_path const &rtc_path) +void Libc::init_time(Current_time ¤t_time, + Rtc_path const &rtc_path, + Watch &watch) { static Rtc_path rtc_path_inst = rtc_path; _current_time_ptr = ¤t_time; _rtc_path = rtc_path_inst.string(); + _watch_ptr = &watch; } @@ -51,21 +56,23 @@ struct Libc::Rtc : Vfs::Watch_response_handler Rtc_path const _rtc_path; + Watch &_watch; + bool _read_file { true }; time_t _rtc_value { 0 }; bool const _rtc_path_valid = (_rtc_path != ""); - Rtc(Rtc_path const &rtc_path) + Rtc(Rtc_path const &rtc_path, Watch &watch) : - _rtc_path(rtc_path) + _rtc_path(rtc_path), _watch(watch) { if (!_rtc_path_valid) { warning("rtc not configured, returning ", _rtc_value); return; } - _watch_handle = watch(_rtc_path.string()); + _watch_handle = _watch.alloc_watch_handle(_rtc_path.string()); if (_watch_handle) { _watch_handle->handler(this); } @@ -134,15 +141,17 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) if (!ts) return Errno(EFAULT); + struct Missing_call_of_init_time : Exception { }; + auto current_time = [&] () { - struct Missing_call_of_init_time : Exception { }; if (!_current_time_ptr) throw Missing_call_of_init_time(); return _current_time_ptr->current_time(); }; + /* initialize timespec just in case users do not check for errors */ ts->tv_sec = 0; ts->tv_nsec = 0; @@ -153,10 +162,13 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) case CLOCK_REALTIME: case CLOCK_SECOND: /* FreeBSD specific */ { + if (!_watch_ptr) + throw Missing_call_of_init_time(); + /* * XXX move instance to Libc::Kernel */ - static Rtc rtc(_rtc_path); + static Rtc rtc(_rtc_path, *_watch_ptr); time_t const rtc_value = rtc.read(); if (!rtc_value) return Errno(EINVAL);