* 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:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user