Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_umtx.c
Show First 20 Lines • Show All 4,405 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
umtx_exec_hook(void *arg __unused, struct proc *p, | umtx_exec_hook(void *arg __unused, struct proc *p, | ||||
struct image_params *imgp __unused) | struct image_params *imgp __unused) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
KASSERT(p == curproc, ("need curproc")); | KASSERT(p == curproc, ("need curproc")); | ||||
PROC_LOCK(p); | |||||
KASSERT((p->p_flag & P_HADTHREADS) == 0 || | KASSERT((p->p_flag & P_HADTHREADS) == 0 || | ||||
(p->p_flag & P_STOPPED_SINGLE) != 0, | (p->p_flag & P_STOPPED_SINGLE) != 0, | ||||
("curproc must be single-threaded")); | ("curproc must be single-threaded")); | ||||
/* | |||||
* There is no need to lock the list as only this thread can be | |||||
* running. | |||||
*/ | |||||
FOREACH_THREAD_IN_PROC(p, td) { | FOREACH_THREAD_IN_PROC(p, td) { | ||||
KASSERT(td == curthread || | KASSERT(td == curthread || | ||||
((td->td_flags & TDF_BOUNDARY) != 0 && TD_IS_SUSPENDED(td)), | ((td->td_flags & TDF_BOUNDARY) != 0 && TD_IS_SUSPENDED(td)), | ||||
("running thread %p %p", p, td)); | ("running thread %p %p", p, td)); | ||||
PROC_UNLOCK(p); | |||||
umtx_thread_cleanup(td); | umtx_thread_cleanup(td); | ||||
PROC_LOCK(p); | |||||
td->td_rb_list = td->td_rbp_list = td->td_rb_inact = 0; | td->td_rb_list = td->td_rbp_list = td->td_rb_inact = 0; | ||||
} | } | ||||
PROC_UNLOCK(p); | |||||
} | } | ||||
/* | /* | ||||
* thread_exit() hook. | * thread_exit() hook. | ||||
*/ | */ | ||||
void | void | ||||
umtx_thread_exit(struct thread *td) | umtx_thread_exit(struct thread *td) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | umtx_thread_cleanup(struct thread *td) | ||||
struct umtx_pi *pi; | struct umtx_pi *pi; | ||||
uintptr_t rb_inact; | uintptr_t rb_inact; | ||||
/* | /* | ||||
* Disown pi mutexes. | * Disown pi mutexes. | ||||
*/ | */ | ||||
uq = td->td_umtxq; | uq = td->td_umtxq; | ||||
if (uq != NULL) { | if (uq != NULL) { | ||||
if (uq->uq_inherited_pri != PRI_MAX || | |||||
!TAILQ_EMPTY(&uq->uq_pi_contested)) { | |||||
mtx_lock(&umtx_lock); | mtx_lock(&umtx_lock); | ||||
uq->uq_inherited_pri = PRI_MAX; | uq->uq_inherited_pri = PRI_MAX; | ||||
while ((pi = TAILQ_FIRST(&uq->uq_pi_contested)) != NULL) { | while ((pi = TAILQ_FIRST(&uq->uq_pi_contested)) != NULL) { | ||||
pi->pi_owner = NULL; | pi->pi_owner = NULL; | ||||
TAILQ_REMOVE(&uq->uq_pi_contested, pi, pi_link); | TAILQ_REMOVE(&uq->uq_pi_contested, pi, pi_link); | ||||
} | } | ||||
mtx_unlock(&umtx_lock); | mtx_unlock(&umtx_lock); | ||||
thread_lock(td); | |||||
sched_lend_user_prio(td, PRI_MAX); | |||||
thread_unlock(td); | |||||
} | } | ||||
sched_lend_user_prio_cond(td, PRI_MAX); | |||||
} | |||||
if (td->td_rb_inact == 0 && td->td_rb_list == 0 && td->td_rbp_list == 0) | |||||
return; | |||||
/* | /* | ||||
* Handle terminated robust mutexes. Must be done after | * Handle terminated robust mutexes. Must be done after | ||||
* robust pi disown, otherwise unlock could see unowned | * robust pi disown, otherwise unlock could see unowned | ||||
* entries. | * entries. | ||||
*/ | */ | ||||
rb_inact = td->td_rb_inact; | rb_inact = td->td_rb_inact; | ||||
if (rb_inact != 0) | if (rb_inact != 0) | ||||
(void)umtx_read_uptr(td, rb_inact, &rb_inact); | (void)umtx_read_uptr(td, rb_inact, &rb_inact); | ||||
umtx_cleanup_rb_list(td, td->td_rb_list, &rb_inact, ""); | umtx_cleanup_rb_list(td, td->td_rb_list, &rb_inact, ""); | ||||
umtx_cleanup_rb_list(td, td->td_rbp_list, &rb_inact, "priv "); | umtx_cleanup_rb_list(td, td->td_rbp_list, &rb_inact, "priv "); | ||||
if (rb_inact != 0) | if (rb_inact != 0) | ||||
(void)umtx_handle_rb(td, rb_inact, NULL, true); | (void)umtx_handle_rb(td, rb_inact, NULL, true); | ||||
} | } |