* 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, extern status_t _user_sigaction(int sig, const struct sigaction *newAction,
struct sigaction *oldAction); struct sigaction *oldAction);
extern bigtime_t _user_set_alarm(bigtime_t time, uint32 mode); 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_sigsuspend(const sigset_t *mask);
extern status_t _user_sigpending(sigset_t *set); extern status_t _user_sigpending(sigset_t *set);
extern status_t _user_set_signal_stack(const stack_t *newUserStack, extern status_t _user_set_signal_stack(const stack_t *newUserStack,
+4 -3
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, extern status_t _kern_sigaction(int sig, const struct sigaction *action,
struct sigaction *oldAction); struct sigaction *oldAction);
extern bigtime_t _kern_set_alarm(bigtime_t time, uint32 mode); 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_sigsuspend(const sigset_t *mask);
extern status_t _kern_sigpending(sigset_t *set); extern status_t _kern_sigpending(sigset_t *set);
extern status_t _kern_set_signal_stack(const stack_t *newStack, extern status_t _kern_set_signal_stack(const stack_t *newStack,
@@ -248,7 +249,7 @@ extern status_t _kern_resize_area(area_id area, size_t newSize);
extern area_id _kern_transfer_area(area_id area, void **_address, uint32 addressSpec, extern area_id _kern_transfer_area(area_id area, void **_address, uint32 addressSpec,
team_id target); team_id target);
extern status_t _kern_set_area_protection(area_id area, uint32 newProtection); extern status_t _kern_set_area_protection(area_id area, uint32 newProtection);
extern area_id _kern_clone_area(const char *name, void **_address, uint32 addressSpec, extern area_id _kern_clone_area(const char *name, void **_address, uint32 addressSpec,
uint32 protection, area_id sourceArea); uint32 protection, area_id sourceArea);
extern status_t _kern_reserve_heap_address_range(addr_t* _address, uint32 addressSpec, extern status_t _kern_reserve_heap_address_range(addr_t* _address, uint32 addressSpec,
addr_t size); addr_t size);
@@ -296,7 +297,7 @@ extern int32 _kern_atomic_set(vint32 *value, int32 newValue);
extern int32 _kern_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst); extern int32 _kern_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst);
extern int32 _kern_atomic_add(vint32 *value, int32 addValue); extern int32 _kern_atomic_add(vint32 *value, int32 addValue);
extern int32 _kern_atomic_and(vint32 *value, int32 andValue); extern int32 _kern_atomic_and(vint32 *value, int32 andValue);
extern int32 _kern_atomic_or(vint32 *value, int32 orValue); extern int32 _kern_atomic_or(vint32 *value, int32 orValue);
extern int32 _kern_atomic_get(vint32 *value); extern int32 _kern_atomic_get(vint32 *value);
#endif // ATOMIC_FUNCS_ARE_SYSCALLS #endif // ATOMIC_FUNCS_ARE_SYSCALLS
@@ -305,7 +306,7 @@ extern int64 _kern_atomic_set64(vint64 *value, int64 newValue);
extern int64 _kern_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst); extern int64 _kern_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst);
extern int64 _kern_atomic_add64(vint64 *value, int64 addValue); extern int64 _kern_atomic_add64(vint64 *value, int64 addValue);
extern int64 _kern_atomic_and64(vint64 *value, int64 andValue); extern int64 _kern_atomic_and64(vint64 *value, int64 andValue);
extern int64 _kern_atomic_or64(vint64 *value, int64 orValue); extern int64 _kern_atomic_or64(vint64 *value, int64 orValue);
extern int64 _kern_atomic_get64(vint64 *value); extern int64 _kern_atomic_get64(vint64 *value);
#endif // ATOMIC64_FUNCS_ARE_SYSCALLS #endif // ATOMIC64_FUNCS_ARE_SYSCALLS
+68 -7
View File
@@ -7,6 +7,8 @@
/*! POSIX signals handling routines */ /*! POSIX signals handling routines */
#include <ksignal.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@@ -17,8 +19,8 @@
#include <debug.h> #include <debug.h>
#include <kernel.h> #include <kernel.h>
#include <kscheduler.h> #include <kscheduler.h>
#include <ksignal.h>
#include <sem.h> #include <sem.h>
#include <syscall_restart.h>
#include <team.h> #include <team.h>
#include <thread.h> #include <thread.h>
#include <tracing.h> #include <tracing.h>
@@ -203,7 +205,7 @@ class SigProcMask : public AbstractTraceEntry {
#endif // SIGNAL_TRACING #endif // SIGNAL_TRACING
// #pragma mark - // #pragma mark -
/*! Updates the thread::flags field according to what signals are pending. /*! Updates the thread::flags field according to what signals are pending.
@@ -482,7 +484,7 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags)
if (flags & B_CHECK_PERMISSION) { if (flags & B_CHECK_PERMISSION) {
// ToDo: introduce euid & uid fields to the team and check permission // ToDo: introduce euid & uid fields to the team and check permission
} }
if (signal == 0) if (signal == 0)
return B_OK; return B_OK;
@@ -560,7 +562,7 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0) if ((flags & SIGNAL_FLAG_TEAMS_LOCKED) == 0)
state = disable_interrupts(); state = disable_interrupts();
if (id > 0) { if (id > 0) {
// send a signal to the specified thread // send a signal to the specified thread
@@ -574,7 +576,7 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
// (the absolute value of the id) // (the absolute value of the id)
struct process_group *group; struct process_group *group;
// TODO: handle -1 correctly // TODO: handle -1 correctly
if (id == 0 || id == -1) { if (id == 0 || id == -1) {
// send a signal to the current team // send a signal to the current team
@@ -612,7 +614,7 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
RELEASE_TEAM_LOCK(); RELEASE_TEAM_LOCK();
GRAB_THREAD_LOCK(); GRAB_THREAD_LOCK();
} }
// ToDo: maybe the scheduler should only be invoked if there is reason to do it? // ToDo: maybe the scheduler should only be invoked if there is reason to do it?
// (ie. deliver_signal() moved some threads in the running queue?) // (ie. deliver_signal() moved some threads in the running queue?)
@@ -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. /*! Replace the current signal block mask and wait for any event to happen.
Before returning, the original signal block mask is reinstantiated. Before returning, the original signal block mask is reinstantiated.
*/ */
@@ -843,7 +885,7 @@ sigpending(sigset_t *set)
if (set == NULL) if (set == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
*set = atomic_get(&thread->sig_pending); *set = atomic_get(&thread->sig_pending);
return B_OK; return B_OK;
} }
@@ -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 status_t
_user_sigsuspend(const sigset_t *userMask) _user_sigsuspend(const sigset_t *userMask)
{ {
+1
View File
@@ -19,5 +19,6 @@ MergeObject posix_signal.o :
sigrelse.cpp sigrelse.cpp
sigset.c sigset.c
sigsuspend.c sigsuspend.c
sigwait.c
strsignal.c strsignal.c
; ;
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. 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
}