/* * Share-lock a mutex, block until acquired. Recursion is allowed. * * Returns 0 on success, or the tsleep() return code on failure. * An error can only be returned if PCATCH is specified in the flags. * * NOTE: Shared locks get a mass-wakeup so if the tsleep fails we * do not have to chain the wakeup(). */ static __inline int __mtx_lock_sh(mtx_t mtx, const char *ident, int flags, int to) { u_int lock; u_int nlock; int error; for (;;) { lock = mtx->mtx_lock; if ((lock & MTX_EXCLUSIVE) == 0) { KKASSERT((lock & MTX_MASK) != MTX_MASK); nlock = lock + 1; if (atomic_cmpset_int(&mtx->mtx_lock, lock, nlock)) { error = 0; break; } } else { nlock = lock | MTX_SHWANTED; tsleep_interlock(mtx, 0); if (atomic_cmpset_int(&mtx->mtx_lock, lock, nlock)) { error = tsleep(mtx, flags, ident, to); if (error) break; ++mtx_contention_count; /* retry */ } else { tsleep_remove(curthread); } } ++mtx_collision_count; } return (error); }
void cpu_lwp_exit(void) { struct thread *td = curthread; struct pcb *pcb; npxexit(); pcb = td->td_pcb; /* Some i386 functionality was dropped */ KKASSERT(pcb->pcb_ext == NULL); /* * disable all hardware breakpoints */ if (pcb->pcb_flags & PCB_DBREGS) { reset_dbregs(); pcb->pcb_flags &= ~PCB_DBREGS; } td->td_gd->gd_cnt.v_swtch++; crit_enter_quick(td); if (td->td_flags & TDF_TSLEEPQ) tsleep_remove(td); lwkt_deschedule_self(td); lwkt_remove_tdallq(td); cpu_thread_exit(); }
void cpu_lwp_exit(void) { struct thread *td = curthread; struct pcb *pcb; struct pcb_ext *ext; /* * If we were using a private TSS do a forced-switch to ourselves * to switch back to the common TSS before freeing it. */ pcb = td->td_pcb; if ((ext = pcb->pcb_ext) != NULL) { crit_enter(); pcb->pcb_ext = NULL; lwkt_switch_return(td->td_switch(td)); crit_exit(); kmem_free(&kernel_map, (vm_offset_t)ext, ctob(IOPAGES + 1)); } user_ldt_free(pcb); if (pcb->pcb_flags & PCB_DBREGS) { /* * disable all hardware breakpoints */ reset_dbregs(); pcb->pcb_flags &= ~PCB_DBREGS; } td->td_gd->gd_cnt.v_swtch++; crit_enter_quick(td); if (td->td_flags & TDF_TSLEEPQ) tsleep_remove(td); lwkt_deschedule_self(td); lwkt_remove_tdallq(td); cpu_thread_exit(); }