kill now sends the signal to the main thread of a process only. To target a specific thread use the new send_signal syscall. Also added set_alarm.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1662 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -62,6 +62,7 @@ status_t sys_get_next_team_info(int32 *cookie, team_info *info);
|
|||||||
|
|
||||||
int sys_kill(pid_t pid, int sig);
|
int sys_kill(pid_t pid, int sig);
|
||||||
int sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
int sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
||||||
|
bigtime_t sys_set_alarm(bigtime_t time, uint32 mode);
|
||||||
|
|
||||||
region_id sys_vm_create_anonymous_region(const char *name, void **address, int addr_type,
|
region_id sys_vm_create_anonymous_region(const char *name, void **address, int addr_type,
|
||||||
addr size, int wiring, int lock);
|
addr size, int wiring, int lock);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ extern "C" {
|
|||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <timer.h>
|
||||||
#include <arch/thread_struct.h>
|
#include <arch/thread_struct.h>
|
||||||
|
|
||||||
extern spinlock_t thread_spinlock;
|
extern spinlock_t thread_spinlock;
|
||||||
@@ -96,6 +97,7 @@ struct thread {
|
|||||||
struct thread *all_next;
|
struct thread *all_next;
|
||||||
struct thread *team_next;
|
struct thread *team_next;
|
||||||
struct thread *q_next;
|
struct thread *q_next;
|
||||||
|
timer alarm;
|
||||||
thread_id id;
|
thread_id id;
|
||||||
char name[SYS_MAX_OS_NAME_LEN];
|
char name[SYS_MAX_OS_NAME_LEN];
|
||||||
int priority;
|
int priority;
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ enum {
|
|||||||
SYSCALL_CREATE_INDEX,
|
SYSCALL_CREATE_INDEX,
|
||||||
SYSCALL_READ_INDEX_STAT,
|
SYSCALL_READ_INDEX_STAT,
|
||||||
SYSCALL_REMOVE_INDEX,
|
SYSCALL_REMOVE_INDEX,
|
||||||
|
SYSCALL_SEND_SIGNAL, /* 110 */
|
||||||
|
SYSCALL_SET_ALARM,
|
||||||
};
|
};
|
||||||
|
|
||||||
int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret);
|
int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret);
|
||||||
|
|||||||
@@ -11,8 +11,10 @@
|
|||||||
|
|
||||||
|
|
||||||
void sig_handler(int);
|
void sig_handler(int);
|
||||||
void install_handler(int);
|
void alarm_handler(int);
|
||||||
|
void install_handler(int, __signal_func_ptr);
|
||||||
int32 thread(void *);
|
int32 thread(void *);
|
||||||
|
void usage(void);
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -29,14 +31,21 @@ sig_handler(int sig)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
install_handler(int sig)
|
alarm_handler(int sig)
|
||||||
|
{
|
||||||
|
printf("Alarm!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
install_handler(int sig, __signal_func_ptr handler)
|
||||||
{
|
{
|
||||||
struct sigaction newa;
|
struct sigaction newa;
|
||||||
struct sigaction olda;
|
struct sigaction olda;
|
||||||
|
|
||||||
memset(&newa, 0, sizeof(newa));
|
memset(&newa, 0, sizeof(newa));
|
||||||
|
|
||||||
newa.sa_handler = sig_handler;
|
newa.sa_handler = handler;
|
||||||
newa.sa_flags = SA_NOMASK | SA_RESTART;
|
newa.sa_flags = SA_NOMASK | SA_RESTART;
|
||||||
|
|
||||||
if (sys_sigaction(sig, &newa, &olda) < 0) {
|
if (sys_sigaction(sig, &newa, &olda) < 0) {
|
||||||
@@ -57,17 +66,42 @@ thread(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
printf("usage: sig_test <mode>\n"
|
||||||
|
"where `mode' is one of:\n"
|
||||||
|
"\t1\tInstalls one handler for all signals\n"
|
||||||
|
"\t2\tSame as 1 but also spawns 5 threads with no active handlers\n"
|
||||||
|
"\t3\tSets an alarm via set_alarm\n"
|
||||||
|
"\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Installing signal handlers...\n");
|
if (argc != 2)
|
||||||
for (i=1; i<=NSIG; i++)
|
usage();
|
||||||
install_handler(i);
|
|
||||||
printf("Spawning some threads...\n");
|
switch (argv[1][0]) {
|
||||||
for (i=0; i<5; i++)
|
case '1':
|
||||||
resume_thread(spawn_thread(thread, "sig_test aux thread", B_NORMAL_PRIORITY, NULL));
|
printf("Spawning some threads...\n");
|
||||||
|
for (i=0; i<5; i++)
|
||||||
|
resume_thread(spawn_thread(thread, "sig_test aux thread", B_NORMAL_PRIORITY, NULL));
|
||||||
|
case '2':
|
||||||
|
printf("Installing signal handlers...\n");
|
||||||
|
for (i=1; i<=NSIG; i++)
|
||||||
|
install_handler(i, sig_handler);
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
install_handler(SIGALRM, alarm_handler);
|
||||||
|
sys_set_alarm(5000000, B_PERIODIC_ALARM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
printf("Done. Entering sleep mode...\n");
|
printf("Done. Entering sleep mode...\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
if (sys_snooze(1000000000L) == B_INTERRUPTED)
|
if (sys_snooze(1000000000L) == B_INTERRUPTED)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
** Distributed under the terms of the OpenBeOS License.
|
** Distributed under the terms of the OpenBeOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
@@ -183,9 +184,26 @@ has_signals_pending(struct thread *t)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_kill(pid_t tid, int sig)
|
sys_kill(pid_t pid, int sig)
|
||||||
{
|
{
|
||||||
return send_signal_etc(tid, sig, 0);
|
struct team *t;
|
||||||
|
int state;
|
||||||
|
thread_id tid = -1;
|
||||||
|
|
||||||
|
// XXX check for permissions
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
t = team_get_team_struct_locked(pid);
|
||||||
|
if ((t) && (t->main_thread))
|
||||||
|
tid = t->main_thread->id;
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
if (sig)
|
||||||
|
return send_signal_etc(tid, sig, 0);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -247,3 +265,36 @@ sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Triggers a SIGALRM to the thread that issued the timer and reschedules
|
||||||
|
static int32
|
||||||
|
alarm_event(timer *t)
|
||||||
|
{
|
||||||
|
int tid = *((int *)((void *)t + sizeof(timer)));
|
||||||
|
|
||||||
|
send_signal_etc(tid, SIGALRM, B_DO_NOT_RESCHEDULE);
|
||||||
|
|
||||||
|
return B_INVOKE_SCHEDULER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
sys_set_alarm(bigtime_t time, uint32 mode)
|
||||||
|
{
|
||||||
|
struct thread *t = thread_get_current_thread();
|
||||||
|
int state;
|
||||||
|
bigtime_t rv = 0;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
|
||||||
|
if (t->alarm.period)
|
||||||
|
rv = (bigtime_t)t->alarm.entry.key - system_time();
|
||||||
|
cancel_timer(&t->alarm);
|
||||||
|
if (time != B_INFINITE_TIMEOUT)
|
||||||
|
add_timer(&t->alarm, &alarm_event, time, mode);
|
||||||
|
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -395,6 +395,12 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
|
|||||||
case SYSCALL_SIGACTION:
|
case SYSCALL_SIGACTION:
|
||||||
*call_ret = user_sigaction((int)arg0, (const struct sigaction *)arg1, (struct sigaction *)arg2);
|
*call_ret = user_sigaction((int)arg0, (const struct sigaction *)arg1, (struct sigaction *)arg2);
|
||||||
break;
|
break;
|
||||||
|
case SYSCALL_SEND_SIGNAL:
|
||||||
|
*call_ret = send_signal_etc((pid_t)arg0, (uint)arg1);
|
||||||
|
break;
|
||||||
|
case SYSCALL_SET_ALARM:
|
||||||
|
*call_ret = sys_set_alarm((bigtime_t)INT32TOINT64(arg0, arg1), (uint32)arg2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*call_ret = -1;
|
*call_ret = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -971,6 +971,9 @@ thread_exit(int retcode)
|
|||||||
// boost our priority to get this over with
|
// boost our priority to get this over with
|
||||||
thread_set_priority(t->id, B_FIRST_REAL_TIME_PRIORITY);
|
thread_set_priority(t->id, B_FIRST_REAL_TIME_PRIORITY);
|
||||||
|
|
||||||
|
// Cancel previously installed alarm timer, if any
|
||||||
|
cancel_timer(&t->alarm);
|
||||||
|
|
||||||
// delete the user stack region first
|
// delete the user stack region first
|
||||||
if (p->_aspace_id >= 0 && t->user_stack_region_id >= 0) {
|
if (p->_aspace_id >= 0 && t->user_stack_region_id >= 0) {
|
||||||
region_id rid = t->user_stack_region_id;
|
region_id rid = t->user_stack_region_id;
|
||||||
|
|||||||
@@ -154,4 +154,6 @@ SYSCALL2(sys_getenv, 80)
|
|||||||
SYSCALL0(sys_return_from_signal, 103)
|
SYSCALL0(sys_return_from_signal, 103)
|
||||||
SYSCALL2(sys_kill, 104)
|
SYSCALL2(sys_kill, 104)
|
||||||
SYSCALL3(sys_sigaction, 105)
|
SYSCALL3(sys_sigaction, 105)
|
||||||
|
SYSCALL2(sys_send_signal, 110)
|
||||||
|
SYSCALL3(sys_set_alarm, 111)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user