posix signals support, 1st pass
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1623 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -60,6 +60,9 @@ status_t sys_get_next_thread_info(team_id team, int32 *cookie, thread_info *info
|
||||
status_t sys_get_team_info(team_id id, team_info *info);
|
||||
status_t sys_get_next_team_info(int32 *cookie, team_info *info);
|
||||
|
||||
int sys_kill(pid_t pid, int sig);
|
||||
int sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
||||
|
||||
region_id sys_vm_create_anonymous_region(const char *name, void **address, int addr_type,
|
||||
addr size, int wiring, int lock);
|
||||
region_id sys_vm_clone_region(const char *name, void **address, int addr_type,
|
||||
|
||||
@@ -21,6 +21,7 @@ extern "C" {
|
||||
#include <cbuf.h>
|
||||
#include <vm.h>
|
||||
#include <smp.h>
|
||||
#include <signal.h>
|
||||
#include <arch/thread_struct.h>
|
||||
|
||||
extern spinlock_t thread_spinlock;
|
||||
@@ -101,7 +102,11 @@ struct thread {
|
||||
int state;
|
||||
int next_state;
|
||||
union cpu_ent *cpu;
|
||||
int pending_signals;
|
||||
|
||||
sigset_t sig_pending;
|
||||
sigset_t sig_block_mask;
|
||||
struct sigaction sig_action[32];
|
||||
|
||||
bool in_kernel;
|
||||
sem_id sem_blocking;
|
||||
int sem_count;
|
||||
|
||||
@@ -178,6 +178,10 @@ enum {
|
||||
#define EOPNOTSUPP (B_POSIX_ERROR_BASE + 43)
|
||||
#define ENOTSOCK (B_POSIX_ERROR_BASE + 44)
|
||||
|
||||
#define ERESTARTSYS (B_POSIX_ERROR_BASE + 45)
|
||||
#define ERESTARTNOINTR (B_POSIX_ERROR_BASE + 46)
|
||||
#define ERESTARTNOHAND (B_POSIX_ERROR_BASE + 47)
|
||||
|
||||
#define ENOMEM B_NO_MEMORY
|
||||
#define EACCES B_PERMISSION_DENIED
|
||||
#define EINTR B_INTERRUPTED
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#ifndef _SIGNAL_H_
|
||||
#define _SIGNAL_H_
|
||||
|
||||
/*
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int sig_atomic_t;
|
||||
|
||||
typedef void (*__signal_func_ptr)(int);
|
||||
|
||||
__signal_func_ptr signal(int signal, __signal_func_ptr signal_func);
|
||||
int raise(int signal);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SIG_DFL ((__signal_func_ptr) 0)
|
||||
#define SIG_IGN ((__signal_func_ptr) 1)
|
||||
#define SIG_ERR ((__signal_func_ptr)-1)
|
||||
|
||||
/*
|
||||
The numbering of signals for BeOS attempts to maintain
|
||||
some consistency with UN*X conventions so that things
|
||||
like "kill -9" do what you expect.
|
||||
*/
|
||||
#define SIGHUP 1 /* hangup -- tty is gone! */
|
||||
#define SIGINT 2 /* interrupt */
|
||||
#define SIGQUIT 3 /* `quit' special character typed in tty */
|
||||
#define SIGILL 4 /* illegal instruction */
|
||||
#define SIGCHLD 5 /* child process exited */
|
||||
#define SIGABRT 6 /* abort() called, dont' catch */
|
||||
#define SIGPIPE 7 /* write to a pipe w/no readers */
|
||||
#define SIGFPE 8 /* floating point exception */
|
||||
#define SIGKILL 9 /* kill a team (not catchable) */
|
||||
#define SIGSTOP 10 /* suspend a thread (not catchable) */
|
||||
#define SIGSEGV 11 /* segmentation violation (read: invalid pointer) */
|
||||
#define SIGCONT 12 /* continue execution if suspended */
|
||||
#define SIGTSTP 13 /* `stop' special character typed in tty */
|
||||
#define SIGALRM 14 /* an alarm has gone off (see alarm()) */
|
||||
#define SIGTERM 15 /* termination requested */
|
||||
#define SIGTTIN 16 /* read of tty from bg process */
|
||||
#define SIGTTOU 17 /* write to tty from bg process */
|
||||
#define SIGUSR1 18 /* app defined signal 1 */
|
||||
#define SIGUSR2 19 /* app defined signal 2 */
|
||||
#define SIGWINCH 20 /* tty window size changed */
|
||||
#define SIGKILLTHR 21 /* be specific: kill just the thread, not team */
|
||||
#define SIGTRAP 22
|
||||
|
||||
#define SIGBUS SIGSEGV /* for old style code */
|
||||
|
||||
/*
|
||||
Signal numbers 23-32 are currently free but may be used in future
|
||||
releases. Use them at your own peril (if you do use them, at least
|
||||
be smart and use them backwards from signal 32).
|
||||
*/
|
||||
#define __signal_max 22
|
||||
#define NSIG (__signal_max+1)
|
||||
|
||||
|
||||
|
||||
typedef long sigset_t;
|
||||
|
||||
/*
|
||||
The Posix interface for signal handling functions isn't as useful
|
||||
as it could be. The standard indicates that only a single argument
|
||||
(the signal number) is passed to the signal handler. It is useful
|
||||
to have more information and the BeOS provides two extra arguments.
|
||||
However, to remain compatible with Posix and ANSI C, we declare the
|
||||
sa_handler field of the sigaction struct as type __signal_func_ptr.
|
||||
That means you'll need to cast any function you assign to the
|
||||
sa_handler field. NOTE: C++ member functions can not be signal
|
||||
handlers (because they expect a "this" pointer as the first
|
||||
argument).
|
||||
|
||||
The 3 arguments that the BeOS provides to signal handlers are as
|
||||
follows:
|
||||
- The first argument is the signal number (as an integer).
|
||||
- The next argument is whatever value is put in the sa_userdata field
|
||||
of the sigaction struct.
|
||||
- The last argument is a pointer to a vregs struct (defined
|
||||
below). The vregs struct contains the contents of the volatile
|
||||
registers at the time the signal was delivered to your thread.
|
||||
You can change the fields of the structure. After your signal
|
||||
handler completes, the OS uses this struct to reload the
|
||||
registers for your thread (privileged registers are not loaded
|
||||
of course). The vregs struct is of course terribly machine
|
||||
dependent and is guaranteed to change, potentially even between
|
||||
different models of the PowerPC family. If you use it, you
|
||||
should expect to have to re-work your code when new processors
|
||||
come out. Nonetheless the ability to change the registers does
|
||||
open some interesting programming possibilities.
|
||||
*/
|
||||
struct sigaction {
|
||||
__signal_func_ptr sa_handler;
|
||||
sigset_t sa_mask;
|
||||
int sa_flags;
|
||||
void *sa_userdata; /* will be passed to the signal handler */
|
||||
};
|
||||
|
||||
|
||||
typedef struct stack_t {
|
||||
void *ss_sp;
|
||||
size_t ss_size;
|
||||
int ss_flags;
|
||||
} stack_t;
|
||||
|
||||
|
||||
#define SA_NOCLDSTOP 0x01 /* for sa_flags */
|
||||
#define SA_ONESHOT 0x02
|
||||
#define SA_NOMASK 0x04
|
||||
#define SA_NODEFER SA_NOMASK
|
||||
#define SA_RESTART 0x08
|
||||
#define SA_STACK 0x10
|
||||
|
||||
|
||||
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
||||
int sigemptyset(sigset_t *set);
|
||||
int sigfillset(sigset_t *set);
|
||||
int sigaddset(sigset_t *set, int signo);
|
||||
int sigdelset(sigset_t *set, int signo);
|
||||
int sigismember(const sigset_t *set, int signo);
|
||||
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
|
||||
extern const char * const sys_siglist[NSIG];
|
||||
const char *strsignal(int sig);
|
||||
const void set_signal_stack(void *ptr, size_t size);
|
||||
int sigaltstack(const stack_t *ss, stack_t *oss); /* XXXdbg */
|
||||
|
||||
extern inline int
|
||||
sigismember(const sigset_t *set, int sig)
|
||||
{
|
||||
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
|
||||
return (*set & mask) ? 1 : 0 ;
|
||||
}
|
||||
extern inline int
|
||||
sigaddset(sigset_t *set, int sig)
|
||||
{
|
||||
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
|
||||
return ((*set |= mask), 0) ;
|
||||
}
|
||||
extern inline int
|
||||
sigdelset(sigset_t *set, int sig)
|
||||
{
|
||||
sigset_t mask = (((sigset_t) 1) << (( sig ) - 1)) ;
|
||||
return ((*set &= ~mask), 0) ;
|
||||
}
|
||||
|
||||
#define SIG_BLOCK 1 /* defines for the how arg of sigprocmask() */
|
||||
#define SIG_UNBLOCK 2
|
||||
#define SIG_SETMASK 3
|
||||
|
||||
int sigpending(sigset_t *set);
|
||||
int sigsuspend(const sigset_t *mask);
|
||||
|
||||
int kill(pid_t pid, int sig);
|
||||
int send_signal(pid_t tid, uint sig);
|
||||
|
||||
|
||||
#endif /* _SIGNAL_H_ */
|
||||
@@ -18,6 +18,10 @@ void arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void
|
||||
//struct thread *arch_thread_get_current_thread(void);
|
||||
//void arch_thread_set_current_thread(struct thread *t);
|
||||
|
||||
void arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig_mask);
|
||||
int64 arch_restore_signal_frame(void);
|
||||
void arch_check_syscall_restart(struct thread *t);
|
||||
|
||||
// for any inline overrides
|
||||
#include <arch_thread.h>
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ struct iframe {
|
||||
unsigned int edx;
|
||||
unsigned int ecx;
|
||||
unsigned int eax;
|
||||
unsigned int orig_eax;
|
||||
unsigned int orig_edx;
|
||||
unsigned int vector;
|
||||
unsigned int error_code;
|
||||
unsigned int eip;
|
||||
@@ -112,6 +114,10 @@ void i386_enter_uspace(addr entry, void *args, addr ustack_top);
|
||||
void i386_set_kstack(addr kstack);
|
||||
void i386_switch_stack_and_call(addr stack, void (*func)(void *), void *arg);
|
||||
void i386_swap_pgdir(addr new_pgdir);
|
||||
void i386_fsave(void *fpu_state);
|
||||
void i386_fxsave(void *fpu_state);
|
||||
void i386_frstor(void *fpu_state);
|
||||
void i386_fxrstor(void *fpu_state);
|
||||
void i386_fsave_swap(void *old_fpu_state, void *new_fpu_state);
|
||||
void i386_fxsave_swap(void *old_fpu_state, void *new_fpu_state);
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ extern "C" {
|
||||
void i386_push_iframe(struct thread *t, struct iframe *frame);
|
||||
void i386_pop_iframe(struct thread *t);
|
||||
|
||||
void i386_return_from_signal();
|
||||
void i386_end_return_from_signal();
|
||||
|
||||
|
||||
static
|
||||
inline struct thread *
|
||||
|
||||
@@ -18,6 +18,7 @@ struct arch_thread {
|
||||
struct farcall interrupt_stack;
|
||||
|
||||
// used to track interrupts on this thread
|
||||
struct iframe *current_iframe;
|
||||
struct iframe *iframes[IFRAME_TRACE_DEPTH];
|
||||
int iframe_ptr;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ extern "C" {
|
||||
|
||||
#include <thread_types.h>
|
||||
#include <arch/thread.h>
|
||||
#include <signal.h>
|
||||
|
||||
// Uncomment the line below to compile the single-queue scheduler
|
||||
//#define NEW_SCHEDULER
|
||||
@@ -18,6 +19,10 @@ extern "C" {
|
||||
void resched(void);
|
||||
void start_scheduler(void);
|
||||
|
||||
#define BLOCKABLE_SIGS (~((1L << (SIGKILL - 1)) | (1L << (SIGSTOP - 1))))
|
||||
|
||||
void handle_signals(struct thread *t, int state);
|
||||
|
||||
void thread_enqueue(struct thread *t, struct thread_queue *q);
|
||||
struct thread *thread_lookat_queue(struct thread_queue *q);
|
||||
struct thread *thread_dequeue(struct thread_queue *q);
|
||||
@@ -45,9 +50,7 @@ int thread_kill_thread_nowait(thread_id id);
|
||||
#define thread_get_current_thread arch_thread_get_current_thread
|
||||
|
||||
struct thread *thread_get_thread_struct(thread_id id);
|
||||
#ifdef NEW_SCHEDULER
|
||||
struct thread *thread_get_thread_struct_locked(thread_id id);
|
||||
#endif /* NEW_SCHEDULER */
|
||||
|
||||
static thread_id thread_get_current_thread_id(void);
|
||||
static inline thread_id
|
||||
@@ -98,6 +101,8 @@ int user_setrlimit(int resource, const struct rlimit * rlp);
|
||||
int user_setenv(const char *name, const char *value, int overwrite);
|
||||
int user_getenv(const char *name, char **value);
|
||||
|
||||
int user_sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
||||
|
||||
#if 1
|
||||
// XXX remove later
|
||||
int thread_test(void);
|
||||
|
||||
Reference in New Issue
Block a user