* Implemented sigwait().

* Not sure if it works as intended, as the specs are a bit vague.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24717 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-04-01 12:15:14 +00:00
parent 4d3ebacc42
commit 10f0fc8f20
5 changed files with 92 additions and 10 deletions
+1
View File
@@ -40,6 +40,7 @@ extern status_t _user_sigprocmask(int how, const sigset_t *set,
extern status_t _user_sigaction(int sig, const struct sigaction *newAction,
struct sigaction *oldAction);
extern bigtime_t _user_set_alarm(bigtime_t time, uint32 mode);
extern status_t _user_sigwait(const sigset_t *set, int *_signal);
extern status_t _user_sigsuspend(const sigset_t *mask);
extern status_t _user_sigpending(sigset_t *set);
extern status_t _user_set_signal_stack(const stack_t *newUserStack,
+1
View File
@@ -131,6 +131,7 @@ extern status_t _kern_sigprocmask(int how, const sigset_t *set,
extern status_t _kern_sigaction(int sig, const struct sigaction *action,
struct sigaction *oldAction);
extern bigtime_t _kern_set_alarm(bigtime_t time, uint32 mode);
extern status_t _kern_sigwait(const sigset_t *set, int *_signal);
extern status_t _kern_sigsuspend(const sigset_t *mask);
extern status_t _kern_sigpending(sigset_t *set);
extern status_t _kern_set_signal_stack(const stack_t *newStack,
+62 -1
View File
@@ -7,6 +7,8 @@
/*! POSIX signals handling routines */
#include <ksignal.h>
#include <stddef.h>
#include <string.h>
@@ -17,8 +19,8 @@
#include <debug.h>
#include <kernel.h>
#include <kscheduler.h>
#include <ksignal.h>
#include <sem.h>
#include <syscall_restart.h>
#include <team.h>
#include <thread.h>
#include <tracing.h>
@@ -798,6 +800,46 @@ set_alarm(bigtime_t time, uint32 mode)
}
/*! Wait for the specified signals, and return the signal retrieved in
\a _signal.
*/
int
sigwait(const sigset_t *set, int *_signal)
{
struct thread *thread = thread_get_current_thread();
int signalsPending = 0;
ConditionVariable<sigset_t> conditionVar;
conditionVar.Publish(set, "sigwait");
while (true) {
ConditionVariableEntry<sigset_t> entry;
entry.Wait(set, B_CAN_INTERRUPT);
if (has_signals_pending(thread)) {
signalsPending = atomic_get(&thread->sig_pending) & *set;
break;
}
}
conditionVar.Unpublish();
update_current_thread_signals_flag();
if (signalsPending) {
// select the lowest pending signal to return in _signal
for (int signal = 1; signal < NSIG; signal++) {
if ((SIGNAL_TO_MASK(signal) & signalsPending) != 0) {
*_signal = signal;
return B_OK;
}
}
}
return B_INTERRUPTED;
}
/*! Replace the current signal block mask and wait for any event to happen.
Before returning, the original signal block mask is reinstantiated.
*/
@@ -915,6 +957,25 @@ _user_sigaction(int signal, const struct sigaction *userAction,
}
status_t
_user_sigwait(const sigset_t *userSet, int *_userSignal)
{
if (userSet == NULL || _userSignal == NULL)
return B_BAD_VALUE;
sigset_t set;
if (user_memcpy(&set, userSet, sizeof(sigset_t)) < B_OK)
return B_BAD_ADDRESS;
int signal;
status_t status = sigwait(&set, &signal);
if (status < B_OK)
return syscall_restart_handle_post(status);
return user_memcpy(_userSignal, &signal, sizeof(int));
}
status_t
_user_sigsuspend(const sigset_t *userMask)
{
+1
View File
@@ -19,5 +19,6 @@ MergeObject posix_signal.o :
sigrelse.cpp
sigset.c
sigsuspend.c
sigwait.c
strsignal.c
;
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <syscalls.h>
#include <signal.h>
int
sigwait(const sigset_t *set, int *_signal)
{
return _kern_sigwait(set, _signal);
// does not set errno, but returns the error value directly
}