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();