10384fff8SJason Evans /*- 20384fff8SJason Evans * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved. 30384fff8SJason Evans * 40384fff8SJason Evans * Redistribution and use in source and binary forms, with or without 50384fff8SJason Evans * modification, are permitted provided that the following conditions 60384fff8SJason Evans * are met: 70384fff8SJason Evans * 1. Redistributions of source code must retain the above copyright 80384fff8SJason Evans * notice, this list of conditions and the following disclaimer. 90384fff8SJason Evans * 2. Redistributions in binary form must reproduce the above copyright 100384fff8SJason Evans * notice, this list of conditions and the following disclaimer in the 110384fff8SJason Evans * documentation and/or other materials provided with the distribution. 120384fff8SJason Evans * 3. Berkeley Software Design Inc's name may not be used to endorse or 130384fff8SJason Evans * promote products derived from this software without specific prior 140384fff8SJason Evans * written permission. 150384fff8SJason Evans * 160384fff8SJason Evans * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 170384fff8SJason Evans * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180384fff8SJason Evans * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190384fff8SJason Evans * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 200384fff8SJason Evans * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210384fff8SJason Evans * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220384fff8SJason Evans * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230384fff8SJason Evans * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240384fff8SJason Evans * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250384fff8SJason Evans * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260384fff8SJason Evans * SUCH DAMAGE. 270384fff8SJason Evans * 280384fff8SJason Evans * from BSDI $Id: mutex_witness.c,v 1.1.2.20 2000/04/27 03:10:27 cp Exp $ 2936412d79SJohn Baldwin * and BSDI $Id: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $ 300384fff8SJason Evans * $FreeBSD$ 310384fff8SJason Evans */ 320384fff8SJason Evans 330384fff8SJason Evans /* 34ba48b69aSJohn Baldwin * Machine independent bits of mutex implementation. 350384fff8SJason Evans */ 360384fff8SJason Evans 379c36c934SJohn Baldwin #include "opt_ddb.h" 38a5a96a19SJohn Baldwin 390384fff8SJason Evans #include <sys/param.h> 4036412d79SJohn Baldwin #include <sys/bus.h> 4136412d79SJohn Baldwin #include <sys/kernel.h> 4219284646SJohn Baldwin #include <sys/lock.h> 43fb919e4dSMark Murray #include <sys/malloc.h> 4419284646SJohn Baldwin #include <sys/mutex.h> 450384fff8SJason Evans #include <sys/proc.h> 46c4f7a187SJohn Baldwin #include <sys/resourcevar.h> 47a5a96a19SJohn Baldwin #include <sys/sysctl.h> 480384fff8SJason Evans #include <sys/systm.h> 4936412d79SJohn Baldwin #include <sys/vmmeter.h> 500384fff8SJason Evans #include <sys/ktr.h> 510384fff8SJason Evans 5236412d79SJohn Baldwin #include <machine/atomic.h> 5336412d79SJohn Baldwin #include <machine/bus.h> 5436412d79SJohn Baldwin #include <machine/clock.h> 550384fff8SJason Evans #include <machine/cpu.h> 5636412d79SJohn Baldwin 579c36c934SJohn Baldwin #include <ddb/ddb.h> 589c36c934SJohn Baldwin 5936412d79SJohn Baldwin #include <vm/vm.h> 6036412d79SJohn Baldwin #include <vm/vm_extern.h> 6136412d79SJohn Baldwin 620cde2e34SJason Evans /* 639ed346baSBosko Milekic * Internal utility macros. 640cde2e34SJason Evans */ 659ed346baSBosko Milekic #define mtx_unowned(m) ((m)->mtx_lock == MTX_UNOWNED) 660cde2e34SJason Evans 679ed346baSBosko Milekic #define mtx_owner(m) (mtx_unowned((m)) ? NULL \ 68b40ce416SJulian Elischer : (struct thread *)((m)->mtx_lock & MTX_FLAGMASK)) 699ed346baSBosko Milekic 700cde2e34SJason Evans /* 7119284646SJohn Baldwin * Lock classes for sleep and spin mutexes. 720cde2e34SJason Evans */ 7319284646SJohn Baldwin struct lock_class lock_class_mtx_sleep = { 7419284646SJohn Baldwin "sleep mutex", 7519284646SJohn Baldwin LC_SLEEPLOCK | LC_RECURSABLE 7619284646SJohn Baldwin }; 7719284646SJohn Baldwin struct lock_class lock_class_mtx_spin = { 7819284646SJohn Baldwin "spin mutex", 7919284646SJohn Baldwin LC_SPINLOCK | LC_RECURSABLE 808484de75SJohn Baldwin }; 818484de75SJohn Baldwin 829ed346baSBosko Milekic /* 839ed346baSBosko Milekic * Prototypes for non-exported routines. 849ed346baSBosko Milekic */ 85b40ce416SJulian Elischer static void propagate_priority(struct thread *); 8636412d79SJohn Baldwin 8736412d79SJohn Baldwin static void 88b40ce416SJulian Elischer propagate_priority(struct thread *td) 8936412d79SJohn Baldwin { 902c100766SJulian Elischer int pri = td->td_priority; 91b40ce416SJulian Elischer struct mtx *m = td->td_blocked; 9236412d79SJohn Baldwin 931bd0eefbSJohn Baldwin mtx_assert(&sched_lock, MA_OWNED); 9436412d79SJohn Baldwin for (;;) { 95b40ce416SJulian Elischer struct thread *td1; 9636412d79SJohn Baldwin 97b40ce416SJulian Elischer td = mtx_owner(m); 9836412d79SJohn Baldwin 99b40ce416SJulian Elischer if (td == NULL) { 10036412d79SJohn Baldwin /* 10136412d79SJohn Baldwin * This really isn't quite right. Really 102b40ce416SJulian Elischer * ought to bump priority of thread that 10336412d79SJohn Baldwin * next acquires the mutex. 10436412d79SJohn Baldwin */ 10536412d79SJohn Baldwin MPASS(m->mtx_lock == MTX_CONTESTED); 10636412d79SJohn Baldwin return; 10736412d79SJohn Baldwin } 1089ed346baSBosko Milekic 109b40ce416SJulian Elischer MPASS(td->td_proc->p_magic == P_MAGIC); 110b40ce416SJulian Elischer KASSERT(td->td_proc->p_stat != SSLEEP, ("sleeping thread owns a mutex")); 1112c100766SJulian Elischer if (td->td_priority <= pri) /* lower is higher priority */ 11236412d79SJohn Baldwin return; 1131bd0eefbSJohn Baldwin 1141bd0eefbSJohn Baldwin /* 115b40ce416SJulian Elischer * Bump this thread's priority. 1161bd0eefbSJohn Baldwin */ 1172c100766SJulian Elischer td->td_priority = pri; 1181bd0eefbSJohn Baldwin 11936412d79SJohn Baldwin /* 12036412d79SJohn Baldwin * If lock holder is actually running, just bump priority. 12136412d79SJohn Baldwin */ 122b40ce416SJulian Elischer /* XXXKSE this test is not sufficient */ 123b40ce416SJulian Elischer if (td->td_kse && (td->td_kse->ke_oncpu != NOCPU)) { 124b40ce416SJulian Elischer MPASS(td->td_proc->p_stat == SRUN 125b40ce416SJulian Elischer || td->td_proc->p_stat == SZOMB 126b40ce416SJulian Elischer || td->td_proc->p_stat == SSTOP); 12736412d79SJohn Baldwin return; 12836412d79SJohn Baldwin } 129d5a08a60SJake Burkholder 1301b43703bSJohn Baldwin #ifndef SMP 1311b43703bSJohn Baldwin /* 132b40ce416SJulian Elischer * For UP, we check to see if td is curthread (this shouldn't 1331b43703bSJohn Baldwin * ever happen however as it would mean we are in a deadlock.) 1341b43703bSJohn Baldwin */ 135b40ce416SJulian Elischer KASSERT(td != curthread, ("Deadlock detected")); 1361b43703bSJohn Baldwin #endif 1371b43703bSJohn Baldwin 13836412d79SJohn Baldwin /* 139b40ce416SJulian Elischer * If on run queue move to new run queue, and quit. 140b40ce416SJulian Elischer * XXXKSE this gets a lot more complicated under threads 141b40ce416SJulian Elischer * but try anyhow. 14236412d79SJohn Baldwin */ 143b40ce416SJulian Elischer if (td->td_proc->p_stat == SRUN) { 144b40ce416SJulian Elischer MPASS(td->td_blocked == NULL); 145b40ce416SJulian Elischer remrunqueue(td); 146b40ce416SJulian Elischer setrunqueue(td); 14736412d79SJohn Baldwin return; 14836412d79SJohn Baldwin } 14936412d79SJohn Baldwin 15036412d79SJohn Baldwin /* 1511bd0eefbSJohn Baldwin * If we aren't blocked on a mutex, we should be. 15236412d79SJohn Baldwin */ 153b40ce416SJulian Elischer KASSERT(td->td_proc->p_stat == SMTX, ( 1541bd0eefbSJohn Baldwin "process %d(%s):%d holds %s but isn't blocked on a mutex\n", 155b40ce416SJulian Elischer td->td_proc->p_pid, td->td_proc->p_comm, td->td_proc->p_stat, 15619284646SJohn Baldwin m->mtx_object.lo_name)); 15736412d79SJohn Baldwin 15836412d79SJohn Baldwin /* 159b40ce416SJulian Elischer * Pick up the mutex that td is blocked on. 16036412d79SJohn Baldwin */ 161b40ce416SJulian Elischer m = td->td_blocked; 16236412d79SJohn Baldwin MPASS(m != NULL); 16336412d79SJohn Baldwin 16436412d79SJohn Baldwin /* 165b40ce416SJulian Elischer * Check if the thread needs to be moved up on 16636412d79SJohn Baldwin * the blocked chain 16736412d79SJohn Baldwin */ 168b40ce416SJulian Elischer if (td == TAILQ_FIRST(&m->mtx_blocked)) { 1691bd0eefbSJohn Baldwin continue; 1701bd0eefbSJohn Baldwin } 1719ed346baSBosko Milekic 172b40ce416SJulian Elischer td1 = TAILQ_PREV(td, threadqueue, td_blkq); 1732c100766SJulian Elischer if (td1->td_priority <= pri) { 17436412d79SJohn Baldwin continue; 17536412d79SJohn Baldwin } 17636412d79SJohn Baldwin 17736412d79SJohn Baldwin /* 178b40ce416SJulian Elischer * Remove thread from blocked chain and determine where 179b40ce416SJulian Elischer * it should be moved up to. Since we know that td1 has 180b40ce416SJulian Elischer * a lower priority than td, we know that at least one 181b40ce416SJulian Elischer * thread in the chain has a lower priority and that 182b40ce416SJulian Elischer * td1 will thus not be NULL after the loop. 18336412d79SJohn Baldwin */ 184b40ce416SJulian Elischer TAILQ_REMOVE(&m->mtx_blocked, td, td_blkq); 185b40ce416SJulian Elischer TAILQ_FOREACH(td1, &m->mtx_blocked, td_blkq) { 186b40ce416SJulian Elischer MPASS(td1->td_proc->p_magic == P_MAGIC); 1872c100766SJulian Elischer if (td1->td_priority > pri) 18836412d79SJohn Baldwin break; 18936412d79SJohn Baldwin } 1909ed346baSBosko Milekic 191b40ce416SJulian Elischer MPASS(td1 != NULL); 192b40ce416SJulian Elischer TAILQ_INSERT_BEFORE(td1, td, td_blkq); 19336412d79SJohn Baldwin CTR4(KTR_LOCK, 1948484de75SJohn Baldwin "propagate_priority: p %p moved before %p on [%p] %s", 195b40ce416SJulian Elischer td, td1, m, m->mtx_object.lo_name); 19636412d79SJohn Baldwin } 19736412d79SJohn Baldwin } 19836412d79SJohn Baldwin 1990cde2e34SJason Evans /* 2006283b7d0SJohn Baldwin * Function versions of the inlined __mtx_* macros. These are used by 2016283b7d0SJohn Baldwin * modules and can also be called from assembly language if needed. 2026283b7d0SJohn Baldwin */ 2036283b7d0SJohn Baldwin void 2046283b7d0SJohn Baldwin _mtx_lock_flags(struct mtx *m, int opts, const char *file, int line) 2056283b7d0SJohn Baldwin { 2066283b7d0SJohn Baldwin 207dde96c99SJohn Baldwin MPASS(curthread != NULL); 208dde96c99SJohn Baldwin _get_sleep_lock(m, curthread, opts, file, line); 209dde96c99SJohn Baldwin LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file, 210dde96c99SJohn Baldwin line); 211dde96c99SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 2126283b7d0SJohn Baldwin } 2136283b7d0SJohn Baldwin 2146283b7d0SJohn Baldwin void 2156283b7d0SJohn Baldwin _mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line) 2166283b7d0SJohn Baldwin { 2176283b7d0SJohn Baldwin 218dde96c99SJohn Baldwin MPASS(curthread != NULL); 21921377ce0SJohn Baldwin mtx_assert(m, MA_OWNED); 220dde96c99SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 221dde96c99SJohn Baldwin LOCK_LOG_LOCK("UNLOCK", &m->mtx_object, opts, m->mtx_recurse, file, 222dde96c99SJohn Baldwin line); 223dde96c99SJohn Baldwin _rel_sleep_lock(m, curthread, opts, file, line); 2246283b7d0SJohn Baldwin } 2256283b7d0SJohn Baldwin 2266283b7d0SJohn Baldwin void 2276283b7d0SJohn Baldwin _mtx_lock_spin_flags(struct mtx *m, int opts, const char *file, int line) 2286283b7d0SJohn Baldwin { 2296283b7d0SJohn Baldwin 230dde96c99SJohn Baldwin MPASS(curthread != NULL); 231dde96c99SJohn Baldwin _get_spin_lock(m, curthread, opts, file, line); 232dde96c99SJohn Baldwin LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file, 233dde96c99SJohn Baldwin line); 234dde96c99SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 2356283b7d0SJohn Baldwin } 2366283b7d0SJohn Baldwin 2376283b7d0SJohn Baldwin void 2386283b7d0SJohn Baldwin _mtx_unlock_spin_flags(struct mtx *m, int opts, const char *file, int line) 2396283b7d0SJohn Baldwin { 2406283b7d0SJohn Baldwin 241dde96c99SJohn Baldwin MPASS(curthread != NULL); 24221377ce0SJohn Baldwin mtx_assert(m, MA_OWNED); 243dde96c99SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 244dde96c99SJohn Baldwin LOCK_LOG_LOCK("UNLOCK", &m->mtx_object, opts, m->mtx_recurse, file, 245dde96c99SJohn Baldwin line); 246dde96c99SJohn Baldwin _rel_spin_lock(m); 2476283b7d0SJohn Baldwin } 2486283b7d0SJohn Baldwin 2496283b7d0SJohn Baldwin /* 2509ed346baSBosko Milekic * The important part of mtx_trylock{,_flags}() 2519ed346baSBosko Milekic * Tries to acquire lock `m.' We do NOT handle recursion here; we assume that 2529ed346baSBosko Milekic * if we're called, it's because we know we don't already own this lock. 2530cde2e34SJason Evans */ 2540cde2e34SJason Evans int 2559ed346baSBosko Milekic _mtx_trylock(struct mtx *m, int opts, const char *file, int line) 2560cde2e34SJason Evans { 2570cde2e34SJason Evans int rval; 2580cde2e34SJason Evans 259b40ce416SJulian Elischer MPASS(curthread != NULL); 2609ed346baSBosko Milekic 261b40ce416SJulian Elischer rval = _obtain_lock(m, curthread); 2629ed346baSBosko Milekic 26319284646SJohn Baldwin LOCK_LOG_TRY("LOCK", &m->mtx_object, opts, rval, file, line); 26419284646SJohn Baldwin if (rval) { 2659ed346baSBosko Milekic /* 2669ed346baSBosko Milekic * We do not handle recursion in _mtx_trylock; see the 2679ed346baSBosko Milekic * note at the top of the routine. 2689ed346baSBosko Milekic */ 2695746a1d8SBosko Milekic KASSERT(!mtx_recursed(m), 2705746a1d8SBosko Milekic ("mtx_trylock() called on a recursed mutex")); 2712d96f0b1SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE | LOP_TRYLOCK, 2722d96f0b1SJohn Baldwin file, line); 2730cde2e34SJason Evans } 2749ed346baSBosko Milekic 27519284646SJohn Baldwin return (rval); 2760cde2e34SJason Evans } 2770cde2e34SJason Evans 2780cde2e34SJason Evans /* 2799ed346baSBosko Milekic * _mtx_lock_sleep: the tougher part of acquiring an MTX_DEF lock. 2809ed346baSBosko Milekic * 2819ed346baSBosko Milekic * We call this if the lock is either contested (i.e. we need to go to 2829ed346baSBosko Milekic * sleep waiting for it), or if we need to recurse on it. 2830cde2e34SJason Evans */ 2840cde2e34SJason Evans void 2859ed346baSBosko Milekic _mtx_lock_sleep(struct mtx *m, int opts, const char *file, int line) 28636412d79SJohn Baldwin { 287b40ce416SJulian Elischer struct thread *td = curthread; 28836412d79SJohn Baldwin 289b40ce416SJulian Elischer if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)td) { 29036412d79SJohn Baldwin m->mtx_recurse++; 29108812b39SBosko Milekic atomic_set_ptr(&m->mtx_lock, MTX_RECURSED); 29219284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 2935746a1d8SBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_sleep: %p recursing", m); 29436412d79SJohn Baldwin return; 29536412d79SJohn Baldwin } 2969ed346baSBosko Milekic 29719284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 29815ec816aSJohn Baldwin CTR4(KTR_LOCK, 29915ec816aSJohn Baldwin "_mtx_lock_sleep: %s contested (lock=%p) at %s:%d", 30019284646SJohn Baldwin m->mtx_object.lo_name, (void *)m->mtx_lock, file, line); 3011bd0eefbSJohn Baldwin 302b40ce416SJulian Elischer while (!_obtain_lock(m, td)) { 303f5271ebcSJohn Baldwin uintptr_t v; 304b40ce416SJulian Elischer struct thread *td1; 30536412d79SJohn Baldwin 3069ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 30736412d79SJohn Baldwin /* 3089ed346baSBosko Milekic * Check if the lock has been released while spinning for 3099ed346baSBosko Milekic * the sched_lock. 31036412d79SJohn Baldwin */ 31136412d79SJohn Baldwin if ((v = m->mtx_lock) == MTX_UNOWNED) { 3129ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 31336412d79SJohn Baldwin continue; 31436412d79SJohn Baldwin } 3159ed346baSBosko Milekic 31636412d79SJohn Baldwin /* 3179ed346baSBosko Milekic * The mutex was marked contested on release. This means that 318b40ce416SJulian Elischer * there are threads blocked on it. 31936412d79SJohn Baldwin */ 32036412d79SJohn Baldwin if (v == MTX_CONTESTED) { 321b40ce416SJulian Elischer td1 = TAILQ_FIRST(&m->mtx_blocked); 322b40ce416SJulian Elischer MPASS(td1 != NULL); 323b40ce416SJulian Elischer m->mtx_lock = (uintptr_t)td | MTX_CONTESTED; 3249ed346baSBosko Milekic 3252c100766SJulian Elischer if (td1->td_priority < td->td_priority) 3262c100766SJulian Elischer td->td_priority = td1->td_priority; 3279ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 32836412d79SJohn Baldwin return; 32936412d79SJohn Baldwin } 3309ed346baSBosko Milekic 33136412d79SJohn Baldwin /* 3329ed346baSBosko Milekic * If the mutex isn't already contested and a failure occurs 3339ed346baSBosko Milekic * setting the contested bit, the mutex was either released 3349ed346baSBosko Milekic * or the state of the MTX_RECURSED bit changed. 33536412d79SJohn Baldwin */ 33636412d79SJohn Baldwin if ((v & MTX_CONTESTED) == 0 && 33736412d79SJohn Baldwin !atomic_cmpset_ptr(&m->mtx_lock, (void *)v, 33836412d79SJohn Baldwin (void *)(v | MTX_CONTESTED))) { 3399ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 34036412d79SJohn Baldwin continue; 34136412d79SJohn Baldwin } 34236412d79SJohn Baldwin 3439ed346baSBosko Milekic /* 3449ed346baSBosko Milekic * We deffinately must sleep for this lock. 3459ed346baSBosko Milekic */ 34636412d79SJohn Baldwin mtx_assert(m, MA_NOTOWNED); 34736412d79SJohn Baldwin 34836412d79SJohn Baldwin #ifdef notyet 34936412d79SJohn Baldwin /* 3509ed346baSBosko Milekic * If we're borrowing an interrupted thread's VM context, we 3519ed346baSBosko Milekic * must clean up before going to sleep. 35236412d79SJohn Baldwin */ 353b40ce416SJulian Elischer if (td->td_ithd != NULL) { 354b40ce416SJulian Elischer struct ithd *it = td->td_ithd; 35536412d79SJohn Baldwin 35636412d79SJohn Baldwin if (it->it_interrupted) { 35719284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 35836412d79SJohn Baldwin CTR2(KTR_LOCK, 35915ec816aSJohn Baldwin "_mtx_lock_sleep: %p interrupted %p", 36036412d79SJohn Baldwin it, it->it_interrupted); 36136412d79SJohn Baldwin intr_thd_fixup(it); 36236412d79SJohn Baldwin } 36336412d79SJohn Baldwin } 36436412d79SJohn Baldwin #endif 36536412d79SJohn Baldwin 3669ed346baSBosko Milekic /* 3679ed346baSBosko Milekic * Put us on the list of threads blocked on this mutex. 3689ed346baSBosko Milekic */ 36936412d79SJohn Baldwin if (TAILQ_EMPTY(&m->mtx_blocked)) { 37018fc2ba9SJohn Baldwin td1 = mtx_owner(m); 371b40ce416SJulian Elischer LIST_INSERT_HEAD(&td1->td_contested, m, mtx_contested); 372b40ce416SJulian Elischer TAILQ_INSERT_TAIL(&m->mtx_blocked, td, td_blkq); 37336412d79SJohn Baldwin } else { 374b40ce416SJulian Elischer TAILQ_FOREACH(td1, &m->mtx_blocked, td_blkq) 3752c100766SJulian Elischer if (td1->td_priority > td->td_priority) 37636412d79SJohn Baldwin break; 377b40ce416SJulian Elischer if (td1) 378b40ce416SJulian Elischer TAILQ_INSERT_BEFORE(td1, td, td_blkq); 37936412d79SJohn Baldwin else 380b40ce416SJulian Elischer TAILQ_INSERT_TAIL(&m->mtx_blocked, td, td_blkq); 38136412d79SJohn Baldwin } 38236412d79SJohn Baldwin 3839ed346baSBosko Milekic /* 3849ed346baSBosko Milekic * Save who we're blocked on. 3859ed346baSBosko Milekic */ 386b40ce416SJulian Elischer td->td_blocked = m; 387b40ce416SJulian Elischer td->td_mtxname = m->mtx_object.lo_name; 388b40ce416SJulian Elischer td->td_proc->p_stat = SMTX; 389b40ce416SJulian Elischer propagate_priority(td); 3909ed346baSBosko Milekic 39119284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 392562e4ffeSJohn Baldwin CTR3(KTR_LOCK, 393b40ce416SJulian Elischer "_mtx_lock_sleep: p %p blocked on [%p] %s", td, m, 39419284646SJohn Baldwin m->mtx_object.lo_name); 3959ed346baSBosko Milekic 396b40ce416SJulian Elischer td->td_proc->p_stats->p_ru.ru_nvcsw++; 39720cdcc5bSJohn Baldwin mi_switch(); 3989ed346baSBosko Milekic 39919284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 40036412d79SJohn Baldwin CTR3(KTR_LOCK, 4019ed346baSBosko Milekic "_mtx_lock_sleep: p %p free from blocked on [%p] %s", 402b40ce416SJulian Elischer td, m, m->mtx_object.lo_name); 4039ed346baSBosko Milekic 4049ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 40536412d79SJohn Baldwin } 4069ed346baSBosko Milekic 40736412d79SJohn Baldwin return; 4089ed346baSBosko Milekic } 4099ed346baSBosko Milekic 4109ed346baSBosko Milekic /* 4119ed346baSBosko Milekic * _mtx_lock_spin: the tougher part of acquiring an MTX_SPIN lock. 4129ed346baSBosko Milekic * 4139ed346baSBosko Milekic * This is only called if we need to actually spin for the lock. Recursion 4149ed346baSBosko Milekic * is handled inline. 4159ed346baSBosko Milekic */ 4169ed346baSBosko Milekic void 4177e1f6dfeSJohn Baldwin _mtx_lock_spin(struct mtx *m, int opts, const char *file, int line) 41836412d79SJohn Baldwin { 41936412d79SJohn Baldwin int i = 0; 42036412d79SJohn Baldwin 42119284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4225746a1d8SBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m); 4239ed346baSBosko Milekic 42436412d79SJohn Baldwin for (;;) { 425b40ce416SJulian Elischer if (_obtain_lock(m, curthread)) 42636412d79SJohn Baldwin break; 4279ed346baSBosko Milekic 4287141f2adSJohn Baldwin /* Give interrupts a chance while we spin. */ 4297e1f6dfeSJohn Baldwin critical_exit(); 43036412d79SJohn Baldwin while (m->mtx_lock != MTX_UNOWNED) { 431bf07c922SJohn Baldwin if (i++ < 10000000) 43236412d79SJohn Baldwin continue; 433bf07c922SJohn Baldwin if (i++ < 60000000) 43436412d79SJohn Baldwin DELAY(1); 43536412d79SJohn Baldwin #ifdef DDB 43636412d79SJohn Baldwin else if (!db_active) 43736412d79SJohn Baldwin #else 43836412d79SJohn Baldwin else 43936412d79SJohn Baldwin #endif 4409ed346baSBosko Milekic panic("spin lock %s held by %p for > 5 seconds", 44119284646SJohn Baldwin m->mtx_object.lo_name, (void *)m->mtx_lock); 44236412d79SJohn Baldwin } 4437e1f6dfeSJohn Baldwin critical_enter(); 44436412d79SJohn Baldwin } 44536412d79SJohn Baldwin 44619284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4479ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m); 4489ed346baSBosko Milekic 44936412d79SJohn Baldwin return; 45036412d79SJohn Baldwin } 45136412d79SJohn Baldwin 4529ed346baSBosko Milekic /* 4539ed346baSBosko Milekic * _mtx_unlock_sleep: the tougher part of releasing an MTX_DEF lock. 4549ed346baSBosko Milekic * 4559ed346baSBosko Milekic * We are only called here if the lock is recursed or contested (i.e. we 4569ed346baSBosko Milekic * need to wake up a blocked thread). 4579ed346baSBosko Milekic */ 45836412d79SJohn Baldwin void 4599ed346baSBosko Milekic _mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line) 46036412d79SJohn Baldwin { 461b40ce416SJulian Elischer struct thread *td, *td1; 46236412d79SJohn Baldwin struct mtx *m1; 46336412d79SJohn Baldwin int pri; 46436412d79SJohn Baldwin 465b40ce416SJulian Elischer td = curthread; 4669ed346baSBosko Milekic 46708812b39SBosko Milekic if (mtx_recursed(m)) { 46836412d79SJohn Baldwin if (--(m->mtx_recurse) == 0) 46908812b39SBosko Milekic atomic_clear_ptr(&m->mtx_lock, MTX_RECURSED); 47019284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4719ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p unrecurse", m); 47236412d79SJohn Baldwin return; 47336412d79SJohn Baldwin } 4749ed346baSBosko Milekic 4759ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 47619284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4779ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p contested", m); 4789ed346baSBosko Milekic 479b40ce416SJulian Elischer td1 = TAILQ_FIRST(&m->mtx_blocked); 480b40ce416SJulian Elischer MPASS(td->td_proc->p_magic == P_MAGIC); 481b40ce416SJulian Elischer MPASS(td1->td_proc->p_magic == P_MAGIC); 4829ed346baSBosko Milekic 483b40ce416SJulian Elischer TAILQ_REMOVE(&m->mtx_blocked, td1, td_blkq); 4849ed346baSBosko Milekic 48536412d79SJohn Baldwin if (TAILQ_EMPTY(&m->mtx_blocked)) { 48636412d79SJohn Baldwin LIST_REMOVE(m, mtx_contested); 48736412d79SJohn Baldwin _release_lock_quick(m); 48819284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4899ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p not held", m); 49036412d79SJohn Baldwin } else 4919ed346baSBosko Milekic atomic_store_rel_ptr(&m->mtx_lock, (void *)MTX_CONTESTED); 4929ed346baSBosko Milekic 493d5a08a60SJake Burkholder pri = PRI_MAX; 494b40ce416SJulian Elischer LIST_FOREACH(m1, &td->td_contested, mtx_contested) { 4952c100766SJulian Elischer int cp = TAILQ_FIRST(&m1->mtx_blocked)->td_priority; 49636412d79SJohn Baldwin if (cp < pri) 49736412d79SJohn Baldwin pri = cp; 49836412d79SJohn Baldwin } 4999ed346baSBosko Milekic 5002c100766SJulian Elischer if (pri > td->td_base_pri) 5012c100766SJulian Elischer pri = td->td_base_pri; 5022c100766SJulian Elischer td->td_priority = pri; 5039ed346baSBosko Milekic 50419284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 5059ed346baSBosko Milekic CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p contested setrunqueue %p", 506b40ce416SJulian Elischer m, td1); 5079ed346baSBosko Milekic 508b40ce416SJulian Elischer td1->td_blocked = NULL; 509b40ce416SJulian Elischer td1->td_proc->p_stat = SRUN; 510b40ce416SJulian Elischer setrunqueue(td1); 5119ed346baSBosko Milekic 5122c100766SJulian Elischer if (td->td_critnest == 1 && td1->td_priority < pri) { 51336412d79SJohn Baldwin #ifdef notyet 514b40ce416SJulian Elischer if (td->td_ithd != NULL) { 515b40ce416SJulian Elischer struct ithd *it = td->td_ithd; 51636412d79SJohn Baldwin 51736412d79SJohn Baldwin if (it->it_interrupted) { 51819284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 51936412d79SJohn Baldwin CTR2(KTR_LOCK, 52015ec816aSJohn Baldwin "_mtx_unlock_sleep: %p interrupted %p", 52136412d79SJohn Baldwin it, it->it_interrupted); 52236412d79SJohn Baldwin intr_thd_fixup(it); 52336412d79SJohn Baldwin } 52436412d79SJohn Baldwin } 52536412d79SJohn Baldwin #endif 526b40ce416SJulian Elischer setrunqueue(td); 52719284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 528562e4ffeSJohn Baldwin CTR2(KTR_LOCK, 5299ed346baSBosko Milekic "_mtx_unlock_sleep: %p switching out lock=%p", m, 5309ed346baSBosko Milekic (void *)m->mtx_lock); 5319ed346baSBosko Milekic 532b40ce416SJulian Elischer td->td_proc->p_stats->p_ru.ru_nivcsw++; 53336412d79SJohn Baldwin mi_switch(); 53419284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 5359ed346baSBosko Milekic CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p resuming lock=%p", 53631271627SJohn Baldwin m, (void *)m->mtx_lock); 53736412d79SJohn Baldwin } 53836412d79SJohn Baldwin 5399ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 5409ed346baSBosko Milekic 5419ed346baSBosko Milekic return; 5429ed346baSBosko Milekic } 5439ed346baSBosko Milekic 5449ed346baSBosko Milekic /* 5459ed346baSBosko Milekic * All the unlocking of MTX_SPIN locks is done inline. 5469ed346baSBosko Milekic * See the _rel_spin_lock() macro for the details. 5479ed346baSBosko Milekic */ 5489ed346baSBosko Milekic 5499ed346baSBosko Milekic /* 55015ec816aSJohn Baldwin * The backing function for the INVARIANTS-enabled mtx_assert() 5519ed346baSBosko Milekic */ 5521103f3b0SJohn Baldwin #ifdef INVARIANT_SUPPORT 5530cde2e34SJason Evans void 55456771ca7SJason Evans _mtx_assert(struct mtx *m, int what, const char *file, int line) 5550cde2e34SJason Evans { 5565cb0fbe4SJohn Baldwin 5575cb0fbe4SJohn Baldwin if (panicstr != NULL) 5585cb0fbe4SJohn Baldwin return; 559a10f4966SJake Burkholder switch (what) { 5600cde2e34SJason Evans case MA_OWNED: 5610cde2e34SJason Evans case MA_OWNED | MA_RECURSED: 5620cde2e34SJason Evans case MA_OWNED | MA_NOTRECURSED: 563a10f4966SJake Burkholder if (!mtx_owned(m)) 5640cde2e34SJason Evans panic("mutex %s not owned at %s:%d", 56519284646SJohn Baldwin m->mtx_object.lo_name, file, line); 566a10f4966SJake Burkholder if (mtx_recursed(m)) { 567a10f4966SJake Burkholder if ((what & MA_NOTRECURSED) != 0) 5680cde2e34SJason Evans panic("mutex %s recursed at %s:%d", 56919284646SJohn Baldwin m->mtx_object.lo_name, file, line); 570a10f4966SJake Burkholder } else if ((what & MA_RECURSED) != 0) { 5710cde2e34SJason Evans panic("mutex %s unrecursed at %s:%d", 57219284646SJohn Baldwin m->mtx_object.lo_name, file, line); 5730cde2e34SJason Evans } 5740cde2e34SJason Evans break; 5750cde2e34SJason Evans case MA_NOTOWNED: 576a10f4966SJake Burkholder if (mtx_owned(m)) 5770cde2e34SJason Evans panic("mutex %s owned at %s:%d", 57819284646SJohn Baldwin m->mtx_object.lo_name, file, line); 5790cde2e34SJason Evans break; 5800cde2e34SJason Evans default: 58156771ca7SJason Evans panic("unknown mtx_assert at %s:%d", file, line); 5820cde2e34SJason Evans } 5830cde2e34SJason Evans } 5840cde2e34SJason Evans #endif 5850cde2e34SJason Evans 5869ed346baSBosko Milekic /* 5879ed346baSBosko Milekic * The MUTEX_DEBUG-enabled mtx_validate() 58819284646SJohn Baldwin * 58919284646SJohn Baldwin * Most of these checks have been moved off into the LO_INITIALIZED flag 59019284646SJohn Baldwin * maintained by the witness code. 5919ed346baSBosko Milekic */ 59236412d79SJohn Baldwin #ifdef MUTEX_DEBUG 59336412d79SJohn Baldwin 5944d77a549SAlfred Perlstein void mtx_validate(struct mtx *); 59536412d79SJohn Baldwin 59619284646SJohn Baldwin void 59719284646SJohn Baldwin mtx_validate(struct mtx *m) 59836412d79SJohn Baldwin { 59936412d79SJohn Baldwin 60036412d79SJohn Baldwin /* 60136412d79SJohn Baldwin * XXX - When kernacc() is fixed on the alpha to handle K0_SEG memory properly 60236412d79SJohn Baldwin * we can re-enable the kernacc() checks. 60336412d79SJohn Baldwin */ 60436412d79SJohn Baldwin #ifndef __alpha__ 60576dcbd6fSBosko Milekic /* 60676dcbd6fSBosko Milekic * Can't call kernacc() from early init386(), especially when 60776dcbd6fSBosko Milekic * initializing Giant mutex, because some stuff in kernacc() 60876dcbd6fSBosko Milekic * requires Giant itself. 60976dcbd6fSBosko Milekic */ 610ab07087eSBosko Milekic if (!cold) 611ab07087eSBosko Milekic if (!kernacc((caddr_t)m, sizeof(m), 612ab07087eSBosko Milekic VM_PROT_READ | VM_PROT_WRITE)) 61319284646SJohn Baldwin panic("Can't read and write to mutex %p", m); 61436412d79SJohn Baldwin #endif 61536412d79SJohn Baldwin } 61636412d79SJohn Baldwin #endif 61736412d79SJohn Baldwin 6189ed346baSBosko Milekic /* 6199ed346baSBosko Milekic * Mutex initialization routine; initialize lock `m' of type contained in 6209ed346baSBosko Milekic * `opts' with options contained in `opts' and description `description.' 6219ed346baSBosko Milekic */ 62236412d79SJohn Baldwin void 6239ed346baSBosko Milekic mtx_init(struct mtx *m, const char *description, int opts) 62436412d79SJohn Baldwin { 62519284646SJohn Baldwin struct lock_object *lock; 6269ed346baSBosko Milekic 62719284646SJohn Baldwin MPASS((opts & ~(MTX_SPIN | MTX_QUIET | MTX_RECURSE | 628f22a4b62SJeff Roberson MTX_SLEEPABLE | MTX_NOWITNESS | MTX_DUPOK)) == 0); 6299ed346baSBosko Milekic 63036412d79SJohn Baldwin #ifdef MUTEX_DEBUG 6319ed346baSBosko Milekic /* Diagnostic and error correction */ 63219284646SJohn Baldwin mtx_validate(m); 6336936206eSJohn Baldwin #endif 63436412d79SJohn Baldwin 63519284646SJohn Baldwin lock = &m->mtx_object; 6367ada5876SJohn Baldwin KASSERT((lock->lo_flags & LO_INITIALIZED) == 0, 6377ada5876SJohn Baldwin ("mutex %s %p already initialized", description, m)); 6387ada5876SJohn Baldwin bzero(m, sizeof(*m)); 63919284646SJohn Baldwin if (opts & MTX_SPIN) 64019284646SJohn Baldwin lock->lo_class = &lock_class_mtx_spin; 64119284646SJohn Baldwin else 64219284646SJohn Baldwin lock->lo_class = &lock_class_mtx_sleep; 64319284646SJohn Baldwin lock->lo_name = description; 64419284646SJohn Baldwin if (opts & MTX_QUIET) 64519284646SJohn Baldwin lock->lo_flags = LO_QUIET; 64619284646SJohn Baldwin if (opts & MTX_RECURSE) 64719284646SJohn Baldwin lock->lo_flags |= LO_RECURSABLE; 64819284646SJohn Baldwin if (opts & MTX_SLEEPABLE) 64919284646SJohn Baldwin lock->lo_flags |= LO_SLEEPABLE; 65019284646SJohn Baldwin if ((opts & MTX_NOWITNESS) == 0) 65119284646SJohn Baldwin lock->lo_flags |= LO_WITNESS; 652f22a4b62SJeff Roberson if (opts & MTX_DUPOK) 653f22a4b62SJeff Roberson lock->lo_flags |= LO_DUPOK; 65419284646SJohn Baldwin 65519284646SJohn Baldwin m->mtx_lock = MTX_UNOWNED; 65636412d79SJohn Baldwin TAILQ_INIT(&m->mtx_blocked); 6579ed346baSBosko Milekic 65819284646SJohn Baldwin LOCK_LOG_INIT(lock, opts); 659d1c1b841SJason Evans 66019284646SJohn Baldwin WITNESS_INIT(lock); 66136412d79SJohn Baldwin } 66236412d79SJohn Baldwin 6639ed346baSBosko Milekic /* 66419284646SJohn Baldwin * Remove lock `m' from all_mtx queue. We don't allow MTX_QUIET to be 66519284646SJohn Baldwin * passed in as a flag here because if the corresponding mtx_init() was 66619284646SJohn Baldwin * called with MTX_QUIET set, then it will already be set in the mutex's 66719284646SJohn Baldwin * flags. 6689ed346baSBosko Milekic */ 66936412d79SJohn Baldwin void 67036412d79SJohn Baldwin mtx_destroy(struct mtx *m) 67136412d79SJohn Baldwin { 67236412d79SJohn Baldwin 67319284646SJohn Baldwin LOCK_LOG_DESTROY(&m->mtx_object, 0); 6749ed346baSBosko Milekic 67519284646SJohn Baldwin if (!mtx_owned(m)) 67619284646SJohn Baldwin MPASS(mtx_unowned(m)); 67719284646SJohn Baldwin else { 67808812b39SBosko Milekic MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0); 6799ed346baSBosko Milekic 68019284646SJohn Baldwin /* Tell witness this isn't locked to make it happy. */ 681c86b6ff5SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, LOP_EXCLUSIVE, __FILE__, 682c86b6ff5SJohn Baldwin __LINE__); 68336412d79SJohn Baldwin } 6840384fff8SJason Evans 68519284646SJohn Baldwin WITNESS_DESTROY(&m->mtx_object); 6860384fff8SJason Evans } 687d23f5958SMatthew Dillon 688d23f5958SMatthew Dillon /* 689d23f5958SMatthew Dillon * Encapsulated Giant mutex routines. These routines provide encapsulation 690d23f5958SMatthew Dillon * control for the Giant mutex, allowing sysctls to be used to turn on and 691d23f5958SMatthew Dillon * off Giant around certain subsystems. The default value for the sysctls 692d23f5958SMatthew Dillon * are set to what developers believe is stable and working in regards to 693d23f5958SMatthew Dillon * the Giant pushdown. Developers should not turn off Giant via these 694d23f5958SMatthew Dillon * sysctls unless they know what they are doing. 695d23f5958SMatthew Dillon * 696d23f5958SMatthew Dillon * Callers of mtx_lock_giant() are expected to pass the return value to an 697d23f5958SMatthew Dillon * accompanying mtx_unlock_giant() later on. If multiple subsystems are 698d23f5958SMatthew Dillon * effected by a Giant wrap, all related sysctl variables must be zero for 699d23f5958SMatthew Dillon * the subsystem call to operate without Giant (as determined by the caller). 700d23f5958SMatthew Dillon */ 701d23f5958SMatthew Dillon 702d23f5958SMatthew Dillon SYSCTL_NODE(_kern, OID_AUTO, giant, CTLFLAG_RD, NULL, "Giant mutex manipulation"); 703d23f5958SMatthew Dillon 704d23f5958SMatthew Dillon static int kern_giant_all = 0; 705d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, all, CTLFLAG_RW, &kern_giant_all, 0, ""); 706d23f5958SMatthew Dillon 707d23f5958SMatthew Dillon int kern_giant_proc = 1; /* Giant around PROC locks */ 708d23f5958SMatthew Dillon int kern_giant_file = 1; /* Giant around struct file & filedesc */ 709735da6deSMatthew Dillon int kern_giant_ucred = 1; /* Giant around ucred */ 710d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, proc, CTLFLAG_RW, &kern_giant_proc, 0, ""); 711d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, file, CTLFLAG_RW, &kern_giant_file, 0, ""); 712735da6deSMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, ucred, CTLFLAG_RW, &kern_giant_ucred, 0, ""); 713d23f5958SMatthew Dillon 714d23f5958SMatthew Dillon int 715d23f5958SMatthew Dillon mtx_lock_giant(int sysctlvar) 716d23f5958SMatthew Dillon { 717d23f5958SMatthew Dillon if (sysctlvar || kern_giant_all) { 718d23f5958SMatthew Dillon mtx_lock(&Giant); 719d23f5958SMatthew Dillon return(1); 720d23f5958SMatthew Dillon } 721d23f5958SMatthew Dillon return(0); 722d23f5958SMatthew Dillon } 723d23f5958SMatthew Dillon 724d23f5958SMatthew Dillon void 725d23f5958SMatthew Dillon mtx_unlock_giant(int s) 726d23f5958SMatthew Dillon { 727d23f5958SMatthew Dillon if (s) 728d23f5958SMatthew Dillon mtx_unlock(&Giant); 729d23f5958SMatthew Dillon } 730d23f5958SMatthew Dillon 731