mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 11:16:57 +00:00
Noux: more useful gettimeofday() implementation
There are certain programs that need gettimeofday(), e.g. network-related tools like ping(1) etc. but also filesystem-related programs like find(1) etc. and of course time-related programs like date(1). As there is currently no interface in Genode for actually using clock devices like RTC on x86 (though there is a driver for it) we "abuse" the timeout_scheduler thread to at least provide flow-of-time. Noux: add clock_gettime() implementation For now, only CLOCK_SECOND is supported. Noux: add utimes() dummy Fixes #401
This commit is contained in:
parent
81e0bfefb6
commit
837f913094
@ -72,6 +72,9 @@ namespace Noux {
|
||||
SYSCALL_SHUTDOWN,
|
||||
SYSCALL_CONNECT,
|
||||
SYSCALL_USERINFO,
|
||||
SYSCALL_GETTIMEOFDAY,
|
||||
SYSCALL_CLOCK_GETTIME,
|
||||
SYSCALL_UTIMES,
|
||||
SYSCALL_INVALID = -1
|
||||
};
|
||||
|
||||
@ -116,6 +119,9 @@ namespace Noux {
|
||||
NOUX_DECL_SYSCALL_NAME(SHUTDOWN)
|
||||
NOUX_DECL_SYSCALL_NAME(CONNECT)
|
||||
NOUX_DECL_SYSCALL_NAME(USERINFO)
|
||||
NOUX_DECL_SYSCALL_NAME(GETTIMEOFDAY)
|
||||
NOUX_DECL_SYSCALL_NAME(CLOCK_GETTIME)
|
||||
NOUX_DECL_SYSCALL_NAME(UTIMES)
|
||||
case SYSCALL_INVALID: return 0;
|
||||
}
|
||||
return 0;
|
||||
|
@ -284,6 +284,11 @@ namespace Noux {
|
||||
typedef char Home[MAX_HOME_LEN];
|
||||
typedef unsigned int Uid;
|
||||
|
||||
/**
|
||||
* time/clock definitions
|
||||
*/
|
||||
enum Clock_Id { CLOCK_ID_SECOND };
|
||||
|
||||
enum General_error { ERR_FD_INVALID, NUM_GENERAL_ERRORS };
|
||||
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
|
||||
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
|
||||
@ -337,6 +342,13 @@ namespace Noux {
|
||||
enum Socket_error { SOCKET_ERR_ACCESS, SOCKET_ERR_NO_AF_SUPPORT,
|
||||
SOCKET_ERR_INVALID, SOCKET_ERR_NO_MEMORY };
|
||||
|
||||
enum Clock_error { CLOCK_ERR_INVALID, CLOCK_ERR_FAULT, CLOCK_ERR_NO_PERM };
|
||||
|
||||
enum Utimes_error { UTIMES_ERR_ACCESS, UTIMES_ERR_FAUL, UTIMES_ERR_EIO,
|
||||
UTIMES_ERR_NAME_TOO_LONG, UTIMES_ERR_NO_ENTRY,
|
||||
UTIMES_ERR_NOT_DIRECTORY, UTIMES_ERR_NO_PERM,
|
||||
UTIMES_ERR_READ_ONLY };
|
||||
|
||||
union {
|
||||
General_error general;
|
||||
Stat_error stat;
|
||||
@ -359,6 +371,8 @@ namespace Noux {
|
||||
Send_error send;
|
||||
Shutdown_error shutdown;
|
||||
Socket_error socket;
|
||||
Clock_error clock;
|
||||
Utimes_error utimes;
|
||||
} error;
|
||||
|
||||
union {
|
||||
@ -462,6 +476,14 @@ namespace Noux {
|
||||
SYSIO_DECL(userinfo, { int request; Uid uid; },
|
||||
{ User name; Uid uid; Uid gid; Shell shell;
|
||||
Home home; });
|
||||
|
||||
SYSIO_DECL(gettimeofday, { }, { unsigned long sec; unsigned int usec; });
|
||||
|
||||
SYSIO_DECL(clock_gettime, { Clock_Id clock_id; },
|
||||
{ unsigned long sec; unsigned long nsec; });
|
||||
|
||||
SYSIO_DECL(utimes, { Path path; unsigned long sec; unsigned long usec; },
|
||||
{ });
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -456,21 +456,52 @@ extern "C" pid_t _wait4(pid_t pid, int *status, int options,
|
||||
|
||||
extern "C" int clock_gettime(clockid_t clk_id, struct timespec *tp)
|
||||
{
|
||||
if (verbose)
|
||||
PDBG("clock_gettime called - not implemented");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
/* we currently only support CLOCK_SECOND */
|
||||
switch (clk_id) {
|
||||
case CLOCK_SECOND:
|
||||
sysio()->clock_gettime_in.clock_id = Noux::Sysio::CLOCK_ID_SECOND;
|
||||
break;
|
||||
default:
|
||||
/* let's save the trip to noux and return directly */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_CLOCK_GETTIME)) {
|
||||
switch (sysio()->error.clock) {
|
||||
case Noux::Sysio::CLOCK_ERR_INVALID: errno = EINVAL; break;
|
||||
default: errno = 0; break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tp->tv_sec = sysio()->clock_gettime_out.sec;
|
||||
tp->tv_nsec = sysio()->clock_gettime_out.nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
if (verbose)
|
||||
PDBG("gettimeofday() called - not implemented");
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_GETTIMEOFDAY)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tv) {
|
||||
tv->tv_sec = 0;
|
||||
tv->tv_usec = 0;
|
||||
tv->tv_sec = sysio()->gettimeofday_out.sec;
|
||||
tv->tv_usec = sysio()->gettimeofday_out.usec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int utimes(const char* path, const struct timeval *times)
|
||||
{
|
||||
if (!noux()->syscall(Noux::Session::SYSCALL_UTIMES)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -70,7 +70,7 @@ namespace Noux {
|
||||
}
|
||||
|
||||
public:
|
||||
Timeout_scheduler() : _curr_time(0) { start(); }
|
||||
Timeout_scheduler(unsigned long curr_time) : _curr_time(curr_time) { start(); }
|
||||
|
||||
Alarm::Time curr_time() const { return _curr_time; }
|
||||
};
|
||||
@ -595,6 +595,70 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYSCALL_GETTIMEOFDAY:
|
||||
{
|
||||
/**
|
||||
* Since the timeout_scheduler thread is started after noux it
|
||||
* basicly returns the eleapsed time since noux was started. We
|
||||
* abuse this timer to provide a more useful implemenation of
|
||||
* gettimeofday() to make certain programs (e.g. ping(1)) happy.
|
||||
* Note: this is just a short-term solution because Genode currently
|
||||
* lacks a proper time interface (there is a RTC driver however, but
|
||||
* there is no interface for it).
|
||||
*/
|
||||
unsigned long time = Noux::timeout_scheduler()->curr_time();
|
||||
|
||||
_sysio->gettimeofday_out.sec = (time / 1000);
|
||||
_sysio->gettimeofday_out.usec = (time % 1000) * 1000;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYSCALL_CLOCK_GETTIME:
|
||||
{
|
||||
/**
|
||||
* It's the same procedure as in SYSCALL_GETTIMEOFDAY.
|
||||
*/
|
||||
unsigned long time = Noux::timeout_scheduler()->curr_time();
|
||||
|
||||
switch (_sysio->clock_gettime_in.clock_id) {
|
||||
|
||||
/* CLOCK_SECOND is used by time(3) in the libc. */
|
||||
case Sysio::CLOCK_ID_SECOND:
|
||||
{
|
||||
_sysio->clock_gettime_out.sec = (time / 1000);
|
||||
_sysio->clock_gettime_out.nsec = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
_sysio->clock_gettime_out.sec = 0;
|
||||
_sysio->clock_gettime_out.nsec = 0;
|
||||
_sysio->error.clock = Sysio::CLOCK_ERR_INVALID;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
case SYSCALL_UTIMES:
|
||||
{
|
||||
/**
|
||||
* This systemcall is currently not implemented because we lack
|
||||
* the needed mechanisms in most file-systems.
|
||||
*
|
||||
* But we return true anyway to keep certain programs, e.g. make
|
||||
* happy.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYSCALL_SOCKET:
|
||||
case SYSCALL_GETSOCKOPT:
|
||||
case SYSCALL_SETSOCKOPT:
|
||||
@ -713,7 +777,7 @@ Noux::Pid_allocator *Noux::pid_allocator()
|
||||
|
||||
Noux::Timeout_scheduler *Noux::timeout_scheduler()
|
||||
{
|
||||
static Noux::Timeout_scheduler inst;
|
||||
static Noux::Timeout_scheduler inst(0);
|
||||
return &inst;
|
||||
}
|
||||
|
||||
|
@ -176,6 +176,9 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
||||
case SYSCALL_READLINK:
|
||||
case SYSCALL_SYMLINK:
|
||||
case SYSCALL_USERINFO:
|
||||
case SYSCALL_GETTIMEOFDAY:
|
||||
case SYSCALL_CLOCK_GETTIME:
|
||||
case SYSCALL_UTIMES:
|
||||
break;
|
||||
case SYSCALL_SOCKET:
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user