From 2d94cd1246c689e4c7564aea2f62eccf027501cc Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 12 May 2013 01:24:42 +0200 Subject: [PATCH] Add alarm(2) and alarmns(2). --- libc/Makefile | 2 + libc/alarm.cpp | 35 ++++++++++++++ libc/alarmns.cpp | 35 ++++++++++++++ libc/include/unistd.h | 7 ++- sortix/Makefile | 1 + sortix/alarm.cpp | 73 ++++++++++++++++++++++++++++++ sortix/alarm.h | 31 +++++++++++++ sortix/include/sortix/syscallnum.h | 3 +- sortix/kernel.cpp | 4 ++ sortix/process.cpp | 28 +++++++++--- sortix/process.h | 2 + 11 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 libc/alarm.cpp create mode 100644 libc/alarmns.cpp create mode 100644 sortix/alarm.cpp create mode 100644 sortix/alarm.h diff --git a/libc/Makefile b/libc/Makefile index ab6573e1..28ef0488 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -161,6 +161,8 @@ wctype.o \ HOSTEDOBJS=\ access.o \ +alarmns.o \ +alarm.o \ arpa/inet/inet_addr.o \ arpa/inet/inet_ntoa.o \ arpa/inet/inet_ntop.o \ diff --git a/libc/alarm.cpp b/libc/alarm.cpp new file mode 100644 index 00000000..ad41f115 --- /dev/null +++ b/libc/alarm.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + alarm.cpp + Set an alarm clock for delivery of a signal. + +*******************************************************************************/ + +#include +#include + +extern "C" unsigned int alarm(unsigned int seconds) +{ + struct timespec delay = timespec_make(seconds, 0); + struct timespec odelay; + if ( alarmns(&delay, &odelay) < 0 ) + return 0; + return odelay.tv_sec + (odelay.tv_nsec ? 1 : 0); +} diff --git a/libc/alarmns.cpp b/libc/alarmns.cpp new file mode 100644 index 00000000..8ded14f5 --- /dev/null +++ b/libc/alarmns.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + alarmns.cpp + Set an alarm clock for delivery of a signal. + +*******************************************************************************/ + +#include + +#include +#include + +DEFN_SYSCALL2(int, sys_alarmns, SYSCALL_ALARMNS, const struct timespec*, struct timespec*) + +extern "C" int alarmns(const struct timespec* delay, struct timespec* odelay) +{ + return sys_alarmns(delay, odelay); +} diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 6ba88921..fe64f5df 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -34,6 +34,10 @@ #include #include #include +__BEGIN_DECLS +@include(time_t.h) +__END_DECLS +#include #endif #include #include @@ -259,7 +263,6 @@ extern char** environ; /* TODO: These are not implemented in sortix libc yet. */ #if defined(__SORTIX_SHOW_UNIMPLEMENTED) -unsigned alarm(unsigned); char* crypt(const char*, const char*); char* ctermid(char*); void encrypt(char [64], int); @@ -296,6 +299,7 @@ extern int opterr, optind, optopt; #endif int access(const char*, int); +unsigned alarm(unsigned); int chdir(const char*); int chown(const char*, uid_t, gid_t); int close(int); @@ -355,6 +359,7 @@ int unlink(const char*); ssize_t write(int, const void*, size_t); #if defined(_SORTIX_SOURCE) +int alarmns(const struct timespec* delay, struct timespec* odelay); int execvpe(const char*, char* const [], char* const []); int getdtablesize(void); size_t getpagesize(void); diff --git a/sortix/Makefile b/sortix/Makefile index 5c829627..e0eefbae 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -72,6 +72,7 @@ LIBS=\ OBJS=\ $(CPUOBJS) \ addralloc.o \ +alarm.o \ ata.o \ bga.o \ calltrace.o \ diff --git a/sortix/alarm.cpp b/sortix/alarm.cpp new file mode 100644 index 00000000..3d8b3135 --- /dev/null +++ b/sortix/alarm.cpp @@ -0,0 +1,73 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + alarm.cpp + Sends a signal after a certain amount of time has passed. + +*******************************************************************************/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "process.h" + +namespace Sortix { +namespace Alarm { + +static void alarm_handler(Clock* /*clock*/, Timer* /*timer*/, void* user) +{ + Process* process = (Process*) user; + ScopedLock lock(&process->user_timers_lock); + process->DeliverSignal(SIGALRM); +} + +int sys_alarmns(const struct timespec* user_delay, struct timespec* user_odelay) +{ + Process* process = CurrentProcess(); + ScopedLock lock(&process->user_timers_lock); + + struct itimerspec delay, odelay; + if ( !CopyFromUser(&delay.it_value, user_delay, sizeof(*user_delay)) ) + return -1; + delay.it_interval = timespec_nul(); + + process->alarm_timer.Set(&delay, &odelay, 0, alarm_handler, (void*) process); + + if ( !CopyToUser(user_odelay, &odelay.it_value, sizeof(*user_odelay)) ) + return -1; + + return 0; +} + +void Init() +{ + Syscall::Register(SYSCALL_ALARMNS, (void*) sys_alarmns); +} + +} // namespace Alarm +} // namespace Sortix diff --git a/sortix/alarm.h b/sortix/alarm.h new file mode 100644 index 00000000..5e1d4747 --- /dev/null +++ b/sortix/alarm.h @@ -0,0 +1,31 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + alarm.h + Sends a signal after a certain amount of time has passed. + +*******************************************************************************/ + +namespace Sortix { +namespace Alarm { + +void Init(); + +} // namespace Alarm +} // namespace Sortix diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index 1b90bbe6..43cc3cb3 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -123,6 +123,7 @@ #define SYSCALL_TIMER_GETOVERRUN 99 #define SYSCALL_TIMER_GETTIME 100 #define SYSCALL_TIMER_SETTIME 101 -#define SYSCALL_MAX_NUM 102 /* index of highest constant + 1 */ +#define SYSCALL_ALARMNS 102 +#define SYSCALL_MAX_NUM 103 /* index of highest constant + 1 */ #endif diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index d8f43dcf..15b569a3 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -65,6 +65,7 @@ #include "thread.h" #include "process.h" #include "signal.h" +#include "alarm.h" #include "ata.h" #include "com.h" #include "uart.h" @@ -429,6 +430,9 @@ static void BootThread(void* /*user*/) // Initialize per-process timers. UserTimer::Init(); + // Initialize per-process alarm timer. + Alarm::Init(); + // Initialize the kernel information query syscall. Info::Init(); diff --git a/sortix/process.cpp b/sortix/process.cpp index 16ee19b7..187895cf 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -129,11 +130,14 @@ namespace Sortix pid = AllocatePID(); uid = euid = 0; gid = egid = 0; + alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC)); Put(this); } Process::~Process() { + if ( alarm_timer.IsAttached() ) + alarm_timer.Detach(); if ( program_image_path ) delete[] program_image_path; assert(!zombiechild); @@ -221,6 +225,18 @@ namespace Sortix ((Thread*) user)->SwitchAddressSpace(addrspace); } + void Process::DeleteTimers() + { + for ( timer_t i = 0; i < PROCESS_TIMER_NUM_MAX; i++ ) + { + if ( user_timers[i].timer.IsAttached() ) + { + user_timers[i].timer.Cancel(); + user_timers[i].timer.Detach(); + } + } + } + void Process::LastPrayer() { assert(this); @@ -236,13 +252,11 @@ namespace Sortix assert(!firstthread); // Disarm and detach all the timers in the process. - for ( timer_t i = 0; i < PROCESS_TIMER_NUM_MAX; i++ ) + DeleteTimers(); + if ( alarm_timer.IsAttached() ) { - if ( user_timers[i].timer.IsAttached() ) - { - user_timers[i].timer.Cancel(); - user_timers[i].timer.Detach(); - } + alarm_timer.Cancel(); + alarm_timer.Detach(); } // We need to temporarily reload the correct addrese space of the dying @@ -617,6 +631,8 @@ namespace Sortix { // TODO: Delete all threads and their stacks. + DeleteTimers(); + ResetAddressSpace(); } diff --git a/sortix/process.h b/sortix/process.h index 49f7be67..1a5b4c6f 100644 --- a/sortix/process.h +++ b/sortix/process.h @@ -145,6 +145,7 @@ namespace Sortix public: kthread_mutex_t user_timers_lock; UserTimer user_timers[PROCESS_TIMER_NUM_MAX]; + Timer alarm_timer; public: int Execute(const char* programname, const uint8_t* program, @@ -172,6 +173,7 @@ namespace Sortix void LastPrayer(); void NotifyChildExit(Process* child, bool zombify); void NotifyNewZombies(); + void DeleteTimers(); public: void ResetForExecute();