libc: rudimentary support for SIGALRM

This patch enables basic use cases of the POSIX 'alarm' function, which
schedules the delivery of a SIGALRM signal after a specified amount of
seconds.

Issue #5337
This commit is contained in:
Norman Feske 2024-08-30 15:39:29 +02:00 committed by Christian Helmuth
parent 0a178dc625
commit fc3bd14da0
16 changed files with 214 additions and 2 deletions

View File

@ -681,6 +681,7 @@ set default_test_pkgs {
test-libc_fifo_pipe
test-libc_fork
test-libc_getenv
test-libc_alarm
test-libc_pipe
test-libc_vfs
test-libc_vfs_audit

View File

@ -12,7 +12,7 @@ LIBS += base vfs
# Back end
#
SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc \
issetugid.cc errno.cc gai_strerror.cc time.cc \
issetugid.cc errno.cc gai_strerror.cc time.cc alarm.cc \
malloc.cc progname.cc fd_alloc.cc file_operations.cc \
plugin.cc plugin_registry.cc select.cc exit.cc environ.cc sleep.cc \
pread_pwrite.cc readv_writev.cc poll.cc \

View File

@ -0,0 +1 @@
Libc alarm() test.

View File

@ -0,0 +1,5 @@
_/src/init
_/src/test-libc_alarm
_/src/libc
_/src/posix
_/src/vfs

View File

@ -0,0 +1 @@
2024-08-30 ca6e62da4a88ade9338dea365858d83409150c78

View File

@ -0,0 +1,22 @@
<runtime ram="3M" caps="200" binary="test-libc_alarm">
<requires> <timer/> </requires>
<fail after_seconds="13"/>
<succeed>triggered_alarms=3</succeed>
<content>
<rom label="ld.lib.so"/>
<rom label="test-libc_alarm"/>
<rom label="libc.lib.so"/>
<rom label="libm.lib.so"/>
<rom label="vfs.lib.so"/>
<rom label="posix.lib.so"/>
</content>
<config>
<vfs> <dir name="dev"> <log/> </dir> </vfs>
<libc stdout="/dev/log" stderr="/dev/log"/>
<arg value="test-libc_alarm"/>
</config>
</runtime>

View File

@ -0,0 +1,2 @@
SRC_DIR := src/test/libc_alarm
include $(GENODE_DIR)/repos/base/recipes/src/content.inc

View File

@ -0,0 +1 @@
2024-08-30 49e1a2b9ef6049be7c0fcee964324fbda54cbed7

View File

@ -0,0 +1,2 @@
libc
posix

View File

@ -0,0 +1,118 @@
/*
* \brief Libc interval timer
* \author Norman Feske
* \date 2024-08-00
*/
/*
* Copyright (C) 2024 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.
*/
/* libc includes */
#include <sys/time.h>
/* libc-internal includes */
#include <internal/signal.h>
#include <internal/timer.h>
#include <internal/init.h>
#include <internal/errno.h>
static Libc::Timer_accessor *_timer_accessor_ptr;
static Libc::Signal *_signal_ptr;
void Libc::init_alarm(Timer_accessor &timer_accessor, Signal &signal)
{
_timer_accessor_ptr = &timer_accessor;
_signal_ptr = &signal;
}
namespace Libc { struct Itimer_real; }
struct Libc::Itimer_real : Noncopyable
{
struct Handler : Timeout_handler
{
Signal &_signal;
virtual void handle_timeout() override { _signal.charge(SIGALRM); }
Handler(Signal &signal) : _signal(signal) { }
} _handler;
Timer_accessor &_timer_accessor;
Constructible<Timeout> _timeout { };
void arm_or_disarm(timeval tv)
{
Libc::uint64_t const ms = tv.tv_sec*1000 + tv.tv_usec/1000;
if (ms) {
_timeout.construct(_timer_accessor, _handler);
_timeout->start(ms);
} else {
_timeout.destruct();
}
}
timeval current()
{
if (!_timeout.constructed())
return { };
Libc::uint64_t const ms = _timeout->duration_left();
return { .tv_sec = long(ms/1000),
.tv_usec = long((ms % 1000)*1000) };
}
Itimer_real(Timer_accessor &timer_accessor, Signal &signal)
:
_handler(signal), _timer_accessor(timer_accessor)
{ }
};
using namespace Libc;
static Itimer_real &itimer_real()
{
struct Missing_call_of_init_alarm : Exception { };
if (!_timer_accessor_ptr || !_signal_ptr)
throw Missing_call_of_init_alarm();
static Itimer_real itimer { *_timer_accessor_ptr, *_signal_ptr };
return itimer;
}
extern "C" int setitimer(int which, const itimerval *new_value, itimerval *old_value)
{
if (which != ITIMER_REAL) {
warning("setitimer: timer %d unsupported");
return Errno(EINVAL);
}
if (!new_value)
return Errno(EFAULT);
if (new_value->it_interval.tv_sec || new_value->it_interval.tv_usec)
warning("setitimer: argument 'new_value->it_interval' not handled");
if (old_value) {
old_value->it_interval = { };
old_value->it_value = itimer_real().current();
}
itimer_real().arm_or_disarm(new_value->it_value);
return 0;
}

View File

@ -141,7 +141,6 @@ DUMMY(int , -1, seteuid, (uid_t))
DUMMY(int , -1, setgid, (gid_t))
DUMMY(int , -1, setuid, (uid_t))
DUMMY(int , -1, setgroups, (int, const gid_t *))
DUMMY(int , -1, setitimer, (int, const itimerval *, itimerval *))
DUMMY(int , -1, setpgid, (pid_t, pid_t))
DUMMY(int , -1, setpriority, (int, int, int))
DUMMY(int , -1, setregid, (gid_t, gid_t))

View File

@ -108,6 +108,7 @@ namespace Libc {
*/
void init_sleep(Monitor &);
void init_time(Current_time &, Current_real_time &);
void init_alarm(Timer_accessor &, Signal &);
/**
* Socket fs

View File

@ -16,10 +16,13 @@
/* Genode includes */
#include <util/noncopyable.h>
#include <util/reconstructible.h>
#include <base/registry.h>
#include <base/thread.h>
/* libc includes */
#include <signal.h>
#include <stdlib.h>
/* libc-internal includes */
#include <internal/call_func.h>

View File

@ -508,6 +508,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
init_vfs_plugin(*this, _env.rm());
init_file_operations(*this, _libc_env);
init_time(*this, *this);
init_alarm(_timer_accessor, _signal);
init_poll(_signal, *this);
init_select(*this);
init_socket_fs(*this, *this);

View File

@ -0,0 +1,52 @@
/*
* \brief Libc alarm test
* \author Norman Feske
* \date 2024-08-30
*/
/*
* Copyright (C) 2024 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.
*/
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
static unsigned triggered_alarms;
static void sigalarm_handler(int)
{
triggered_alarms++;
}
int main(int, char **)
{
static struct sigaction sa;
sa.sa_handler = sigalarm_handler;
int ret = sigaction(SIGALRM, &sa, NULL);
if (ret < 0) {
printf("sigaction unexpectedly returned %d\n", ret);
return 1;
}
signal(SIGALRM, sigalarm_handler);
unsigned observed_alarms = 0;
alarm(2);
while (observed_alarms != 3) {
sleep(1);
printf("triggered_alarms=%u\n", triggered_alarms);
if (triggered_alarms != observed_alarms) {
observed_alarms = triggered_alarms;
alarm(2);
}
}
return 0;
}

View File

@ -0,0 +1,3 @@
TARGET = test-libc_alarm
SRC_C = main.c
LIBS = posix