beos compatibility fixes: exit_thread now issues a signal; wait_for_thread returns B_INTERRUPTED if target thread gets killed
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1674 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a86569deee
commit
8fe70e8212
@ -156,7 +156,7 @@ enum {
|
|||||||
|
|
||||||
extern sem_id create_sem(int32 count, const char *name);
|
extern sem_id create_sem(int32 count, const char *name);
|
||||||
extern status_t delete_sem(sem_id id);
|
extern status_t delete_sem(sem_id id);
|
||||||
extern status_t delete_sem_etc(sem_id id, status_t returnCode); /* ToDo: not public BeOS */
|
extern status_t delete_sem_etc(sem_id id, status_t returnCode, bool interrupted); /* ToDo: not public BeOS */
|
||||||
extern status_t acquire_sem(sem_id id);
|
extern status_t acquire_sem(sem_id id);
|
||||||
extern status_t acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout);
|
extern status_t acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout);
|
||||||
extern status_t release_sem(sem_id id);
|
extern status_t release_sem(sem_id id);
|
||||||
|
@ -48,6 +48,7 @@ thread_id sys_get_current_thread_id(void);
|
|||||||
int sys_suspend_thread(thread_id tid);
|
int sys_suspend_thread(thread_id tid);
|
||||||
int sys_resume_thread(thread_id tid);
|
int sys_resume_thread(thread_id tid);
|
||||||
int sys_kill_thread(thread_id tid);
|
int sys_kill_thread(thread_id tid);
|
||||||
|
void sys_exit_thread(status_t return_value);
|
||||||
|
|
||||||
status_t sys_wait_on_thread(thread_id tid, status_t *retcode);
|
status_t sys_wait_on_thread(thread_id tid, status_t *retcode);
|
||||||
int sys_kill_team(team_id tid);
|
int sys_kill_team(team_id tid);
|
||||||
|
@ -52,9 +52,10 @@ enum {
|
|||||||
TEAM_STATE_DEATH // being killed
|
TEAM_STATE_DEATH // being killed
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIG_NONE 0
|
|
||||||
#define SIG_SUSPEND 1
|
#define THREAD_RETURN_EXIT 0x1
|
||||||
#define SIG_KILL 2
|
#define THREAD_RETURN_INTERRUPTED 0x2
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The team structure; equivalent to a common process.
|
* The team structure; equivalent to a common process.
|
||||||
@ -128,7 +129,9 @@ struct thread {
|
|||||||
addr entry;
|
addr entry;
|
||||||
void *args;
|
void *args;
|
||||||
struct team *team;
|
struct team *team;
|
||||||
|
status_t return_code;
|
||||||
sem_id return_code_sem;
|
sem_id return_code_sem;
|
||||||
|
int return_flags;
|
||||||
region_id kernel_stack_region_id;
|
region_id kernel_stack_region_id;
|
||||||
addr kernel_stack_base;
|
addr kernel_stack_base;
|
||||||
region_id user_stack_region_id;
|
region_id user_stack_region_id;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
/* user calls */
|
/* user calls */
|
||||||
sem_id user_create_sem(int32 count, const char *name);
|
sem_id user_create_sem(int32 count, const char *name);
|
||||||
status_t user_delete_sem(sem_id id);
|
status_t user_delete_sem(sem_id id);
|
||||||
status_t user_delete_sem_etc(sem_id id, status_t return_code);
|
status_t user_delete_sem_etc(sem_id id, status_t return_code, bool interrupted);
|
||||||
status_t user_acquire_sem(sem_id id);
|
status_t user_acquire_sem(sem_id id);
|
||||||
status_t user_acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout);
|
status_t user_acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout);
|
||||||
status_t user_release_sem(sem_id id);
|
status_t user_release_sem(sem_id id);
|
||||||
|
@ -43,7 +43,7 @@ int thread_resume_thread(thread_id id);
|
|||||||
status_t thread_set_priority(thread_id id, int32 priority);
|
status_t thread_set_priority(thread_id id, int32 priority);
|
||||||
int thread_init(kernel_args *ka);
|
int thread_init(kernel_args *ka);
|
||||||
int thread_init_percpu(int cpu_num);
|
int thread_init_percpu(int cpu_num);
|
||||||
void thread_exit(int retcode);
|
void thread_exit(void);
|
||||||
int thread_kill_thread(thread_id id);
|
int thread_kill_thread(thread_id id);
|
||||||
int thread_kill_thread_nowait(thread_id id);
|
int thread_kill_thread_nowait(thread_id id);
|
||||||
|
|
||||||
|
@ -245,12 +245,12 @@ create_sem(int32 count, const char *name)
|
|||||||
status_t
|
status_t
|
||||||
delete_sem(sem_id id)
|
delete_sem(sem_id id)
|
||||||
{
|
{
|
||||||
return delete_sem_etc(id, 0);
|
return delete_sem_etc(id, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
delete_sem_etc(sem_id id, status_t return_code)
|
delete_sem_etc(sem_id id, status_t return_code, bool interrupted)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
int state;
|
int state;
|
||||||
@ -282,7 +282,7 @@ delete_sem_etc(sem_id id, status_t return_code)
|
|||||||
// free any threads waiting for this semaphore
|
// free any threads waiting for this semaphore
|
||||||
while ((t = thread_dequeue(&gSems[slot].q)) != NULL) {
|
while ((t = thread_dequeue(&gSems[slot].q)) != NULL) {
|
||||||
t->state = B_THREAD_READY;
|
t->state = B_THREAD_READY;
|
||||||
t->sem_errcode = B_BAD_SEM_ID;
|
t->sem_errcode = interrupted ? B_INTERRUPTED : B_BAD_SEM_ID;
|
||||||
t->sem_deleted_retcode = return_code;
|
t->sem_deleted_retcode = return_code;
|
||||||
t->sem_count = 0;
|
t->sem_count = 0;
|
||||||
thread_enqueue(t, &release_queue);
|
thread_enqueue(t, &release_queue);
|
||||||
@ -851,7 +851,7 @@ sem_delete_owned_sems(team_id owner)
|
|||||||
RELEASE_SEM_LIST_LOCK();
|
RELEASE_SEM_LIST_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
delete_sem_etc(id, 0);
|
delete_sem(id);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
@ -896,9 +896,9 @@ user_delete_sem(sem_id id)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
user_delete_sem_etc(sem_id id, status_t return_code)
|
user_delete_sem_etc(sem_id id, status_t return_code, bool interrupted)
|
||||||
{
|
{
|
||||||
return delete_sem_etc(id, return_code);
|
return delete_sem_etc(id, return_code, interrupted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,9 +72,11 @@ handle_signals(struct thread *t, int state)
|
|||||||
case SIGKILL:
|
case SIGKILL:
|
||||||
case SIGKILLTHR:
|
case SIGKILLTHR:
|
||||||
default:
|
default:
|
||||||
|
if (!(t->return_flags & THREAD_RETURN_EXIT))
|
||||||
|
t->return_flags |= THREAD_RETURN_INTERRUPTED;
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
thread_exit(sig);
|
thread_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,8 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
|
|||||||
*call_ret = thread_get_current_thread_id();
|
*call_ret = thread_get_current_thread_id();
|
||||||
break;
|
break;
|
||||||
case SYSCALL_EXIT_THREAD:
|
case SYSCALL_EXIT_THREAD:
|
||||||
thread_exit((int)arg0);
|
sys_exit_thread((status_t)arg0);
|
||||||
|
// thread_exit((int)arg0);
|
||||||
*call_ret = 0;
|
*call_ret = 0;
|
||||||
break;
|
break;
|
||||||
case SYSCALL_CREATE_TEAM:
|
case SYSCALL_CREATE_TEAM:
|
||||||
|
@ -376,7 +376,7 @@ create_team_struct(const char *name, bool kernel)
|
|||||||
p->thread_list = NULL;
|
p->thread_list = NULL;
|
||||||
p->main_thread = NULL;
|
p->main_thread = NULL;
|
||||||
p->state = TEAM_STATE_BIRTH;
|
p->state = TEAM_STATE_BIRTH;
|
||||||
p->pending_signals = SIG_NONE;
|
p->pending_signals = 0;
|
||||||
p->death_sem = -1;
|
p->death_sem = -1;
|
||||||
p->user_env_base = 0;
|
p->user_env_base = 0;
|
||||||
|
|
||||||
|
@ -270,6 +270,8 @@ create_thread_struct(const char *name)
|
|||||||
t->user_time = 0;
|
t->user_time = 0;
|
||||||
t->kernel_time = 0;
|
t->kernel_time = 0;
|
||||||
t->last_time = 0;
|
t->last_time = 0;
|
||||||
|
t->return_code = 0;
|
||||||
|
t->return_flags = 0;
|
||||||
|
|
||||||
sprintf(temp, "thread_0x%lx_retcode_sem", t->id);
|
sprintf(temp, "thread_0x%lx_retcode_sem", t->id);
|
||||||
t->return_code_sem = create_sem(0, temp);
|
t->return_code_sem = create_sem(0, temp);
|
||||||
@ -292,11 +294,11 @@ create_thread_struct(const char *name)
|
|||||||
return t;
|
return t;
|
||||||
|
|
||||||
err4:
|
err4:
|
||||||
delete_sem_etc(t->msg.read_sem, -1);
|
delete_sem_etc(t->msg.read_sem, -1, false);
|
||||||
err3:
|
err3:
|
||||||
delete_sem_etc(t->msg.write_sem, -1);
|
delete_sem_etc(t->msg.write_sem, -1, false);
|
||||||
err2:
|
err2:
|
||||||
delete_sem_etc(t->return_code_sem, -1);
|
delete_sem_etc(t->return_code_sem, -1, false);
|
||||||
err1:
|
err1:
|
||||||
kfree(t);
|
kfree(t);
|
||||||
err:
|
err:
|
||||||
@ -308,11 +310,11 @@ static void
|
|||||||
delete_thread_struct(struct thread *t)
|
delete_thread_struct(struct thread *t)
|
||||||
{
|
{
|
||||||
if (t->return_code_sem >= 0)
|
if (t->return_code_sem >= 0)
|
||||||
delete_sem_etc(t->return_code_sem, -1);
|
delete_sem_etc(t->return_code_sem, -1, false);
|
||||||
if (t->msg.write_sem >= 0)
|
if (t->msg.write_sem >= 0)
|
||||||
delete_sem_etc(t->msg.write_sem, -1);
|
delete_sem_etc(t->msg.write_sem, -1, false);
|
||||||
if (t->msg.read_sem >= 0)
|
if (t->msg.read_sem >= 0)
|
||||||
delete_sem_etc(t->msg.read_sem, -1);
|
delete_sem_etc(t->msg.read_sem, -1, false);
|
||||||
kfree(t);
|
kfree(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -957,7 +959,7 @@ thread_exit2(void *_args)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
thread_exit(int retcode)
|
thread_exit(void)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
struct thread *t = thread_get_current_thread();
|
struct thread *t = thread_get_current_thread();
|
||||||
@ -966,7 +968,9 @@ thread_exit(int retcode)
|
|||||||
unsigned int death_stack;
|
unsigned int death_stack;
|
||||||
sem_id cached_death_sem;
|
sem_id cached_death_sem;
|
||||||
|
|
||||||
dprintf("thread 0x%lx exiting w/return code 0x%x\n", t->id, retcode);
|
dprintf("thread 0x%lx exiting %s w/return code 0x%x\n", t->id,
|
||||||
|
t->return_flags & THREAD_RETURN_INTERRUPTED ? "due to signal" : "normally",
|
||||||
|
(int)t->return_code);
|
||||||
|
|
||||||
// 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);
|
||||||
@ -1048,7 +1052,7 @@ thread_exit(int retcode)
|
|||||||
sem_id s = t->return_code_sem;
|
sem_id s = t->return_code_sem;
|
||||||
|
|
||||||
t->return_code_sem = -1;
|
t->return_code_sem = -1;
|
||||||
delete_sem_etc(s, retcode);
|
delete_sem_etc(s, t->return_code, t->return_flags & THREAD_RETURN_INTERRUPTED ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
death_stack = get_death_stack();
|
death_stack = get_death_stack();
|
||||||
@ -1077,6 +1081,23 @@ thread_exit(int retcode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sys_exit_thread(status_t return_value)
|
||||||
|
{
|
||||||
|
struct thread *t = thread_get_current_thread();
|
||||||
|
int state;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
t->return_code = return_value;
|
||||||
|
t->return_flags = THREAD_RETURN_EXIT;
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
send_signal_etc(t->id, SIGKILLTHR, B_DO_NOT_RESCHEDULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
thread_kill_thread(thread_id id)
|
thread_kill_thread(thread_id id)
|
||||||
{
|
{
|
||||||
@ -1102,7 +1123,10 @@ thread_kill_thread_nowait(thread_id id)
|
|||||||
static void
|
static void
|
||||||
thread_kthread_exit(void)
|
thread_kthread_exit(void)
|
||||||
{
|
{
|
||||||
thread_exit(0);
|
struct thread *t = thread_get_current_thread();
|
||||||
|
|
||||||
|
t->return_flags = THREAD_RETURN_EXIT;
|
||||||
|
thread_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user