Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_thr.c
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | if ((param->child_tid != NULL && | ||||
suword_lwpid(param->child_tid, td->td_tid)) || | suword_lwpid(param->child_tid, td->td_tid)) || | ||||
(param->parent_tid != NULL && | (param->parent_tid != NULL && | ||||
suword_lwpid(param->parent_tid, td->td_tid))) | suword_lwpid(param->parent_tid, td->td_tid))) | ||||
return (EFAULT); | return (EFAULT); | ||||
/* Set up our machine context. */ | /* Set up our machine context. */ | ||||
stack.ss_sp = param->stack_base; | stack.ss_sp = param->stack_base; | ||||
stack.ss_size = param->stack_size; | stack.ss_size = param->stack_size; | ||||
/* Set upcall address to user thread entry function. */ | /* Set upcall address to user thread entry function. */ | ||||
cpu_set_upcall(td, param->start_func, param->arg, &stack); | cpu_set_upcall(td, param->start_func, param->arg, &stack); | ||||
/* Setup user TLS address and TLS pointer register. */ | /* Setup user TLS address and TLS pointer register. */ | ||||
return (cpu_set_user_tls(td, param->tls_base)); | return (cpu_set_user_tls(td, param->tls_base)); | ||||
} | } | ||||
int | int | ||||
kern_thr_new(struct thread *td, struct thr_param *param) | kern_thr_new(struct thread *td, struct thr_param *param) | ||||
▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | sys_thr_self(struct thread *td, struct thr_self_args *uap) | ||||
int error; | int error; | ||||
error = suword_lwpid(uap->id, (unsigned)td->td_tid); | error = suword_lwpid(uap->id, (unsigned)td->td_tid); | ||||
if (error == -1) | if (error == -1) | ||||
return (EFAULT); | return (EFAULT); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
sys_thr_exit(struct thread *td, struct thr_exit_args *uap) | sys_thr_exit(struct thread *td, struct thr_exit_args *uap) | ||||
/* long *state */ | /* long *state */ | ||||
{ | { | ||||
umtx_thread_exit(td); | umtx_thread_exit(td); | ||||
/* Signal userland that it can free the stack. */ | /* Signal userland that it can free the stack. */ | ||||
if ((void *)uap->state != NULL) { | if ((void *)uap->state != NULL) { | ||||
suword_lwpid(uap->state, 1); | suword_lwpid(uap->state, 1); | ||||
kern_umtx_wake(td, uap->state, INT_MAX, 0); | kern_umtx_wake(td, uap->state, INT_MAX, 0); | ||||
} | } | ||||
return (kern_thr_exit(td)); | return (kern_thr_exit(td)); | ||||
} | } | ||||
void door_slam(struct thread *td); | |||||
int | int | ||||
kern_thr_exit(struct thread *td) | kern_thr_exit(struct thread *td) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
/* | /* | ||||
* If all of the threads in a process call this routine to | * If all of the threads in a process call this routine to | ||||
* exit (e.g. all threads call pthread_exit()), exactly one | * exit (e.g. all threads call pthread_exit()), exactly one | ||||
* thread should return to the caller to terminate the process | * thread should return to the caller to terminate the process | ||||
* instead of the thread. | * instead of the thread. | ||||
* | * | ||||
* Checking p_numthreads alone is not sufficient since threads | * Checking p_numthreads alone is not sufficient since threads | ||||
* might be committed to terminating while the PROC_LOCK is | * might be committed to terminating while the PROC_LOCK is | ||||
Show All 9 Lines | if (p->p_numthreads == p->p_pendingexits + 1) { | ||||
* Ignore attempts to shut down last thread in the | * Ignore attempts to shut down last thread in the | ||||
* proc. This will actually call _exit(2) in the | * proc. This will actually call _exit(2) in the | ||||
* usermode trampoline when it returns. | * usermode trampoline when it returns. | ||||
*/ | */ | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
return (0); | return (0); | ||||
} | } | ||||
if(td->td_door){ | |||||
PROC_UNLOCK(p); | |||||
door_slam(td); | |||||
PROC_LOCK(p); | |||||
} | |||||
if (p->p_sysent->sv_ontdexit != NULL) | if (p->p_sysent->sv_ontdexit != NULL) | ||||
p->p_sysent->sv_ontdexit(td); | p->p_sysent->sv_ontdexit(td); | ||||
td->td_dbgflags |= TDB_EXIT; | td->td_dbgflags |= TDB_EXIT; | ||||
if (p->p_ptevents & PTRACE_LWP) { | if (p->p_ptevents & PTRACE_LWP) { | ||||
p->p_pendingexits++; | p->p_pendingexits++; | ||||
ptracestop(td, SIGTRAP, NULL); | ptracestop(td, SIGTRAP, NULL); | ||||
p->p_pendingexits--; | p->p_pendingexits--; | ||||
} | } | ||||
tidhash_remove(td); | tidhash_remove(td); | ||||
/* | /* | ||||
* The check above should prevent all other threads from this | * The check above should prevent all other threads from this | ||||
* process from exiting while the PROC_LOCK is dropped, so | * process from exiting while the PROC_LOCK is dropped, so | ||||
* there must be at least one other thread other than the | * there must be at least one other thread other than the | ||||
* current thread. | * current thread. | ||||
*/ | */ | ||||
KASSERT(p->p_numthreads > 1, ("too few threads")); | KASSERT(p->p_numthreads > 1, ("too few threads")); | ||||
racct_sub(p, RACCT_NTHR, 1); | racct_sub(p, RACCT_NTHR, 1); | ||||
tdsigcleanup(td); | tdsigcleanup(td); | ||||
#ifdef AUDIT | #ifdef AUDIT | ||||
AUDIT_SYSCALL_EXIT(0, td); | AUDIT_SYSCALL_EXIT(0, td); | ||||
#endif | #endif | ||||
PROC_SLOCK(p); | PROC_SLOCK(p); | ||||
thread_stopped(p); | thread_stopped(p); | ||||
thread_exit(); | thread_exit(); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 240 Lines • Show Last 20 Lines |