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:
lillo
2002-10-23 17:31:10 +00:00
parent 54d6a27c67
commit f510e6ce60
24 changed files with 789 additions and 196 deletions
+2 -1
View File
@@ -22,7 +22,8 @@ KernelObjects
<$(SOURCE_GRIST)>port.c
<$(SOURCE_GRIST)>queue.c
<$(SOURCE_GRIST)>scheduler.c
<$(SOURCE_GRIST)>sem.c
<$(SOURCE_GRIST)>sem.c
<$(SOURCE_GRIST)>signal.c
<$(SOURCE_GRIST)>smp.c
<$(SOURCE_GRIST)>syscalls.c
<$(SOURCE_GRIST)>sysctl.c
+5 -2
View File
@@ -165,8 +165,10 @@ i386_handle_trap(struct iframe frame)
int ret = B_HANDLED_INTERRUPT;
struct thread *thread = thread_get_current_thread();
if (thread)
if (thread) {
i386_push_iframe(thread, &frame);
thread->arch_info.current_iframe = &frame;
}
// if(frame.vector != 0x20)
// dprintf("i386_handle_trap: vector 0x%x, ip 0x%x, cpu %d\n", frame.vector, frame.eip, smp_get_current_cpu());
@@ -249,7 +251,7 @@ i386_handle_trap(struct iframe frame)
}
break;
}
if (ret == B_INVOKE_SCHEDULER) {
int state = disable_interrupts();
GRAB_THREAD_LOCK();
@@ -261,6 +263,7 @@ i386_handle_trap(struct iframe frame)
if (frame.cs == USER_CODE_SEG || frame.vector == 99) {
thread_atkernel_exit();
}
// dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu());
if (thread)
+20 -6
View File
@@ -15,6 +15,8 @@
.align 8; \
name: \
pushl $vector; \
pushl $-1; \
pushl $-1; \
jmp int_bottom
#define TRAP(name, vector) \
@@ -23,6 +25,8 @@ name: \
name: \
pushl $0; \
pushl $vector; \
pushl %edx; \
pushl %eax; \
jmp int_bottom
TRAP(trap0, 0)
@@ -92,7 +96,7 @@ int_bottom:
pop %es
pop %ds
popa
addl $8,%esp
addl $16,%esp
iret
// custom stack -> copy registers to kernel stack and switch there
@@ -102,22 +106,22 @@ int_bottom:
addl _interrupt_stack_offset,%edx
lss (%edx),%esp
movl %ebx,%ds
subl $84,%esp
subl $92,%esp
movl %esp,%edi
movl $19,%ecx
movl $21,%ecx
rep movsl
movl %eax,%ds
subl $76,%esi
subl $84,%esi
movl %esi,(%edi) // save custom stack address
movl %ebx,4(%edi)
call i386_handle_trap
lss 76(%esp),%esp // reload custom stack address
lss 84(%esp),%esp // reload custom stack address
pop %gs
pop %fs
pop %es
pop %ds
popa
addl $8,%esp
addl $16,%esp
iret
_interrupt_stack_offset:
@@ -151,3 +155,13 @@ FUNCTION(i386_stack_switch):
pushl %ecx
popf
jmp *%edx
FUNCTION(i386_return_from_signal):
popl %eax // flush the only signal handler parameter
movl $103, %eax // This syscall will restore the cpu context to the
movl $0, %ecx // one existing before calling the signal handler
lea 4(%esp), %edx
int $99
ret
FUNCTION(i386_end_return_from_signal):
+115
View File
@@ -10,8 +10,11 @@
#include <memheap.h>
#include <thread.h>
#include <arch/thread.h>
#include <arch_cpu.h>
#include <int.h>
#include <string.h>
#include <Errors.h>
#include <signal.h>
// from arch_interrupts.S
@@ -194,3 +197,115 @@ arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
i386_enter_uspace(entry, args, ustack_top - 4);
}
void
arch_setup_signal_frame(struct thread *t, struct sigaction *sa, int sig, int sig_mask)
{
struct iframe *frame = t->arch_info.current_iframe;
uint32 *stack = (uint32 *)frame->user_esp;
uint32 *code;
uint32 *fpu_state;
if (frame->orig_eax >= 0) {
// we're coming from a syscall
switch (frame->eax) {
case ERESTARTNOHAND:
frame->eax = EINTR;
break;
case EINTR:
case ERESTARTSYS:
if (!(sa->sa_flags & SA_RESTART)) {
frame->eax = EINTR;
break;
}
/* fallthrough */
case ERESTARTNOINTR:
dprintf("### restarting syscall %d after signal %d\n", frame->orig_eax, sig);
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
break;
}
}
stack -= 192;
code = stack + 25;
fpu_state = stack + 64;
stack[0] = (uint32)code; // return address when sa_handler done
stack[1] = sig; // only argument to sa_handler
stack[2] = frame->gs;
stack[3] = frame->fs;
stack[4] = frame->es;
stack[5] = frame->ds;
stack[6] = frame->edi;
stack[7] = frame->esi;
stack[8] = frame->ebp;
stack[9] = frame->esp;
stack[10] = frame->ebx;
stack[11] = frame->edx;
stack[12] = frame->ecx;
stack[13] = frame->eax;
stack[18] = frame->eip;
stack[19] = frame->cs;
stack[20] = frame->flags;
stack[21] = frame->user_esp;
stack[22] = frame->user_ss;
stack[23] = sig_mask;
stack[24] = (uint32)fpu_state;
i386_fsave(fpu_state);
memcpy(code, i386_return_from_signal, (i386_end_return_from_signal - i386_return_from_signal));
frame->user_esp = (uint32)stack;
frame->eip = (uint32)sa->sa_handler;
}
int64
arch_restore_signal_frame(void)
{
struct thread *t = thread_get_current_thread();
struct iframe *frame;
uint32 fpu_state;
dprintf("### arch_restore_signal_frame: entry\n");
frame = t->arch_info.current_iframe;
t->sig_block_mask = *((sigset_t *)((void *)frame->user_esp + sizeof(struct iframe))) & BLOCKABLE_SIGS;
fpu_state = *((uint32 *)((void *)frame->user_esp + sizeof(struct iframe) + sizeof(uint32)));
memcpy((void *)frame, (void *)frame->user_esp, sizeof(struct iframe));
i386_frstor((void *)fpu_state);
dprintf("### arch_restore_signal_frame: exit\n");
frame->orig_eax = -1; /* disable syscall checks */
return (int64)frame->eax | ((int64)frame->edx << 32);
}
void
arch_check_syscall_restart(struct thread *t)
{
struct iframe *frame = t->arch_info.current_iframe;
dprintf("### arch_check_syscall_restart: entry\n");
if (frame->orig_eax >= 0) {
dprintf("### arch_check_syscall_restart: coming from a syscall\n");
if ((frame->eax == ERESTARTNOHAND) ||
(frame->eax == EINTR) ||
(frame->eax == ERESTARTSYS) ||
(frame->eax == ERESTARTNOINTR)) {
dprintf("### arch_check_syscall_restart: syscall restart needed\n");
frame->eax = frame->orig_eax;
frame->edx = frame->orig_edx;
frame->eip -= 2;
}
}
dprintf("### arch_check_syscall_restart: exit\n");
}
+24
View File
@@ -101,6 +101,30 @@ FUNCTION(arch_cpu_global_TLB_invalidate):
movl %eax,%cr3
ret
/* void i386_fsave(void *fpu_state); */
FUNCTION(i386_fsave):
movl 4(%esp), %eax
fsave (%eax)
ret
/* void i386_fxsave(void *fpu_state); */
FUNCTION(i386_fxsave):
movl 4(%esp), %eax
fxsave (%eax)
ret
/* void i386_frstor(void *fpu_state); */
FUNCTION(i386_frstor):
movl 4(%esp), %eax
frstor (%eax)
ret
/* void i386_fxrstor(void *fpu_state); */
FUNCTION(i386_fxrstor):
movl 4(%esp), %eax
fxrstor (%eax)
ret
/* void i386_fsave_swap(void *old_fpu_state, void *new_fpu_state); */
FUNCTION(i386_fsave_swap):
movl 4(%esp),%eax
+6 -4
View File
@@ -401,9 +401,9 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
TRACE_BLOCK(("acquire_sem_etc(id = %ld): block name = %s, thread = %p, name = %s\n", id, gSems[slot].name, t, t->name));
// do a quick check to see if the thread has any pending kill signals
// do a quick check to see if the thread has any pending signals
// this should catch most of the cases where the thread had a signal
if ((flags & B_CAN_INTERRUPT) && (t->pending_signals & SIG_KILL)) {
if ((flags & B_CAN_INTERRUPT) && t->sig_pending) {
gSems[slot].count += count;
status = B_INTERRUPTED;
goto err;
@@ -436,9 +436,9 @@ acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout)
RELEASE_SEM_LOCK(gSems[slot]);
GRAB_THREAD_LOCK();
// check again to see if a kill signal is pending.
// check again to see if a signal is pending.
// it may have been delivered while setting up the sem, though it's pretty unlikely
if ((flags & B_CAN_INTERRUPT) && (t->pending_signals & SIG_KILL)) {
if ((flags & B_CAN_INTERRUPT) && t->sig_pending) {
struct thread_queue wakeup_queue;
// ok, so a tiny race happened where a signal was delivered to this thread while
// it was setting up the sem. We can only be sure a signal wasn't delivered
@@ -768,6 +768,8 @@ sem_interrupt_thread(struct thread *t)
if ((t->sem_flags & B_CAN_INTERRUPT) == 0)
return ERR_SEM_NOT_INTERRUPTABLE;
t->next_state = B_THREAD_READY;
slot = t->sem_blocking % MAX_SEMS;
GRAB_SEM_LOCK(gSems[slot]);
+249
View File
@@ -0,0 +1,249 @@
/* POSIX signals handling routines
**
** Copyright 2002, Angelo Mottola, a.mottola@libero.it. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include <kernel.h>
#include <debug.h>
#include <thread.h>
#include <arch/thread.h>
#include <int.h>
#include <sem.h>
#include <string.h>
#include <signal.h>
#include <syscalls.h>
const char * const sys_siglist[NSIG] = {
"NONE", "HUP", "INT", "QUIT", "ILL", "CHLD", "ABRT", "PIPE",
"FPE", "KILL", "STOP", "SEGV", "CONT", "TSTP", "ALRM", "TERM",
"TTIN", "TTOU", "USR1", "USR2", "WINCH", "KILLTHR", "TRAP"
};
// Expects interrupts off and thread lock held.
void
handle_signals(struct thread *t, int state)
{
uint32 sig_mask = t->sig_pending & (~t->sig_block_mask);
int i, sig;
struct sigaction *handler;
if (sig_mask) {
for (i = 0; i < NSIG; i++) {
if (sig_mask & 0x1) {
sig = i + 1;
handler = &t->sig_action[i];
sig_mask >>= 1;
t->sig_pending &= ~(1L << i);
dprintf("Thread 0x%lx received signal %s\n", t->id, sys_siglist[sig]);
if (handler->sa_handler == SIG_IGN) {
// signal is to be ignored
// XXX apply zombie cleaning on SIGCHLD
continue;
}
if (handler->sa_handler == SIG_DFL) {
// default signal behaviour
switch (sig) {
case SIGCHLD:
case SIGWINCH:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
case SIGCONT:
continue;
case SIGSTOP:
t->next_state = B_THREAD_SUSPENDED;
continue;
case SIGQUIT:
case SIGILL:
case SIGTRAP:
case SIGABRT:
case SIGFPE:
case SIGSEGV:
dprintf("Shutting down thread 0x%lx due to signal #%d\n", t->id, sig);
case SIGKILL:
case SIGKILLTHR:
default:
RELEASE_THREAD_LOCK();
restore_interrupts(state);
thread_exit(sig);
}
}
// User defined signal handler
dprintf("### Setting up custom signal handler frame...\n");
arch_setup_signal_frame(t, handler, sig, t->sig_block_mask);
if (handler->sa_flags & SA_ONESHOT)
handler->sa_handler = SIG_DFL;
if (!(handler->sa_flags & SA_NOMASK))
t->sig_block_mask |= (handler->sa_mask | (1L << sig)) & BLOCKABLE_SIGS;
return;
} else
sig_mask >>= 1;
}
arch_check_syscall_restart(t);
}
}
int
send_signal_etc(pid_t tid, uint sig, uint32 flags)
{
int state;
struct thread *t, *main_t;
if ((sig < 1) || (sig > 32))
return B_BAD_VALUE;
state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_thread_struct_locked(tid);
if (!t) {
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return B_BAD_THREAD_ID;
}
// XXX check permission
// Signals to kernel threads will only wake them up
if (t->team == team_get_kernel_team()) {
if (t->state == B_THREAD_SUSPENDED) {
t->state = t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
}
}
else {
t->sig_pending |= (1L << (sig - 1));
switch (sig) {
case SIGKILL:
// Forward KILLTHR to the main thread of the team
main_t = t->team->main_thread;
main_t->sig_pending |= (1L << (SIGKILLTHR - 1));
// Wake up main thread
if (main_t->state == B_THREAD_SUSPENDED) {
main_t->state = main_t->next_state = B_THREAD_READY;
thread_enqueue_run_q(main_t);
} else if (main_t->state == B_THREAD_WAITING)
sem_interrupt_thread(main_t);
// Fallthrough
case SIGKILLTHR:
// Wake up suspended threads and interrupt waiting ones
if (t->state == B_THREAD_SUSPENDED) {
t->state = t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
} else if (t->state == B_THREAD_WAITING)
sem_interrupt_thread(t);
break;
case SIGCONT:
// Wake up thread if it was suspended
if ((t->state == B_THREAD_READY) ||
(t->state == B_THREAD_SUSPENDED)) {
t->state = t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
}
break;
default:
if (t->sig_pending & ((~t->sig_block_mask) | (1L << (SIGCHLD - 1)))) {
// Interrupt thread if it was waiting
if (t->state == B_THREAD_WAITING)
sem_interrupt_thread(t);
}
break;
}
}
if (!(flags & B_DO_NOT_RESCHEDULE))
resched();
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return B_OK;
}
int
has_signals_pending(struct thread *t)
{
if (!t)
t = thread_get_current_thread();
return (t->sig_pending & ~t->sig_block_mask);
}
int
sys_kill(pid_t tid, int sig)
{
return send_signal_etc(tid, sig, 0);
}
int
user_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
struct sigaction kact;
struct sigaction koact;
int rc;
if ((!act) || (!oact))
return EINVAL;
rc = user_memcpy(&kact, act, sizeof(struct sigaction));
if (rc < 0)
return rc;
rc = user_memcpy(&koact, oact, sizeof(struct sigaction));
if (rc < 0)
return rc;
rc = sys_sigaction(sig, &kact, &koact);
if (rc < 0)
return rc;
rc = user_memcpy(oact, &koact, sizeof(struct sigaction));
return rc;
}
int
sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
struct thread *t;
int state;
if ((sig < 1) || (sig > 32))
return EINVAL;
if ((sig == SIGKILL) || (sig == SIGKILLTHR) || (sig == SIGSTOP))
return EINVAL;
state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_current_thread();
memcpy(oact, &t->sig_action[sig - 1], sizeof(struct sigaction));
memcpy(&t->sig_action[sig - 1], act, sizeof(struct sigaction));
if (act->sa_handler == SIG_IGN)
t->sig_pending &= ~(1L << (sig - 1));
else if (act->sa_handler == SIG_DFL) {
if ((sig == SIGCONT) || (sig == SIGCHLD) || (sig == SIGWINCH))
t->sig_pending &= ~(1L << (sig - 1));
}
else
dprintf("### custom signal handler set\n");
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return 0;
}
+10
View File
@@ -6,6 +6,7 @@
#include <kernel.h>
#include <ksyscalls.h>
#include <syscalls.h>
#include <int.h>
#include <arch/int.h>
#include <debug.h>
@@ -385,6 +386,15 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
case SYSCALL_GET_NEXT_TEAM_INFO:
*call_ret = user_get_next_team_info((int32 *)arg0, (team_info *)arg1);
break;
case SYSCALL_RETURN_FROM_SIGNAL:
*call_ret = arch_restore_signal_frame();
break;
case SYSCALL_KILL:
*call_ret = sys_kill((pid_t)arg0, (int)arg1);
break;
case SYSCALL_SIGACTION:
*call_ret = user_sigaction((int)arg0, (const struct sigaction *)arg1, (struct sigaction *)arg2);
break;
default:
*call_ret = -1;
}
+40 -179
View File
@@ -1,4 +1,4 @@
/* Threading and team information */
/* Threading routines */
/*
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -75,11 +75,8 @@ static struct thread_queue run_q[(B_MAX_PRIORITY / 2) + 1] = { { NULL, NULL }, }
struct thread_queue dead_q;
static void thread_entry(void);
#ifndef NEW_SCHEDULER
static struct thread *thread_get_thread_struct_locked(thread_id id);
#endif /* not NEW_SCHEDULER */
static void thread_kthread_exit(void);
static void deliver_signal(struct thread *t, int signal);
//static void deliver_signal(struct thread *t, int signal);
// insert a thread onto the tail of a queue
@@ -266,11 +263,13 @@ create_thread_struct(const char *name)
t->q_next = NULL;
t->priority = -1;
t->args = NULL;
t->pending_signals = SIG_NONE;
t->sig_pending = 0;
t->sig_block_mask = 0;
memset(t->sig_action, 0, 32 * sizeof(struct sigaction));
t->in_kernel = true;
t->user_time = 0;
t->kernel_time = 0;
t->last_time = 0;
t->last_time = 0;
sprintf(temp, "thread_0x%lx_retcode_sem", t->id);
t->return_code_sem = create_sem(0, temp);
@@ -326,7 +325,9 @@ _create_user_thread_kentry(void)
t = thread_get_current_thread();
// a signal may have been delivered here
thread_atkernel_exit();
// thread_atkernel_exit();
t->last_time = system_time();
t->in_kernel = false;
// jump to the entry point in user space
arch_thread_enter_uspace((addr)t->entry, t->args, t->user_stack_base + STACK_SIZE);
@@ -343,7 +344,9 @@ _create_kernel_thread_kentry(void)
struct thread *t;
t = thread_get_current_thread();
t->last_time = system_time();
// call the entry function with the appropriate args
func = (void *)t->entry;
@@ -466,70 +469,22 @@ thread_create_kernel_thread_etc(const char *name, int (*func)(void *), void *arg
int
thread_suspend_thread(thread_id id)
{
int state;
struct thread *t;
int retval;
bool global_resched = false;
state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_current_thread();
if (t->id != id) {
t = thread_get_thread_struct_locked(id);
}
if (t != NULL) {
if (t->team == team_get_kernel_team()) {
// no way
retval = EPERM;
} else if (t->in_kernel == true) {
t->pending_signals |= SIG_SUSPEND;
retval = B_NO_ERROR;
} else {
t->next_state = B_THREAD_SUSPENDED;
global_resched = true;
retval = B_NO_ERROR;
}
} else
retval = ERR_INVALID_HANDLE;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
if (global_resched)
int rv;
rv = send_signal_etc(id, SIGSTOP, B_DO_NOT_RESCHEDULE);
if (rv == B_OK)
smp_send_broadcast_ici(SMP_MSG_RESCHEDULE, 0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
return retval;
return rv;
}
int
thread_resume_thread(thread_id id)
{
int state;
struct thread *t;
int retval;
state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_thread_struct_locked(id);
if (t != NULL && t->state == B_THREAD_SUSPENDED) {
t->state = B_THREAD_READY;
t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
retval = B_NO_ERROR;
} else
retval = ERR_INVALID_HANDLE;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
return retval;
return send_signal_etc(id, SIGCONT, B_DO_NOT_RESCHEDULE);
}
#ifndef NEW_SCHEDULER
status_t
thread_set_priority(thread_id id, int32 priority)
@@ -614,7 +569,7 @@ _dump_thread_info(struct thread *t)
dprintf("(%d)\n", t->cpu->info.cpu_num);
else
dprintf("\n");
dprintf("pending_signals: 0x%x\n", t->pending_signals);
dprintf("sig_pending: 0x%lx\n", t->sig_pending);
dprintf("in_kernel: %d\n", t->in_kernel);
dprintf("sem_blocking:0x%lx\n", t->sem_blocking);
dprintf("sem_count: 0x%x\n", t->sem_count);
@@ -1072,13 +1027,7 @@ thread_exit(int retcode)
}
RELEASE_TEAM_LOCK();
restore_interrupts(state);
#if 0
// Now wait for all of the threads to die
// XXX block on a semaphore
while((volatile int)p->num_threads > 0) {
snooze(10000); // 10 ms
}
#endif
// wait until all threads in team are dead.
acquire_sem_etc(p->death_sem, p->num_threads, 0, 0);
delete_sem(p->death_sem);
}
@@ -1125,55 +1074,25 @@ thread_exit(int retcode)
}
static int
_thread_kill_thread(thread_id id, bool wait_on)
{
int state;
struct thread *t;
int rc;
// dprintf("_thread_kill_thread: id %d, wait_on %d\n", id, wait_on);
state = disable_interrupts();
GRAB_THREAD_LOCK();
t = thread_get_thread_struct_locked(id);
if (t != NULL) {
if (t->team == team_get_kernel_team()) {
// can't touch this
rc = EPERM;
} else {
deliver_signal(t, SIG_KILL);
rc = B_NO_ERROR;
if (t->id == thread_get_current_thread()->id)
wait_on = false; // can't wait on ourself
}
} else
rc = ERR_INVALID_HANDLE;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
if (rc < 0)
return rc;
if (wait_on)
thread_wait_on_thread(id, NULL);
return rc;
}
int
thread_kill_thread(thread_id id)
{
return _thread_kill_thread(id, true);
int rv;
rv = send_signal_etc(id, SIGKILLTHR, B_DO_NOT_RESCHEDULE);
if (rv < 0)
return rv;
if (id != thread_get_current_thread()->id)
thread_wait_on_thread(id, NULL);
return rv;
}
int
thread_kill_thread_nowait(thread_id id)
{
return _thread_kill_thread(id, false);
return send_signal_etc(id, SIGKILLTHR, B_DO_NOT_RESCHEDULE);
}
@@ -1192,6 +1111,10 @@ thread_wait_on_thread(thread_id id, int *retcode)
struct thread *t;
int rc;
rc = send_signal_etc(id, SIGCONT, 0);
if (rc != B_OK)
return rc;
state = disable_interrupts();
GRAB_THREAD_LOCK();
@@ -1199,7 +1122,7 @@ thread_wait_on_thread(thread_id id, int *retcode)
if (t != NULL) {
sem = t->return_code_sem;
} else {
sem = ERR_INVALID_HANDLE;
sem = B_BAD_THREAD_ID;
}
RELEASE_THREAD_LOCK();
@@ -1244,11 +1167,9 @@ thread_get_thread_struct(thread_id id)
return t;
}
#ifndef NEW_SCHEDULER
static struct thread *thread_get_thread_struct_locked(thread_id id)
#else /* NEW_SCHEDULER */
struct thread *thread_get_thread_struct_locked(thread_id id)
#endif /* NEW_SCHEDULER */
struct thread *
thread_get_thread_struct_locked(thread_id id)
{
struct thread_key key;
@@ -1258,61 +1179,6 @@ struct thread *thread_get_thread_struct_locked(thread_id id)
}
// sets the pending signal flag on a thread and possibly does some work to wake it up, etc.
// expects the thread lock to be held
static void
deliver_signal(struct thread *t, int signal)
{
// dprintf("deliver_signal: thread %p (%d), signal %d\n", t, t->id, signal);
switch (signal) {
case SIG_KILL:
t->pending_signals |= SIG_KILL;
switch (t->state) {
case B_THREAD_SUSPENDED:
t->state = B_THREAD_READY;
t->next_state = B_THREAD_READY;
thread_enqueue_run_q(t);
break;
case B_THREAD_WAITING:
sem_interrupt_thread(t);
break;
default:
;
}
break;
default:
t->pending_signals |= signal;
}
}
// expects the thread lock to be held
static void
_check_for_thread_sigs(struct thread *t, int state)
{
if (t->pending_signals == SIG_NONE)
return;
if (t->pending_signals & SIG_KILL) {
t->pending_signals &= ~SIG_KILL;
RELEASE_THREAD_LOCK();
restore_interrupts(state);
thread_exit(0);
// never gets to here
}
if (t->pending_signals & SIG_SUSPEND) {
t->pending_signals &= ~SIG_SUSPEND;
t->next_state = B_THREAD_SUSPENDED;
// XXX will probably want to delay this
resched();
}
}
// called in the int handler code when a thread enters the kernel for any reason
void
@@ -1333,13 +1199,8 @@ thread_atkernel_entry(void)
t->user_time += now - t->last_time;
t->last_time = now;
GRAB_THREAD_LOCK();
t->in_kernel = true;
_check_for_thread_sigs(t, state);
RELEASE_THREAD_LOCK();
restore_interrupts(state);
}
@@ -1360,7 +1221,7 @@ thread_atkernel_exit(void)
state = disable_interrupts();
GRAB_THREAD_LOCK();
_check_for_thread_sigs(t, state);
handle_signals(t, state);
t->in_kernel = false;