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 70b40ce416SJulian Elischer #define SET_PRIO(td, pri) (td)->td_ksegrp->kg_pri.pri_level = (pri) 710cde2e34SJason Evans 720cde2e34SJason Evans /* 7319284646SJohn Baldwin * Lock classes for sleep and spin mutexes. 740cde2e34SJason Evans */ 7519284646SJohn Baldwin struct lock_class lock_class_mtx_sleep = { 7619284646SJohn Baldwin "sleep mutex", 7719284646SJohn Baldwin LC_SLEEPLOCK | LC_RECURSABLE 7819284646SJohn Baldwin }; 7919284646SJohn Baldwin struct lock_class lock_class_mtx_spin = { 8019284646SJohn Baldwin "spin mutex", 8119284646SJohn Baldwin LC_SPINLOCK | LC_RECURSABLE 828484de75SJohn Baldwin }; 838484de75SJohn Baldwin 849ed346baSBosko Milekic /* 859ed346baSBosko Milekic * Prototypes for non-exported routines. 869ed346baSBosko Milekic */ 87b40ce416SJulian Elischer static void propagate_priority(struct thread *); 8836412d79SJohn Baldwin 8936412d79SJohn Baldwin static void 90b40ce416SJulian Elischer propagate_priority(struct thread *td) 9136412d79SJohn Baldwin { 92b40ce416SJulian Elischer struct ksegrp *kg = td->td_ksegrp; 93b40ce416SJulian Elischer int pri = kg->kg_pri.pri_level; 94b40ce416SJulian Elischer struct mtx *m = td->td_blocked; 9536412d79SJohn Baldwin 961bd0eefbSJohn Baldwin mtx_assert(&sched_lock, MA_OWNED); 9736412d79SJohn Baldwin for (;;) { 98b40ce416SJulian Elischer struct thread *td1; 9936412d79SJohn Baldwin 100b40ce416SJulian Elischer td = mtx_owner(m); 10136412d79SJohn Baldwin 102b40ce416SJulian Elischer if (td == NULL) { 10336412d79SJohn Baldwin /* 10436412d79SJohn Baldwin * This really isn't quite right. Really 105b40ce416SJulian Elischer * ought to bump priority of thread that 10636412d79SJohn Baldwin * next acquires the mutex. 10736412d79SJohn Baldwin */ 10836412d79SJohn Baldwin MPASS(m->mtx_lock == MTX_CONTESTED); 10936412d79SJohn Baldwin return; 11036412d79SJohn Baldwin } 111a44f918bSJohn Baldwin kg = td->td_ksegrp; 1129ed346baSBosko Milekic 113b40ce416SJulian Elischer MPASS(td->td_proc->p_magic == P_MAGIC); 114b40ce416SJulian Elischer KASSERT(td->td_proc->p_stat != SSLEEP, ("sleeping thread owns a mutex")); 115b40ce416SJulian Elischer if (kg->kg_pri.pri_level <= pri) /* lower is higher priority */ 11636412d79SJohn Baldwin return; 1171bd0eefbSJohn Baldwin 1181bd0eefbSJohn Baldwin /* 119b40ce416SJulian Elischer * Bump this thread's priority. 1201bd0eefbSJohn Baldwin */ 121b40ce416SJulian Elischer SET_PRIO(td, pri); 1221bd0eefbSJohn Baldwin 12336412d79SJohn Baldwin /* 12436412d79SJohn Baldwin * If lock holder is actually running, just bump priority. 12536412d79SJohn Baldwin */ 126b40ce416SJulian Elischer /* XXXKSE this test is not sufficient */ 127b40ce416SJulian Elischer if (td->td_kse && (td->td_kse->ke_oncpu != NOCPU)) { 128b40ce416SJulian Elischer MPASS(td->td_proc->p_stat == SRUN 129b40ce416SJulian Elischer || td->td_proc->p_stat == SZOMB 130b40ce416SJulian Elischer || td->td_proc->p_stat == SSTOP); 13136412d79SJohn Baldwin return; 13236412d79SJohn Baldwin } 133d5a08a60SJake Burkholder 1341b43703bSJohn Baldwin #ifndef SMP 1351b43703bSJohn Baldwin /* 136b40ce416SJulian Elischer * For UP, we check to see if td is curthread (this shouldn't 1371b43703bSJohn Baldwin * ever happen however as it would mean we are in a deadlock.) 1381b43703bSJohn Baldwin */ 139b40ce416SJulian Elischer KASSERT(td != curthread, ("Deadlock detected")); 1401b43703bSJohn Baldwin #endif 1411b43703bSJohn Baldwin 14236412d79SJohn Baldwin /* 143b40ce416SJulian Elischer * If on run queue move to new run queue, and quit. 144b40ce416SJulian Elischer * XXXKSE this gets a lot more complicated under threads 145b40ce416SJulian Elischer * but try anyhow. 14636412d79SJohn Baldwin */ 147b40ce416SJulian Elischer if (td->td_proc->p_stat == SRUN) { 148b40ce416SJulian Elischer MPASS(td->td_blocked == NULL); 149b40ce416SJulian Elischer remrunqueue(td); 150b40ce416SJulian Elischer setrunqueue(td); 15136412d79SJohn Baldwin return; 15236412d79SJohn Baldwin } 15336412d79SJohn Baldwin 15436412d79SJohn Baldwin /* 1551bd0eefbSJohn Baldwin * If we aren't blocked on a mutex, we should be. 15636412d79SJohn Baldwin */ 157b40ce416SJulian Elischer KASSERT(td->td_proc->p_stat == SMTX, ( 1581bd0eefbSJohn Baldwin "process %d(%s):%d holds %s but isn't blocked on a mutex\n", 159b40ce416SJulian Elischer td->td_proc->p_pid, td->td_proc->p_comm, td->td_proc->p_stat, 16019284646SJohn Baldwin m->mtx_object.lo_name)); 16136412d79SJohn Baldwin 16236412d79SJohn Baldwin /* 163b40ce416SJulian Elischer * Pick up the mutex that td is blocked on. 16436412d79SJohn Baldwin */ 165b40ce416SJulian Elischer m = td->td_blocked; 16636412d79SJohn Baldwin MPASS(m != NULL); 16736412d79SJohn Baldwin 16836412d79SJohn Baldwin /* 169b40ce416SJulian Elischer * Check if the thread needs to be moved up on 17036412d79SJohn Baldwin * the blocked chain 17136412d79SJohn Baldwin */ 172b40ce416SJulian Elischer if (td == TAILQ_FIRST(&m->mtx_blocked)) { 1731bd0eefbSJohn Baldwin continue; 1741bd0eefbSJohn Baldwin } 1759ed346baSBosko Milekic 176b40ce416SJulian Elischer td1 = TAILQ_PREV(td, threadqueue, td_blkq); 177b40ce416SJulian Elischer if (td1->td_ksegrp->kg_pri.pri_level <= pri) { 17836412d79SJohn Baldwin continue; 17936412d79SJohn Baldwin } 18036412d79SJohn Baldwin 18136412d79SJohn Baldwin /* 182b40ce416SJulian Elischer * Remove thread from blocked chain and determine where 183b40ce416SJulian Elischer * it should be moved up to. Since we know that td1 has 184b40ce416SJulian Elischer * a lower priority than td, we know that at least one 185b40ce416SJulian Elischer * thread in the chain has a lower priority and that 186b40ce416SJulian Elischer * td1 will thus not be NULL after the loop. 18736412d79SJohn Baldwin */ 188b40ce416SJulian Elischer TAILQ_REMOVE(&m->mtx_blocked, td, td_blkq); 189b40ce416SJulian Elischer TAILQ_FOREACH(td1, &m->mtx_blocked, td_blkq) { 190b40ce416SJulian Elischer MPASS(td1->td_proc->p_magic == P_MAGIC); 191b40ce416SJulian Elischer if (td1->td_ksegrp->kg_pri.pri_level > pri) 19236412d79SJohn Baldwin break; 19336412d79SJohn Baldwin } 1949ed346baSBosko Milekic 195b40ce416SJulian Elischer MPASS(td1 != NULL); 196b40ce416SJulian Elischer TAILQ_INSERT_BEFORE(td1, td, td_blkq); 19736412d79SJohn Baldwin CTR4(KTR_LOCK, 1988484de75SJohn Baldwin "propagate_priority: p %p moved before %p on [%p] %s", 199b40ce416SJulian Elischer td, td1, m, m->mtx_object.lo_name); 20036412d79SJohn Baldwin } 20136412d79SJohn Baldwin } 20236412d79SJohn Baldwin 2030cde2e34SJason Evans /* 2046283b7d0SJohn Baldwin * Function versions of the inlined __mtx_* macros. These are used by 2056283b7d0SJohn Baldwin * modules and can also be called from assembly language if needed. 2066283b7d0SJohn Baldwin */ 2076283b7d0SJohn Baldwin void 2086283b7d0SJohn Baldwin _mtx_lock_flags(struct mtx *m, int opts, const char *file, int line) 2096283b7d0SJohn Baldwin { 2106283b7d0SJohn Baldwin 211dde96c99SJohn Baldwin MPASS(curthread != NULL); 212dde96c99SJohn Baldwin _get_sleep_lock(m, curthread, opts, file, line); 213dde96c99SJohn Baldwin LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file, 214dde96c99SJohn Baldwin line); 215dde96c99SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 2166283b7d0SJohn Baldwin } 2176283b7d0SJohn Baldwin 2186283b7d0SJohn Baldwin void 2196283b7d0SJohn Baldwin _mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line) 2206283b7d0SJohn Baldwin { 2216283b7d0SJohn Baldwin 222dde96c99SJohn Baldwin MPASS(curthread != NULL); 22321377ce0SJohn Baldwin mtx_assert(m, MA_OWNED); 224dde96c99SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 225dde96c99SJohn Baldwin LOCK_LOG_LOCK("UNLOCK", &m->mtx_object, opts, m->mtx_recurse, file, 226dde96c99SJohn Baldwin line); 227dde96c99SJohn Baldwin _rel_sleep_lock(m, curthread, opts, file, line); 2286283b7d0SJohn Baldwin } 2296283b7d0SJohn Baldwin 2306283b7d0SJohn Baldwin void 2316283b7d0SJohn Baldwin _mtx_lock_spin_flags(struct mtx *m, int opts, const char *file, int line) 2326283b7d0SJohn Baldwin { 2336283b7d0SJohn Baldwin 234dde96c99SJohn Baldwin MPASS(curthread != NULL); 235dde96c99SJohn Baldwin _get_spin_lock(m, curthread, opts, file, line); 236dde96c99SJohn Baldwin LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file, 237dde96c99SJohn Baldwin line); 238dde96c99SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 2396283b7d0SJohn Baldwin } 2406283b7d0SJohn Baldwin 2416283b7d0SJohn Baldwin void 2426283b7d0SJohn Baldwin _mtx_unlock_spin_flags(struct mtx *m, int opts, const char *file, int line) 2436283b7d0SJohn Baldwin { 2446283b7d0SJohn Baldwin 245dde96c99SJohn Baldwin MPASS(curthread != NULL); 24621377ce0SJohn Baldwin mtx_assert(m, MA_OWNED); 247dde96c99SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line); 248dde96c99SJohn Baldwin LOCK_LOG_LOCK("UNLOCK", &m->mtx_object, opts, m->mtx_recurse, file, 249dde96c99SJohn Baldwin line); 250dde96c99SJohn Baldwin _rel_spin_lock(m); 2516283b7d0SJohn Baldwin } 2526283b7d0SJohn Baldwin 2536283b7d0SJohn Baldwin /* 2549ed346baSBosko Milekic * The important part of mtx_trylock{,_flags}() 2559ed346baSBosko Milekic * Tries to acquire lock `m.' We do NOT handle recursion here; we assume that 2569ed346baSBosko Milekic * if we're called, it's because we know we don't already own this lock. 2570cde2e34SJason Evans */ 2580cde2e34SJason Evans int 2599ed346baSBosko Milekic _mtx_trylock(struct mtx *m, int opts, const char *file, int line) 2600cde2e34SJason Evans { 2610cde2e34SJason Evans int rval; 2620cde2e34SJason Evans 263b40ce416SJulian Elischer MPASS(curthread != NULL); 2649ed346baSBosko Milekic 265b40ce416SJulian Elischer rval = _obtain_lock(m, curthread); 2669ed346baSBosko Milekic 26719284646SJohn Baldwin LOCK_LOG_TRY("LOCK", &m->mtx_object, opts, rval, file, line); 26819284646SJohn Baldwin if (rval) { 2699ed346baSBosko Milekic /* 2709ed346baSBosko Milekic * We do not handle recursion in _mtx_trylock; see the 2719ed346baSBosko Milekic * note at the top of the routine. 2729ed346baSBosko Milekic */ 2735746a1d8SBosko Milekic KASSERT(!mtx_recursed(m), 2745746a1d8SBosko Milekic ("mtx_trylock() called on a recursed mutex")); 2752d96f0b1SJohn Baldwin WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE | LOP_TRYLOCK, 2762d96f0b1SJohn Baldwin file, line); 2770cde2e34SJason Evans } 2789ed346baSBosko Milekic 27919284646SJohn Baldwin return (rval); 2800cde2e34SJason Evans } 2810cde2e34SJason Evans 2820cde2e34SJason Evans /* 2839ed346baSBosko Milekic * _mtx_lock_sleep: the tougher part of acquiring an MTX_DEF lock. 2849ed346baSBosko Milekic * 2859ed346baSBosko Milekic * We call this if the lock is either contested (i.e. we need to go to 2869ed346baSBosko Milekic * sleep waiting for it), or if we need to recurse on it. 2870cde2e34SJason Evans */ 2880cde2e34SJason Evans void 2899ed346baSBosko Milekic _mtx_lock_sleep(struct mtx *m, int opts, const char *file, int line) 29036412d79SJohn Baldwin { 291b40ce416SJulian Elischer struct thread *td = curthread; 292b40ce416SJulian Elischer struct ksegrp *kg = td->td_ksegrp; 29336412d79SJohn Baldwin 294b40ce416SJulian Elischer if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)td) { 29536412d79SJohn Baldwin m->mtx_recurse++; 29608812b39SBosko Milekic atomic_set_ptr(&m->mtx_lock, MTX_RECURSED); 29719284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 2985746a1d8SBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_sleep: %p recursing", m); 29936412d79SJohn Baldwin return; 30036412d79SJohn Baldwin } 3019ed346baSBosko Milekic 30219284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 30315ec816aSJohn Baldwin CTR4(KTR_LOCK, 30415ec816aSJohn Baldwin "_mtx_lock_sleep: %s contested (lock=%p) at %s:%d", 30519284646SJohn Baldwin m->mtx_object.lo_name, (void *)m->mtx_lock, file, line); 3061bd0eefbSJohn Baldwin 307b40ce416SJulian Elischer while (!_obtain_lock(m, td)) { 308f5271ebcSJohn Baldwin uintptr_t v; 309b40ce416SJulian Elischer struct thread *td1; 31036412d79SJohn Baldwin 3119ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 31236412d79SJohn Baldwin /* 3139ed346baSBosko Milekic * Check if the lock has been released while spinning for 3149ed346baSBosko Milekic * the sched_lock. 31536412d79SJohn Baldwin */ 31636412d79SJohn Baldwin if ((v = m->mtx_lock) == MTX_UNOWNED) { 3179ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 31836412d79SJohn Baldwin continue; 31936412d79SJohn Baldwin } 3209ed346baSBosko Milekic 32136412d79SJohn Baldwin /* 3229ed346baSBosko Milekic * The mutex was marked contested on release. This means that 323b40ce416SJulian Elischer * there are threads blocked on it. 32436412d79SJohn Baldwin */ 32536412d79SJohn Baldwin if (v == MTX_CONTESTED) { 326b40ce416SJulian Elischer td1 = TAILQ_FIRST(&m->mtx_blocked); 327b40ce416SJulian Elischer MPASS(td1 != NULL); 328b40ce416SJulian Elischer m->mtx_lock = (uintptr_t)td | MTX_CONTESTED; 3299ed346baSBosko Milekic 330b40ce416SJulian Elischer if (td1->td_ksegrp->kg_pri.pri_level < kg->kg_pri.pri_level) 331b40ce416SJulian Elischer SET_PRIO(td, td1->td_ksegrp->kg_pri.pri_level); 3329ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 33336412d79SJohn Baldwin return; 33436412d79SJohn Baldwin } 3359ed346baSBosko Milekic 33636412d79SJohn Baldwin /* 3379ed346baSBosko Milekic * If the mutex isn't already contested and a failure occurs 3389ed346baSBosko Milekic * setting the contested bit, the mutex was either released 3399ed346baSBosko Milekic * or the state of the MTX_RECURSED bit changed. 34036412d79SJohn Baldwin */ 34136412d79SJohn Baldwin if ((v & MTX_CONTESTED) == 0 && 34236412d79SJohn Baldwin !atomic_cmpset_ptr(&m->mtx_lock, (void *)v, 34336412d79SJohn Baldwin (void *)(v | MTX_CONTESTED))) { 3449ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 34536412d79SJohn Baldwin continue; 34636412d79SJohn Baldwin } 34736412d79SJohn Baldwin 3489ed346baSBosko Milekic /* 3499ed346baSBosko Milekic * We deffinately must sleep for this lock. 3509ed346baSBosko Milekic */ 35136412d79SJohn Baldwin mtx_assert(m, MA_NOTOWNED); 35236412d79SJohn Baldwin 35336412d79SJohn Baldwin #ifdef notyet 35436412d79SJohn Baldwin /* 3559ed346baSBosko Milekic * If we're borrowing an interrupted thread's VM context, we 3569ed346baSBosko Milekic * must clean up before going to sleep. 35736412d79SJohn Baldwin */ 358b40ce416SJulian Elischer if (td->td_ithd != NULL) { 359b40ce416SJulian Elischer struct ithd *it = td->td_ithd; 36036412d79SJohn Baldwin 36136412d79SJohn Baldwin if (it->it_interrupted) { 36219284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 36336412d79SJohn Baldwin CTR2(KTR_LOCK, 36415ec816aSJohn Baldwin "_mtx_lock_sleep: %p interrupted %p", 36536412d79SJohn Baldwin it, it->it_interrupted); 36636412d79SJohn Baldwin intr_thd_fixup(it); 36736412d79SJohn Baldwin } 36836412d79SJohn Baldwin } 36936412d79SJohn Baldwin #endif 37036412d79SJohn Baldwin 3719ed346baSBosko Milekic /* 3729ed346baSBosko Milekic * Put us on the list of threads blocked on this mutex. 3739ed346baSBosko Milekic */ 37436412d79SJohn Baldwin if (TAILQ_EMPTY(&m->mtx_blocked)) { 375b40ce416SJulian Elischer td1 = (struct thread *)(m->mtx_lock & MTX_FLAGMASK); 376b40ce416SJulian Elischer LIST_INSERT_HEAD(&td1->td_contested, m, mtx_contested); 377b40ce416SJulian Elischer TAILQ_INSERT_TAIL(&m->mtx_blocked, td, td_blkq); 37836412d79SJohn Baldwin } else { 379b40ce416SJulian Elischer TAILQ_FOREACH(td1, &m->mtx_blocked, td_blkq) 380b40ce416SJulian Elischer if (td1->td_ksegrp->kg_pri.pri_level > kg->kg_pri.pri_level) 38136412d79SJohn Baldwin break; 382b40ce416SJulian Elischer if (td1) 383b40ce416SJulian Elischer TAILQ_INSERT_BEFORE(td1, td, td_blkq); 38436412d79SJohn Baldwin else 385b40ce416SJulian Elischer TAILQ_INSERT_TAIL(&m->mtx_blocked, td, td_blkq); 38636412d79SJohn Baldwin } 38736412d79SJohn Baldwin 3889ed346baSBosko Milekic /* 3899ed346baSBosko Milekic * Save who we're blocked on. 3909ed346baSBosko Milekic */ 391b40ce416SJulian Elischer td->td_blocked = m; 392b40ce416SJulian Elischer td->td_mtxname = m->mtx_object.lo_name; 393b40ce416SJulian Elischer td->td_proc->p_stat = SMTX; 394b40ce416SJulian Elischer propagate_priority(td); 3959ed346baSBosko Milekic 39619284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 397562e4ffeSJohn Baldwin CTR3(KTR_LOCK, 398b40ce416SJulian Elischer "_mtx_lock_sleep: p %p blocked on [%p] %s", td, m, 39919284646SJohn Baldwin m->mtx_object.lo_name); 4009ed346baSBosko Milekic 401b40ce416SJulian Elischer td->td_proc->p_stats->p_ru.ru_nvcsw++; 40220cdcc5bSJohn Baldwin mi_switch(); 4039ed346baSBosko Milekic 40419284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 40536412d79SJohn Baldwin CTR3(KTR_LOCK, 4069ed346baSBosko Milekic "_mtx_lock_sleep: p %p free from blocked on [%p] %s", 407b40ce416SJulian Elischer td, m, m->mtx_object.lo_name); 4089ed346baSBosko Milekic 4099ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 41036412d79SJohn Baldwin } 4119ed346baSBosko Milekic 41236412d79SJohn Baldwin return; 4139ed346baSBosko Milekic } 4149ed346baSBosko Milekic 4159ed346baSBosko Milekic /* 4169ed346baSBosko Milekic * _mtx_lock_spin: the tougher part of acquiring an MTX_SPIN lock. 4179ed346baSBosko Milekic * 4189ed346baSBosko Milekic * This is only called if we need to actually spin for the lock. Recursion 4199ed346baSBosko Milekic * is handled inline. 4209ed346baSBosko Milekic */ 4219ed346baSBosko Milekic void 4227e1f6dfeSJohn Baldwin _mtx_lock_spin(struct mtx *m, int opts, const char *file, int line) 42336412d79SJohn Baldwin { 42436412d79SJohn Baldwin int i = 0; 42536412d79SJohn Baldwin 42619284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4275746a1d8SBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m); 4289ed346baSBosko Milekic 42936412d79SJohn Baldwin for (;;) { 430b40ce416SJulian Elischer if (_obtain_lock(m, curthread)) 43136412d79SJohn Baldwin break; 4329ed346baSBosko Milekic 4337141f2adSJohn Baldwin /* Give interrupts a chance while we spin. */ 4347e1f6dfeSJohn Baldwin critical_exit(); 43536412d79SJohn Baldwin while (m->mtx_lock != MTX_UNOWNED) { 43636412d79SJohn Baldwin if (i++ < 1000000) 43736412d79SJohn Baldwin continue; 43836412d79SJohn Baldwin if (i++ < 6000000) 43936412d79SJohn Baldwin DELAY(1); 44036412d79SJohn Baldwin #ifdef DDB 44136412d79SJohn Baldwin else if (!db_active) 44236412d79SJohn Baldwin #else 44336412d79SJohn Baldwin else 44436412d79SJohn Baldwin #endif 4459ed346baSBosko Milekic panic("spin lock %s held by %p for > 5 seconds", 44619284646SJohn Baldwin m->mtx_object.lo_name, (void *)m->mtx_lock); 44736412d79SJohn Baldwin } 4487e1f6dfeSJohn Baldwin critical_enter(); 44936412d79SJohn Baldwin } 45036412d79SJohn Baldwin 45119284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4529ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m); 4539ed346baSBosko Milekic 45436412d79SJohn Baldwin return; 45536412d79SJohn Baldwin } 45636412d79SJohn Baldwin 4579ed346baSBosko Milekic /* 4589ed346baSBosko Milekic * _mtx_unlock_sleep: the tougher part of releasing an MTX_DEF lock. 4599ed346baSBosko Milekic * 4609ed346baSBosko Milekic * We are only called here if the lock is recursed or contested (i.e. we 4619ed346baSBosko Milekic * need to wake up a blocked thread). 4629ed346baSBosko Milekic */ 46336412d79SJohn Baldwin void 4649ed346baSBosko Milekic _mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line) 46536412d79SJohn Baldwin { 466b40ce416SJulian Elischer struct thread *td, *td1; 46736412d79SJohn Baldwin struct mtx *m1; 46836412d79SJohn Baldwin int pri; 469b40ce416SJulian Elischer struct ksegrp *kg; 47036412d79SJohn Baldwin 471b40ce416SJulian Elischer td = curthread; 472b40ce416SJulian Elischer kg = td->td_ksegrp; 4739ed346baSBosko Milekic 47408812b39SBosko Milekic if (mtx_recursed(m)) { 47536412d79SJohn Baldwin if (--(m->mtx_recurse) == 0) 47608812b39SBosko Milekic atomic_clear_ptr(&m->mtx_lock, MTX_RECURSED); 47719284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4789ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p unrecurse", m); 47936412d79SJohn Baldwin return; 48036412d79SJohn Baldwin } 4819ed346baSBosko Milekic 4829ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 48319284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4849ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p contested", m); 4859ed346baSBosko Milekic 486b40ce416SJulian Elischer td1 = TAILQ_FIRST(&m->mtx_blocked); 487b40ce416SJulian Elischer MPASS(td->td_proc->p_magic == P_MAGIC); 488b40ce416SJulian Elischer MPASS(td1->td_proc->p_magic == P_MAGIC); 4899ed346baSBosko Milekic 490b40ce416SJulian Elischer TAILQ_REMOVE(&m->mtx_blocked, td1, td_blkq); 4919ed346baSBosko Milekic 49236412d79SJohn Baldwin if (TAILQ_EMPTY(&m->mtx_blocked)) { 49336412d79SJohn Baldwin LIST_REMOVE(m, mtx_contested); 49436412d79SJohn Baldwin _release_lock_quick(m); 49519284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 4969ed346baSBosko Milekic CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p not held", m); 49736412d79SJohn Baldwin } else 4989ed346baSBosko Milekic atomic_store_rel_ptr(&m->mtx_lock, (void *)MTX_CONTESTED); 4999ed346baSBosko Milekic 500d5a08a60SJake Burkholder pri = PRI_MAX; 501b40ce416SJulian Elischer LIST_FOREACH(m1, &td->td_contested, mtx_contested) { 502b40ce416SJulian Elischer int cp = TAILQ_FIRST(&m1->mtx_blocked)->td_ksegrp->kg_pri.pri_level; 50336412d79SJohn Baldwin if (cp < pri) 50436412d79SJohn Baldwin pri = cp; 50536412d79SJohn Baldwin } 5069ed346baSBosko Milekic 507b40ce416SJulian Elischer if (pri > kg->kg_pri.pri_native) 508b40ce416SJulian Elischer pri = kg->kg_pri.pri_native; 509b40ce416SJulian Elischer SET_PRIO(td, pri); 5109ed346baSBosko Milekic 51119284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 5129ed346baSBosko Milekic CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p contested setrunqueue %p", 513b40ce416SJulian Elischer m, td1); 5149ed346baSBosko Milekic 515b40ce416SJulian Elischer td1->td_blocked = NULL; 516b40ce416SJulian Elischer td1->td_proc->p_stat = SRUN; 517b40ce416SJulian Elischer setrunqueue(td1); 5189ed346baSBosko Milekic 519c86b6ff5SJohn Baldwin if (td->td_critnest == 1 && td1->td_ksegrp->kg_pri.pri_level < pri) { 52036412d79SJohn Baldwin #ifdef notyet 521b40ce416SJulian Elischer if (td->td_ithd != NULL) { 522b40ce416SJulian Elischer struct ithd *it = td->td_ithd; 52336412d79SJohn Baldwin 52436412d79SJohn Baldwin if (it->it_interrupted) { 52519284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 52636412d79SJohn Baldwin CTR2(KTR_LOCK, 52715ec816aSJohn Baldwin "_mtx_unlock_sleep: %p interrupted %p", 52836412d79SJohn Baldwin it, it->it_interrupted); 52936412d79SJohn Baldwin intr_thd_fixup(it); 53036412d79SJohn Baldwin } 53136412d79SJohn Baldwin } 53236412d79SJohn Baldwin #endif 533b40ce416SJulian Elischer setrunqueue(td); 53419284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 535562e4ffeSJohn Baldwin CTR2(KTR_LOCK, 5369ed346baSBosko Milekic "_mtx_unlock_sleep: %p switching out lock=%p", m, 5379ed346baSBosko Milekic (void *)m->mtx_lock); 5389ed346baSBosko Milekic 539b40ce416SJulian Elischer td->td_proc->p_stats->p_ru.ru_nivcsw++; 54036412d79SJohn Baldwin mi_switch(); 54119284646SJohn Baldwin if (LOCK_LOG_TEST(&m->mtx_object, opts)) 5429ed346baSBosko Milekic CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p resuming lock=%p", 54331271627SJohn Baldwin m, (void *)m->mtx_lock); 54436412d79SJohn Baldwin } 54536412d79SJohn Baldwin 5469ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 5479ed346baSBosko Milekic 5489ed346baSBosko Milekic return; 5499ed346baSBosko Milekic } 5509ed346baSBosko Milekic 5519ed346baSBosko Milekic /* 5529ed346baSBosko Milekic * All the unlocking of MTX_SPIN locks is done inline. 5539ed346baSBosko Milekic * See the _rel_spin_lock() macro for the details. 5549ed346baSBosko Milekic */ 5559ed346baSBosko Milekic 5569ed346baSBosko Milekic /* 55715ec816aSJohn Baldwin * The backing function for the INVARIANTS-enabled mtx_assert() 5589ed346baSBosko Milekic */ 5591103f3b0SJohn Baldwin #ifdef INVARIANT_SUPPORT 5600cde2e34SJason Evans void 56156771ca7SJason Evans _mtx_assert(struct mtx *m, int what, const char *file, int line) 5620cde2e34SJason Evans { 5635cb0fbe4SJohn Baldwin 5645cb0fbe4SJohn Baldwin if (panicstr != NULL) 5655cb0fbe4SJohn Baldwin return; 566a10f4966SJake Burkholder switch (what) { 5670cde2e34SJason Evans case MA_OWNED: 5680cde2e34SJason Evans case MA_OWNED | MA_RECURSED: 5690cde2e34SJason Evans case MA_OWNED | MA_NOTRECURSED: 570a10f4966SJake Burkholder if (!mtx_owned(m)) 5710cde2e34SJason Evans panic("mutex %s not owned at %s:%d", 57219284646SJohn Baldwin m->mtx_object.lo_name, file, line); 573a10f4966SJake Burkholder if (mtx_recursed(m)) { 574a10f4966SJake Burkholder if ((what & MA_NOTRECURSED) != 0) 5750cde2e34SJason Evans panic("mutex %s recursed at %s:%d", 57619284646SJohn Baldwin m->mtx_object.lo_name, file, line); 577a10f4966SJake Burkholder } else if ((what & MA_RECURSED) != 0) { 5780cde2e34SJason Evans panic("mutex %s unrecursed at %s:%d", 57919284646SJohn Baldwin m->mtx_object.lo_name, file, line); 5800cde2e34SJason Evans } 5810cde2e34SJason Evans break; 5820cde2e34SJason Evans case MA_NOTOWNED: 583a10f4966SJake Burkholder if (mtx_owned(m)) 5840cde2e34SJason Evans panic("mutex %s owned at %s:%d", 58519284646SJohn Baldwin m->mtx_object.lo_name, file, line); 5860cde2e34SJason Evans break; 5870cde2e34SJason Evans default: 58856771ca7SJason Evans panic("unknown mtx_assert at %s:%d", file, line); 5890cde2e34SJason Evans } 5900cde2e34SJason Evans } 5910cde2e34SJason Evans #endif 5920cde2e34SJason Evans 5939ed346baSBosko Milekic /* 5949ed346baSBosko Milekic * The MUTEX_DEBUG-enabled mtx_validate() 59519284646SJohn Baldwin * 59619284646SJohn Baldwin * Most of these checks have been moved off into the LO_INITIALIZED flag 59719284646SJohn Baldwin * maintained by the witness code. 5989ed346baSBosko Milekic */ 59936412d79SJohn Baldwin #ifdef MUTEX_DEBUG 60036412d79SJohn Baldwin 60119284646SJohn Baldwin void mtx_validate __P((struct mtx *)); 60236412d79SJohn Baldwin 60319284646SJohn Baldwin void 60419284646SJohn Baldwin mtx_validate(struct mtx *m) 60536412d79SJohn Baldwin { 60636412d79SJohn Baldwin 60736412d79SJohn Baldwin /* 60836412d79SJohn Baldwin * XXX - When kernacc() is fixed on the alpha to handle K0_SEG memory properly 60936412d79SJohn Baldwin * we can re-enable the kernacc() checks. 61036412d79SJohn Baldwin */ 61136412d79SJohn Baldwin #ifndef __alpha__ 61276dcbd6fSBosko Milekic /* 61376dcbd6fSBosko Milekic * Can't call kernacc() from early init386(), especially when 61476dcbd6fSBosko Milekic * initializing Giant mutex, because some stuff in kernacc() 61576dcbd6fSBosko Milekic * requires Giant itself. 61676dcbd6fSBosko Milekic */ 617ab07087eSBosko Milekic if (!cold) 618ab07087eSBosko Milekic if (!kernacc((caddr_t)m, sizeof(m), 619ab07087eSBosko Milekic VM_PROT_READ | VM_PROT_WRITE)) 62019284646SJohn Baldwin panic("Can't read and write to mutex %p", m); 62136412d79SJohn Baldwin #endif 62236412d79SJohn Baldwin } 62336412d79SJohn Baldwin #endif 62436412d79SJohn Baldwin 6259ed346baSBosko Milekic /* 6269ed346baSBosko Milekic * Mutex initialization routine; initialize lock `m' of type contained in 6279ed346baSBosko Milekic * `opts' with options contained in `opts' and description `description.' 6289ed346baSBosko Milekic */ 62936412d79SJohn Baldwin void 6309ed346baSBosko Milekic mtx_init(struct mtx *m, const char *description, int opts) 63136412d79SJohn Baldwin { 63219284646SJohn Baldwin struct lock_object *lock; 6339ed346baSBosko Milekic 63419284646SJohn Baldwin MPASS((opts & ~(MTX_SPIN | MTX_QUIET | MTX_RECURSE | 63519284646SJohn Baldwin MTX_SLEEPABLE | MTX_NOWITNESS)) == 0); 6369ed346baSBosko Milekic 63736412d79SJohn Baldwin #ifdef MUTEX_DEBUG 6389ed346baSBosko Milekic /* Diagnostic and error correction */ 63919284646SJohn Baldwin mtx_validate(m); 6406936206eSJohn Baldwin #endif 64136412d79SJohn Baldwin 64219284646SJohn Baldwin lock = &m->mtx_object; 6437ada5876SJohn Baldwin KASSERT((lock->lo_flags & LO_INITIALIZED) == 0, 6447ada5876SJohn Baldwin ("mutex %s %p already initialized", description, m)); 6457ada5876SJohn Baldwin bzero(m, sizeof(*m)); 64619284646SJohn Baldwin if (opts & MTX_SPIN) 64719284646SJohn Baldwin lock->lo_class = &lock_class_mtx_spin; 64819284646SJohn Baldwin else 64919284646SJohn Baldwin lock->lo_class = &lock_class_mtx_sleep; 65019284646SJohn Baldwin lock->lo_name = description; 65119284646SJohn Baldwin if (opts & MTX_QUIET) 65219284646SJohn Baldwin lock->lo_flags = LO_QUIET; 65319284646SJohn Baldwin if (opts & MTX_RECURSE) 65419284646SJohn Baldwin lock->lo_flags |= LO_RECURSABLE; 65519284646SJohn Baldwin if (opts & MTX_SLEEPABLE) 65619284646SJohn Baldwin lock->lo_flags |= LO_SLEEPABLE; 65719284646SJohn Baldwin if ((opts & MTX_NOWITNESS) == 0) 65819284646SJohn Baldwin lock->lo_flags |= LO_WITNESS; 65919284646SJohn Baldwin 66019284646SJohn Baldwin m->mtx_lock = MTX_UNOWNED; 66136412d79SJohn Baldwin TAILQ_INIT(&m->mtx_blocked); 6629ed346baSBosko Milekic 66319284646SJohn Baldwin LOCK_LOG_INIT(lock, opts); 664d1c1b841SJason Evans 66519284646SJohn Baldwin WITNESS_INIT(lock); 66636412d79SJohn Baldwin } 66736412d79SJohn Baldwin 6689ed346baSBosko Milekic /* 66919284646SJohn Baldwin * Remove lock `m' from all_mtx queue. We don't allow MTX_QUIET to be 67019284646SJohn Baldwin * passed in as a flag here because if the corresponding mtx_init() was 67119284646SJohn Baldwin * called with MTX_QUIET set, then it will already be set in the mutex's 67219284646SJohn Baldwin * flags. 6739ed346baSBosko Milekic */ 67436412d79SJohn Baldwin void 67536412d79SJohn Baldwin mtx_destroy(struct mtx *m) 67636412d79SJohn Baldwin { 67736412d79SJohn Baldwin 67819284646SJohn Baldwin LOCK_LOG_DESTROY(&m->mtx_object, 0); 6799ed346baSBosko Milekic 68019284646SJohn Baldwin if (!mtx_owned(m)) 68119284646SJohn Baldwin MPASS(mtx_unowned(m)); 68219284646SJohn Baldwin else { 68308812b39SBosko Milekic MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0); 6849ed346baSBosko Milekic 68519284646SJohn Baldwin /* Tell witness this isn't locked to make it happy. */ 686c86b6ff5SJohn Baldwin WITNESS_UNLOCK(&m->mtx_object, LOP_EXCLUSIVE, __FILE__, 687c86b6ff5SJohn Baldwin __LINE__); 68836412d79SJohn Baldwin } 6890384fff8SJason Evans 69019284646SJohn Baldwin WITNESS_DESTROY(&m->mtx_object); 6910384fff8SJason Evans } 692d23f5958SMatthew Dillon 693d23f5958SMatthew Dillon /* 694d23f5958SMatthew Dillon * Encapsulated Giant mutex routines. These routines provide encapsulation 695d23f5958SMatthew Dillon * control for the Giant mutex, allowing sysctls to be used to turn on and 696d23f5958SMatthew Dillon * off Giant around certain subsystems. The default value for the sysctls 697d23f5958SMatthew Dillon * are set to what developers believe is stable and working in regards to 698d23f5958SMatthew Dillon * the Giant pushdown. Developers should not turn off Giant via these 699d23f5958SMatthew Dillon * sysctls unless they know what they are doing. 700d23f5958SMatthew Dillon * 701d23f5958SMatthew Dillon * Callers of mtx_lock_giant() are expected to pass the return value to an 702d23f5958SMatthew Dillon * accompanying mtx_unlock_giant() later on. If multiple subsystems are 703d23f5958SMatthew Dillon * effected by a Giant wrap, all related sysctl variables must be zero for 704d23f5958SMatthew Dillon * the subsystem call to operate without Giant (as determined by the caller). 705d23f5958SMatthew Dillon */ 706d23f5958SMatthew Dillon 707d23f5958SMatthew Dillon SYSCTL_NODE(_kern, OID_AUTO, giant, CTLFLAG_RD, NULL, "Giant mutex manipulation"); 708d23f5958SMatthew Dillon 709d23f5958SMatthew Dillon static int kern_giant_all = 0; 710d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, all, CTLFLAG_RW, &kern_giant_all, 0, ""); 711d23f5958SMatthew Dillon 712d23f5958SMatthew Dillon int kern_giant_proc = 1; /* Giant around PROC locks */ 713d23f5958SMatthew Dillon int kern_giant_file = 1; /* Giant around struct file & filedesc */ 714d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, proc, CTLFLAG_RW, &kern_giant_proc, 0, ""); 715d23f5958SMatthew Dillon SYSCTL_INT(_kern_giant, OID_AUTO, file, CTLFLAG_RW, &kern_giant_file, 0, ""); 716d23f5958SMatthew Dillon 717d23f5958SMatthew Dillon int 718d23f5958SMatthew Dillon mtx_lock_giant(int sysctlvar) 719d23f5958SMatthew Dillon { 720d23f5958SMatthew Dillon if (sysctlvar || kern_giant_all) { 721d23f5958SMatthew Dillon mtx_lock(&Giant); 722d23f5958SMatthew Dillon return(1); 723d23f5958SMatthew Dillon } 724d23f5958SMatthew Dillon return(0); 725d23f5958SMatthew Dillon } 726d23f5958SMatthew Dillon 727d23f5958SMatthew Dillon void 728d23f5958SMatthew Dillon mtx_unlock_giant(int s) 729d23f5958SMatthew Dillon { 730d23f5958SMatthew Dillon if (s) 731d23f5958SMatthew Dillon mtx_unlock(&Giant); 732d23f5958SMatthew Dillon } 733d23f5958SMatthew Dillon 734