subr_witness.c revision 71287
1/*- 2 * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Berkeley Software Design Inc's name may not be used to endorse or 13 * promote products derived from this software without specific prior 14 * written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * from BSDI $Id: mutex_witness.c,v 1.1.2.20 2000/04/27 03:10:27 cp Exp $ 29 * and BSDI $Id: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $ 30 * $FreeBSD: head/sys/kern/subr_witness.c 71287 2001-01-20 02:30:58Z jake $ 31 */ 32 33/* 34 * Main Entry: witness 35 * Pronunciation: 'wit-n&s 36 * Function: noun 37 * Etymology: Middle English witnesse, from Old English witnes knowledge, 38 * testimony, witness, from 2wit 39 * Date: before 12th century 40 * 1 : attestation of a fact or event : TESTIMONY 41 * 2 : one that gives evidence; specifically : one who testifies in 42 * a cause or before a judicial tribunal 43 * 3 : one asked to be present at a transaction so as to be able to 44 * testify to its having taken place 45 * 4 : one who has personal knowledge of something 46 * 5 a : something serving as evidence or proof : SIGN 47 * b : public affirmation by word or example of usually 48 * religious faith or conviction <the heroic witness to divine 49 * life -- Pilot> 50 * 6 capitalized : a member of the Jehovah's Witnesses 51 */ 52 53#include "opt_ddb.h" 54#include "opt_witness.h" 55 56/* 57 * Cause non-inlined mtx_*() to be compiled. 58 * Must be defined early because other system headers may include mutex.h. 59 */ 60#define _KERN_MUTEX_C_ 61 62#include <sys/param.h> 63#include <sys/bus.h> 64#include <sys/kernel.h> 65#include <sys/malloc.h> 66#include <sys/proc.h> 67#include <sys/sysctl.h> 68#include <sys/systm.h> 69#include <sys/vmmeter.h> 70#include <sys/ktr.h> 71 72#include <machine/atomic.h> 73#include <machine/bus.h> 74#include <machine/clock.h> 75#include <machine/cpu.h> 76 77#include <ddb/ddb.h> 78 79#include <vm/vm.h> 80#include <vm/vm_extern.h> 81 82#include <sys/mutex.h> 83 84/* 85 * Machine independent bits of the mutex implementation 86 */ 87/* All mutexes in system (used for debug/panic) */ 88#ifdef WITNESS 89static struct mtx_debug all_mtx_debug = { NULL, {NULL, NULL}, NULL, 0, 90 "All mutexes queue head" }; 91static struct mtx all_mtx = { MTX_UNOWNED, 0, 0, &all_mtx_debug, 92 TAILQ_HEAD_INITIALIZER(all_mtx.mtx_blocked), 93 { NULL, NULL }, &all_mtx, &all_mtx }; 94#else /* WITNESS */ 95static struct mtx all_mtx = { MTX_UNOWNED, 0, 0, "All mutexes queue head", 96 TAILQ_HEAD_INITIALIZER(all_mtx.mtx_blocked), 97 { NULL, NULL }, &all_mtx, &all_mtx }; 98#endif /* WITNESS */ 99 100static int mtx_cur_cnt; 101static int mtx_max_cnt; 102 103static void propagate_priority(struct proc *); 104 105#define mtx_unowned(m) ((m)->mtx_lock == MTX_UNOWNED) 106#define mtx_owner(m) (mtx_unowned(m) ? NULL \ 107 : (struct proc *)((m)->mtx_lock & MTX_FLAGMASK)) 108 109#define RETIP(x) *(((uintptr_t *)(&x)) - 1) 110#define SET_PRIO(p, pri) (p)->p_priority = (pri) 111 112static void 113propagate_priority(struct proc *p) 114{ 115 int pri = p->p_priority; 116 struct mtx *m = p->p_blocked; 117 118 mtx_assert(&sched_lock, MA_OWNED); 119 for (;;) { 120 struct proc *p1; 121 122 p = mtx_owner(m); 123 124 if (p == NULL) { 125 /* 126 * This really isn't quite right. Really 127 * ought to bump priority of process that 128 * next acquires the mutex. 129 */ 130 MPASS(m->mtx_lock == MTX_CONTESTED); 131 return; 132 } 133 MPASS(p->p_magic == P_MAGIC); 134 KASSERT(p->p_stat != SSLEEP, ("sleeping process owns a mutex")); 135 if (p->p_priority <= pri) 136 return; 137 138 /* 139 * Bump this process' priority. 140 */ 141 SET_PRIO(p, pri); 142 143 /* 144 * If lock holder is actually running, just bump priority. 145 */ 146#ifdef SMP 147 /* 148 * For SMP, we can check the p_oncpu field to see if we are 149 * running. 150 */ 151 if (p->p_oncpu != 0xff) { 152 MPASS(p->p_stat == SRUN || p->p_stat == SZOMB); 153 return; 154 } 155#else 156 /* 157 * For UP, we check to see if p is curproc (this shouldn't 158 * ever happen however as it would mean we are in a deadlock.) 159 */ 160 if (p == curproc) { 161 panic("Deadlock detected"); 162 return; 163 } 164#endif 165 /* 166 * If on run queue move to new run queue, and 167 * quit. 168 */ 169 if (p->p_stat == SRUN) { 170 printf("XXX: moving process %d(%s) to a new run queue\n", 171 p->p_pid, p->p_comm); 172 MPASS(p->p_blocked == NULL); 173 remrunqueue(p); 174 setrunqueue(p); 175 return; 176 } 177 178 /* 179 * If we aren't blocked on a mutex, we should be. 180 */ 181 KASSERT(p->p_stat == SMTX, ( 182 "process %d(%s):%d holds %s but isn't blocked on a mutex\n", 183 p->p_pid, p->p_comm, p->p_stat, 184 m->mtx_description)); 185 186 /* 187 * Pick up the mutex that p is blocked on. 188 */ 189 m = p->p_blocked; 190 MPASS(m != NULL); 191 192 printf("XXX: process %d(%s) is blocked on %s\n", p->p_pid, 193 p->p_comm, m->mtx_description); 194 /* 195 * Check if the proc needs to be moved up on 196 * the blocked chain 197 */ 198 if (p == TAILQ_FIRST(&m->mtx_blocked)) { 199 printf("XXX: process at head of run queue\n"); 200 continue; 201 } 202 p1 = TAILQ_PREV(p, rq, p_procq); 203 if (p1->p_priority <= pri) { 204 printf( 205 "XXX: previous process %d(%s) has higher priority\n", 206 p->p_pid, p->p_comm); 207 continue; 208 } 209 210 /* 211 * Remove proc from blocked chain and determine where 212 * it should be moved up to. Since we know that p1 has 213 * a lower priority than p, we know that at least one 214 * process in the chain has a lower priority and that 215 * p1 will thus not be NULL after the loop. 216 */ 217 TAILQ_REMOVE(&m->mtx_blocked, p, p_procq); 218 TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) { 219 MPASS(p1->p_magic == P_MAGIC); 220 if (p1->p_priority > pri) 221 break; 222 } 223 MPASS(p1 != NULL); 224 TAILQ_INSERT_BEFORE(p1, p, p_procq); 225 CTR4(KTR_LOCK, 226 "propagate_priority: p 0x%p moved before 0x%p on [0x%p] %s", 227 p, p1, m, m->mtx_description); 228 } 229} 230 231void 232mtx_enter_hard(struct mtx *m, int type, int saveintr) 233{ 234 struct proc *p = CURPROC; 235 236 KASSERT(p != NULL, ("curproc is NULL in mutex")); 237 238 switch (type) { 239 case MTX_DEF: 240 if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)p) { 241 m->mtx_recurse++; 242 atomic_set_ptr(&m->mtx_lock, MTX_RECURSED); 243 if ((type & MTX_QUIET) == 0) 244 CTR1(KTR_LOCK, "mtx_enter: 0x%p recurse", m); 245 return; 246 } 247 if ((type & MTX_QUIET) == 0) 248 CTR3(KTR_LOCK, 249 "mtx_enter: 0x%p contested (lock=%p) [0x%p]", 250 m, (void *)m->mtx_lock, (void *)RETIP(m)); 251 252 /* 253 * Save our priority. Even though p_nativepri is protected 254 * by sched_lock, we don't obtain it here as it can be 255 * expensive. Since this is the only place p_nativepri is 256 * set, and since two CPUs will not be executing the same 257 * process concurrently, we know that no other CPU is going 258 * to be messing with this. Also, p_nativepri is only read 259 * when we are blocked on a mutex, so that can't be happening 260 * right now either. 261 */ 262 p->p_nativepri = p->p_priority; 263 while (!_obtain_lock(m, p)) { 264 uintptr_t v; 265 struct proc *p1; 266 267 mtx_enter(&sched_lock, MTX_SPIN | MTX_RLIKELY); 268 /* 269 * check if the lock has been released while 270 * waiting for the schedlock. 271 */ 272 if ((v = m->mtx_lock) == MTX_UNOWNED) { 273 mtx_exit(&sched_lock, MTX_SPIN); 274 continue; 275 } 276 /* 277 * The mutex was marked contested on release. This 278 * means that there are processes blocked on it. 279 */ 280 if (v == MTX_CONTESTED) { 281 p1 = TAILQ_FIRST(&m->mtx_blocked); 282 KASSERT(p1 != NULL, ("contested mutex has no contesters")); 283 KASSERT(p != NULL, ("curproc is NULL for contested mutex")); 284 m->mtx_lock = (uintptr_t)p | MTX_CONTESTED; 285 if (p1->p_priority < p->p_priority) { 286 SET_PRIO(p, p1->p_priority); 287 } 288 mtx_exit(&sched_lock, MTX_SPIN); 289 return; 290 } 291 /* 292 * If the mutex isn't already contested and 293 * a failure occurs setting the contested bit the 294 * mutex was either release or the 295 * state of the RECURSION bit changed. 296 */ 297 if ((v & MTX_CONTESTED) == 0 && 298 !atomic_cmpset_ptr(&m->mtx_lock, (void *)v, 299 (void *)(v | MTX_CONTESTED))) { 300 mtx_exit(&sched_lock, MTX_SPIN); 301 continue; 302 } 303 304 /* We definitely have to sleep for this lock */ 305 mtx_assert(m, MA_NOTOWNED); 306 307#ifdef notyet 308 /* 309 * If we're borrowing an interrupted thread's VM 310 * context must clean up before going to sleep. 311 */ 312 if (p->p_flag & (P_ITHD | P_SITHD)) { 313 ithd_t *it = (ithd_t *)p; 314 315 if (it->it_interrupted) { 316 if ((type & MTX_QUIET) == 0) 317 CTR2(KTR_LOCK, 318 "mtx_enter: 0x%x interrupted 0x%x", 319 it, it->it_interrupted); 320 intr_thd_fixup(it); 321 } 322 } 323#endif 324 325 /* Put us on the list of procs blocked on this mutex */ 326 if (TAILQ_EMPTY(&m->mtx_blocked)) { 327 p1 = (struct proc *)(m->mtx_lock & 328 MTX_FLAGMASK); 329 LIST_INSERT_HEAD(&p1->p_contested, m, 330 mtx_contested); 331 TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq); 332 } else { 333 TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) 334 if (p1->p_priority > p->p_priority) 335 break; 336 if (p1) 337 TAILQ_INSERT_BEFORE(p1, p, p_procq); 338 else 339 TAILQ_INSERT_TAIL(&m->mtx_blocked, p, 340 p_procq); 341 } 342 343 p->p_blocked = m; /* Who we're blocked on */ 344 p->p_mtxname = m->mtx_description; 345 p->p_stat = SMTX; 346#if 0 347 propagate_priority(p); 348#endif 349 if ((type & MTX_QUIET) == 0) 350 CTR3(KTR_LOCK, 351 "mtx_enter: p 0x%p blocked on [0x%p] %s", 352 p, m, m->mtx_description); 353 mi_switch(); 354 if ((type & MTX_QUIET) == 0) 355 CTR3(KTR_LOCK, 356 "mtx_enter: p 0x%p free from blocked on [0x%p] %s", 357 p, m, m->mtx_description); 358 mtx_exit(&sched_lock, MTX_SPIN); 359 } 360 return; 361 case MTX_SPIN: 362 case MTX_SPIN | MTX_FIRST: 363 case MTX_SPIN | MTX_TOPHALF: 364 { 365 int i = 0; 366 367 if (m->mtx_lock == (uintptr_t)p) { 368 m->mtx_recurse++; 369 return; 370 } 371 if ((type & MTX_QUIET) == 0) 372 CTR1(KTR_LOCK, "mtx_enter: %p spinning", m); 373 for (;;) { 374 if (_obtain_lock(m, p)) 375 break; 376 while (m->mtx_lock != MTX_UNOWNED) { 377 if (i++ < 1000000) 378 continue; 379 if (i++ < 6000000) 380 DELAY (1); 381#ifdef DDB 382 else if (!db_active) 383#else 384 else 385#endif 386 panic( 387 "spin lock %s held by 0x%p for > 5 seconds", 388 m->mtx_description, 389 (void *)m->mtx_lock); 390 } 391 } 392 393#ifdef MUTEX_DEBUG 394 if (type != MTX_SPIN) 395 m->mtx_saveintr = 0xbeefface; 396 else 397#endif 398 m->mtx_saveintr = saveintr; 399 if ((type & MTX_QUIET) == 0) 400 CTR1(KTR_LOCK, "mtx_enter: 0x%p spin done", m); 401 return; 402 } 403 } 404} 405 406void 407mtx_exit_hard(struct mtx *m, int type) 408{ 409 struct proc *p, *p1; 410 struct mtx *m1; 411 int pri; 412 413 p = CURPROC; 414 switch (type) { 415 case MTX_DEF: 416 case MTX_DEF | MTX_NOSWITCH: 417 if (mtx_recursed(m)) { 418 if (--(m->mtx_recurse) == 0) 419 atomic_clear_ptr(&m->mtx_lock, MTX_RECURSED); 420 if ((type & MTX_QUIET) == 0) 421 CTR1(KTR_LOCK, "mtx_exit: 0x%p unrecurse", m); 422 return; 423 } 424 mtx_enter(&sched_lock, MTX_SPIN); 425 if ((type & MTX_QUIET) == 0) 426 CTR1(KTR_LOCK, "mtx_exit: 0x%p contested", m); 427 p1 = TAILQ_FIRST(&m->mtx_blocked); 428 MPASS(p->p_magic == P_MAGIC); 429 MPASS(p1->p_magic == P_MAGIC); 430 TAILQ_REMOVE(&m->mtx_blocked, p1, p_procq); 431 if (TAILQ_EMPTY(&m->mtx_blocked)) { 432 LIST_REMOVE(m, mtx_contested); 433 _release_lock_quick(m); 434 if ((type & MTX_QUIET) == 0) 435 CTR1(KTR_LOCK, "mtx_exit: 0x%p not held", m); 436 } else 437 atomic_store_rel_ptr(&m->mtx_lock, 438 (void *)MTX_CONTESTED); 439 pri = MAXPRI; 440 LIST_FOREACH(m1, &p->p_contested, mtx_contested) { 441 int cp = TAILQ_FIRST(&m1->mtx_blocked)->p_priority; 442 if (cp < pri) 443 pri = cp; 444 } 445 if (pri > p->p_nativepri) 446 pri = p->p_nativepri; 447 SET_PRIO(p, pri); 448 if ((type & MTX_QUIET) == 0) 449 CTR2(KTR_LOCK, 450 "mtx_exit: 0x%p contested setrunqueue 0x%p", m, p1); 451 p1->p_blocked = NULL; 452 p1->p_mtxname = NULL; 453 p1->p_stat = SRUN; 454 setrunqueue(p1); 455 if ((type & MTX_NOSWITCH) == 0 && p1->p_priority < pri) { 456#ifdef notyet 457 if (p->p_flag & (P_ITHD | P_SITHD)) { 458 ithd_t *it = (ithd_t *)p; 459 460 if (it->it_interrupted) { 461 if ((type & MTX_QUIET) == 0) 462 CTR2(KTR_LOCK, 463 "mtx_exit: 0x%x interruped 0x%x", 464 it, it->it_interrupted); 465 intr_thd_fixup(it); 466 } 467 } 468#endif 469 setrunqueue(p); 470 if ((type & MTX_QUIET) == 0) 471 CTR2(KTR_LOCK, 472 "mtx_exit: 0x%p switching out lock=0x%p", 473 m, (void *)m->mtx_lock); 474 mi_switch(); 475 if ((type & MTX_QUIET) == 0) 476 CTR2(KTR_LOCK, 477 "mtx_exit: 0x%p resuming lock=0x%p", 478 m, (void *)m->mtx_lock); 479 } 480 mtx_exit(&sched_lock, MTX_SPIN); 481 break; 482 case MTX_SPIN: 483 case MTX_SPIN | MTX_FIRST: 484 if (mtx_recursed(m)) { 485 m->mtx_recurse--; 486 return; 487 } 488 MPASS(mtx_owned(m)); 489 _release_lock_quick(m); 490 if (type & MTX_FIRST) 491 enable_intr(); /* XXX is this kosher? */ 492 else { 493 MPASS(m->mtx_saveintr != 0xbeefface); 494 restore_intr(m->mtx_saveintr); 495 } 496 break; 497 case MTX_SPIN | MTX_TOPHALF: 498 if (mtx_recursed(m)) { 499 m->mtx_recurse--; 500 return; 501 } 502 MPASS(mtx_owned(m)); 503 _release_lock_quick(m); 504 break; 505 default: 506 panic("mtx_exit_hard: unsupported type 0x%x\n", type); 507 } 508} 509 510#define MV_DESTROY 0 /* validate before destory */ 511#define MV_INIT 1 /* validate before init */ 512 513#ifdef MUTEX_DEBUG 514 515int mtx_validate __P((struct mtx *, int)); 516 517int 518mtx_validate(struct mtx *m, int when) 519{ 520 struct mtx *mp; 521 int i; 522 int retval = 0; 523 524 if (m == &all_mtx || cold) 525 return 0; 526 527 mtx_enter(&all_mtx, MTX_DEF); 528/* 529 * XXX - When kernacc() is fixed on the alpha to handle K0_SEG memory properly 530 * we can re-enable the kernacc() checks. 531 */ 532#ifndef __alpha__ 533 MPASS(kernacc((caddr_t)all_mtx.mtx_next, sizeof(uintptr_t), 534 VM_PROT_READ) == 1); 535#endif 536 MPASS(all_mtx.mtx_next->mtx_prev == &all_mtx); 537 for (i = 0, mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) { 538#ifndef __alpha__ 539 if (kernacc((caddr_t)mp->mtx_next, sizeof(uintptr_t), 540 VM_PROT_READ) != 1) { 541 panic("mtx_validate: mp=%p mp->mtx_next=%p", 542 mp, mp->mtx_next); 543 } 544#endif 545 i++; 546 if (i > mtx_cur_cnt) { 547 panic("mtx_validate: too many in chain, known=%d\n", 548 mtx_cur_cnt); 549 } 550 } 551 MPASS(i == mtx_cur_cnt); 552 switch (when) { 553 case MV_DESTROY: 554 for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) 555 if (mp == m) 556 break; 557 MPASS(mp == m); 558 break; 559 case MV_INIT: 560 for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) 561 if (mp == m) { 562 /* 563 * Not good. This mutex already exists. 564 */ 565 printf("re-initing existing mutex %s\n", 566 m->mtx_description); 567 MPASS(m->mtx_lock == MTX_UNOWNED); 568 retval = 1; 569 } 570 } 571 mtx_exit(&all_mtx, MTX_DEF); 572 return (retval); 573} 574#endif 575 576void 577mtx_init(struct mtx *m, const char *t, int flag) 578{ 579#ifdef WITNESS 580 struct mtx_debug *debug; 581#endif 582 583 if ((flag & MTX_QUIET) == 0) 584 CTR2(KTR_LOCK, "mtx_init 0x%p (%s)", m, t); 585#ifdef MUTEX_DEBUG 586 if (mtx_validate(m, MV_INIT)) /* diagnostic and error correction */ 587 return; 588#endif 589#ifdef WITNESS 590 if (flag & MTX_COLD) 591 debug = m->mtx_debug; 592 else 593 debug = NULL; 594 if (debug == NULL) { 595#ifdef DIAGNOSTIC 596 if(cold && bootverbose) 597 printf("malloc'ing mtx_debug while cold for %s\n", t); 598#endif 599 600 /* XXX - should not use DEVBUF */ 601 debug = malloc(sizeof(struct mtx_debug), M_DEVBUF, 602 M_NOWAIT | M_ZERO); 603 MPASS(debug != NULL); 604 } 605#endif 606 bzero((void *)m, sizeof *m); 607 TAILQ_INIT(&m->mtx_blocked); 608#ifdef WITNESS 609 m->mtx_debug = debug; 610#endif 611 m->mtx_description = t; 612 m->mtx_lock = MTX_UNOWNED; 613 /* Put on all mutex queue */ 614 mtx_enter(&all_mtx, MTX_DEF); 615 m->mtx_next = &all_mtx; 616 m->mtx_prev = all_mtx.mtx_prev; 617 m->mtx_prev->mtx_next = m; 618 all_mtx.mtx_prev = m; 619 if (++mtx_cur_cnt > mtx_max_cnt) 620 mtx_max_cnt = mtx_cur_cnt; 621 mtx_exit(&all_mtx, MTX_DEF); 622 witness_init(m, flag); 623} 624 625void 626mtx_destroy(struct mtx *m) 627{ 628 629 CTR2(KTR_LOCK, "mtx_destroy 0x%p (%s)", m, m->mtx_description); 630#ifdef MUTEX_DEBUG 631 if (m->mtx_next == NULL) 632 panic("mtx_destroy: %p (%s) already destroyed", 633 m, m->mtx_description); 634 635 if (!mtx_owned(m)) { 636 MPASS(m->mtx_lock == MTX_UNOWNED); 637 } else { 638 MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0); 639 } 640 mtx_validate(m, MV_DESTROY); /* diagnostic */ 641#endif 642 643#ifdef WITNESS 644 if (m->mtx_witness) 645 witness_destroy(m); 646#endif /* WITNESS */ 647 648 /* Remove from the all mutex queue */ 649 mtx_enter(&all_mtx, MTX_DEF); 650 m->mtx_next->mtx_prev = m->mtx_prev; 651 m->mtx_prev->mtx_next = m->mtx_next; 652#ifdef MUTEX_DEBUG 653 m->mtx_next = m->mtx_prev = NULL; 654#endif 655#ifdef WITNESS 656 free(m->mtx_debug, M_DEVBUF); 657 m->mtx_debug = NULL; 658#endif 659 mtx_cur_cnt--; 660 mtx_exit(&all_mtx, MTX_DEF); 661} 662 663/* 664 * The non-inlined versions of the mtx_*() functions are always built (above), 665 * but the witness code depends on the WITNESS kernel option being specified. 666 */ 667#ifdef WITNESS 668 669#define WITNESS_COUNT 200 670#define WITNESS_NCHILDREN 2 671 672int witness_watch = 1; 673 674struct witness { 675 struct witness *w_next; 676 const char *w_description; 677 const char *w_file; 678 int w_line; 679 struct witness *w_morechildren; 680 u_char w_childcnt; 681 u_char w_Giant_squawked:1; 682 u_char w_other_squawked:1; 683 u_char w_same_squawked:1; 684 u_char w_sleep:1; /* MTX_DEF type mutex. */ 685 u_char w_spin:1; /* MTX_SPIN type mutex. */ 686 u_char w_recurse:1; /* MTX_RECURSE mutex option. */ 687 u_int w_level; 688 struct witness *w_children[WITNESS_NCHILDREN]; 689}; 690 691struct witness_blessed { 692 char *b_lock1; 693 char *b_lock2; 694}; 695 696#ifdef DDB 697/* 698 * When DDB is enabled and witness_ddb is set to 1, it will cause the system to 699 * drop into kdebug() when: 700 * - a lock heirarchy violation occurs 701 * - locks are held when going to sleep. 702 */ 703#ifdef WITNESS_DDB 704int witness_ddb = 1; 705#else 706int witness_ddb = 0; 707#endif 708SYSCTL_INT(_debug, OID_AUTO, witness_ddb, CTLFLAG_RW, &witness_ddb, 0, ""); 709#endif /* DDB */ 710 711#ifdef WITNESS_SKIPSPIN 712int witness_skipspin = 1; 713#else 714int witness_skipspin = 0; 715#endif 716SYSCTL_INT(_debug, OID_AUTO, witness_skipspin, CTLFLAG_RD, &witness_skipspin, 0, 717 ""); 718 719MUTEX_DECLARE(static,w_mtx); 720static struct witness *w_free; 721static struct witness *w_all; 722static int w_inited; 723static int witness_dead; /* fatal error, probably no memory */ 724 725static struct witness w_data[WITNESS_COUNT]; 726 727static struct witness *enroll __P((const char *description, int flag)); 728static int itismychild __P((struct witness *parent, struct witness *child)); 729static void removechild __P((struct witness *parent, struct witness *child)); 730static int isitmychild __P((struct witness *parent, struct witness *child)); 731static int isitmydescendant __P((struct witness *parent, struct witness *child)); 732static int dup_ok __P((struct witness *)); 733static int blessed __P((struct witness *, struct witness *)); 734static void witness_displaydescendants 735 __P((void(*)(const char *fmt, ...), struct witness *)); 736static void witness_leveldescendents __P((struct witness *parent, int level)); 737static void witness_levelall __P((void)); 738static struct witness * witness_get __P((void)); 739static void witness_free __P((struct witness *m)); 740 741 742static char *ignore_list[] = { 743 "witness lock", 744 NULL 745}; 746 747static char *spin_order_list[] = { 748 "sio", 749 "sched lock", 750#ifdef __i386__ 751 "clk", 752#endif 753 "callout", 754 /* 755 * leaf locks 756 */ 757 NULL 758}; 759 760static char *order_list[] = { 761 "uidinfo hash", "uidinfo struct", NULL, 762 NULL 763}; 764 765static char *dup_list[] = { 766 NULL 767}; 768 769static char *sleep_list[] = { 770 "Giant", 771 NULL 772}; 773 774/* 775 * Pairs of locks which have been blessed 776 * Don't complain about order problems with blessed locks 777 */ 778static struct witness_blessed blessed_list[] = { 779}; 780static int blessed_count = sizeof(blessed_list) / sizeof(struct witness_blessed); 781 782void 783witness_init(struct mtx *m, int flag) 784{ 785 m->mtx_witness = enroll(m->mtx_description, flag); 786} 787 788void 789witness_destroy(struct mtx *m) 790{ 791 struct mtx *m1; 792 struct proc *p; 793 p = CURPROC; 794 for ((m1 = LIST_FIRST(&p->p_heldmtx)); m1 != NULL; 795 m1 = LIST_NEXT(m1, mtx_held)) { 796 if (m1 == m) { 797 LIST_REMOVE(m, mtx_held); 798 break; 799 } 800 } 801 return; 802 803} 804 805void 806witness_enter(struct mtx *m, int flags, const char *file, int line) 807{ 808 struct witness *w, *w1; 809 struct mtx *m1; 810 struct proc *p; 811 int i; 812#ifdef DDB 813 int go_into_ddb = 0; 814#endif /* DDB */ 815 816 if (panicstr) 817 return; 818 w = m->mtx_witness; 819 p = CURPROC; 820 821 if (flags & MTX_SPIN) { 822 if (!(w->w_spin)) 823 panic("mutex_enter: MTX_SPIN on MTX_DEF mutex %s @" 824 " %s:%d", m->mtx_description, file, line); 825 if (mtx_recursed(m)) { 826 if (!(w->w_recurse)) 827 panic("mutex_enter: recursion on non-recursive" 828 " mutex %s @ %s:%d", m->mtx_description, 829 file, line); 830 return; 831 } 832 mtx_enter(&w_mtx, MTX_SPIN | MTX_QUIET); 833 i = PCPU_GET(witness_spin_check); 834 if (i != 0 && w->w_level < i) { 835 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 836 panic("mutex_enter(%s:%x, MTX_SPIN) out of order @" 837 " %s:%d already holding %s:%x", 838 m->mtx_description, w->w_level, file, line, 839 spin_order_list[ffs(i)-1], i); 840 } 841 PCPU_SET(witness_spin_check, i | w->w_level); 842 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 843 w->w_file = file; 844 w->w_line = line; 845 m->mtx_line = line; 846 m->mtx_file = file; 847 return; 848 } 849 if (w->w_spin) 850 panic("mutex_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 851 m->mtx_description, file, line); 852 853 if (mtx_recursed(m)) { 854 if (!(w->w_recurse)) 855 panic("mutex_enter: recursion on non-recursive" 856 " mutex %s @ %s:%d", m->mtx_description, 857 file, line); 858 return; 859 } 860 if (witness_dead) 861 goto out; 862 if (cold) 863 goto out; 864 865 if (!mtx_legal2block()) 866 panic("blockable mtx_enter() of %s when not legal @ %s:%d", 867 m->mtx_description, file, line); 868 /* 869 * Is this the first mutex acquired 870 */ 871 if ((m1 = LIST_FIRST(&p->p_heldmtx)) == NULL) 872 goto out; 873 874 if ((w1 = m1->mtx_witness) == w) { 875 if (w->w_same_squawked || dup_ok(w)) 876 goto out; 877 w->w_same_squawked = 1; 878 printf("acquring duplicate lock of same type: \"%s\"\n", 879 m->mtx_description); 880 printf(" 1st @ %s:%d\n", w->w_file, w->w_line); 881 printf(" 2nd @ %s:%d\n", file, line); 882#ifdef DDB 883 go_into_ddb = 1; 884#endif /* DDB */ 885 goto out; 886 } 887 MPASS(!mtx_owned(&w_mtx)); 888 mtx_enter(&w_mtx, MTX_SPIN | MTX_QUIET); 889 /* 890 * If we have a known higher number just say ok 891 */ 892 if (witness_watch > 1 && w->w_level > w1->w_level) { 893 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 894 goto out; 895 } 896 if (isitmydescendant(m1->mtx_witness, w)) { 897 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 898 goto out; 899 } 900 for (i = 0; m1 != NULL; m1 = LIST_NEXT(m1, mtx_held), i++) { 901 902 MPASS(i < 200); 903 w1 = m1->mtx_witness; 904 if (isitmydescendant(w, w1)) { 905 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 906 if (blessed(w, w1)) 907 goto out; 908 if (m1 == &Giant) { 909 if (w1->w_Giant_squawked) 910 goto out; 911 else 912 w1->w_Giant_squawked = 1; 913 } else { 914 if (w1->w_other_squawked) 915 goto out; 916 else 917 w1->w_other_squawked = 1; 918 } 919 printf("lock order reversal\n"); 920 printf(" 1st %s last acquired @ %s:%d\n", 921 w->w_description, w->w_file, w->w_line); 922 printf(" 2nd %p %s @ %s:%d\n", 923 m1, w1->w_description, w1->w_file, w1->w_line); 924 printf(" 3rd %p %s @ %s:%d\n", 925 m, w->w_description, file, line); 926#ifdef DDB 927 go_into_ddb = 1; 928#endif /* DDB */ 929 goto out; 930 } 931 } 932 m1 = LIST_FIRST(&p->p_heldmtx); 933 if (!itismychild(m1->mtx_witness, w)) 934 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 935 936out: 937#ifdef DDB 938 if (witness_ddb && go_into_ddb) 939 Debugger("witness_enter"); 940#endif /* DDB */ 941 w->w_file = file; 942 w->w_line = line; 943 m->mtx_line = line; 944 m->mtx_file = file; 945 946 /* 947 * If this pays off it likely means that a mutex being witnessed 948 * is acquired in hardclock. Put it in the ignore list. It is 949 * likely not the mutex this assert fails on. 950 */ 951 MPASS(m->mtx_held.le_prev == NULL); 952 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 953} 954 955void 956witness_exit(struct mtx *m, int flags, const char *file, int line) 957{ 958 struct witness *w; 959 960 if (panicstr) 961 return; 962 w = m->mtx_witness; 963 964 if (flags & MTX_SPIN) { 965 if (!(w->w_spin)) 966 panic("mutex_exit: MTX_SPIN on MTX_DEF mutex %s @" 967 " %s:%d", m->mtx_description, file, line); 968 if (mtx_recursed(m)) { 969 if (!(w->w_recurse)) 970 panic("mutex_exit: recursion on non-recursive" 971 " mutex %s @ %s:%d", m->mtx_description, 972 file, line); 973 return; 974 } 975 mtx_enter(&w_mtx, MTX_SPIN | MTX_QUIET); 976 PCPU_SET(witness_spin_check, 977 PCPU_GET(witness_spin_check) & ~w->w_level); 978 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 979 return; 980 } 981 if (w->w_spin) 982 panic("mutex_exit: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 983 m->mtx_description, file, line); 984 985 if (mtx_recursed(m)) { 986 if (!(w->w_recurse)) 987 panic("mutex_exit: recursion on non-recursive" 988 " mutex %s @ %s:%d", m->mtx_description, 989 file, line); 990 return; 991 } 992 993 if ((flags & MTX_NOSWITCH) == 0 && !mtx_legal2block() && !cold) 994 panic("switchable mtx_exit() of %s when not legal @ %s:%d", 995 m->mtx_description, file, line); 996 LIST_REMOVE(m, mtx_held); 997 m->mtx_held.le_prev = NULL; 998} 999 1000void 1001witness_try_enter(struct mtx *m, int flags, const char *file, int line) 1002{ 1003 struct proc *p; 1004 struct witness *w = m->mtx_witness; 1005 1006 if (panicstr) 1007 return; 1008 if (flags & MTX_SPIN) { 1009 if (!(w->w_spin)) 1010 panic("mutex_try_enter: " 1011 "MTX_SPIN on MTX_DEF mutex %s @ %s:%d", 1012 m->mtx_description, file, line); 1013 if (mtx_recursed(m)) { 1014 if (!(w->w_recurse)) 1015 panic("mutex_try_enter: recursion on" 1016 " non-recursive mutex %s @ %s:%d", 1017 m->mtx_description, file, line); 1018 return; 1019 } 1020 mtx_enter(&w_mtx, MTX_SPIN | MTX_QUIET); 1021 PCPU_SET(witness_spin_check, 1022 PCPU_GET(witness_spin_check) | w->w_level); 1023 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 1024 w->w_file = file; 1025 w->w_line = line; 1026 m->mtx_line = line; 1027 m->mtx_file = file; 1028 return; 1029 } 1030 1031 if (w->w_spin) 1032 panic("mutex_try_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 1033 m->mtx_description, file, line); 1034 1035 if (mtx_recursed(m)) { 1036 if (!(w->w_recurse)) 1037 panic("mutex_try_enter: recursion on non-recursive" 1038 " mutex %s @ %s:%d", m->mtx_description, file, 1039 line); 1040 return; 1041 } 1042 w->w_file = file; 1043 w->w_line = line; 1044 m->mtx_line = line; 1045 m->mtx_file = file; 1046 p = CURPROC; 1047 MPASS(m->mtx_held.le_prev == NULL); 1048 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 1049} 1050 1051void 1052witness_display(void(*prnt)(const char *fmt, ...)) 1053{ 1054 struct witness *w, *w1; 1055 1056 witness_levelall(); 1057 1058 for (w = w_all; w; w = w->w_next) { 1059 if (w->w_file == NULL) 1060 continue; 1061 for (w1 = w_all; w1; w1 = w1->w_next) { 1062 if (isitmychild(w1, w)) 1063 break; 1064 } 1065 if (w1 != NULL) 1066 continue; 1067 /* 1068 * This lock has no anscestors, display its descendants. 1069 */ 1070 witness_displaydescendants(prnt, w); 1071 } 1072 prnt("\nMutex which were never acquired\n"); 1073 for (w = w_all; w; w = w->w_next) { 1074 if (w->w_file != NULL) 1075 continue; 1076 prnt("%s\n", w->w_description); 1077 } 1078} 1079 1080int 1081witness_sleep(int check_only, struct mtx *mtx, const char *file, int line) 1082{ 1083 struct mtx *m; 1084 struct proc *p; 1085 char **sleep; 1086 int n = 0; 1087 1088 p = CURPROC; 1089 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 1090 m = LIST_NEXT(m, mtx_held)) { 1091 if (m == mtx) 1092 continue; 1093 for (sleep = sleep_list; *sleep!= NULL; sleep++) 1094 if (strcmp(m->mtx_description, *sleep) == 0) 1095 goto next; 1096 printf("%s:%d: %s with \"%s\" locked from %s:%d\n", 1097 file, line, check_only ? "could sleep" : "sleeping", 1098 m->mtx_description, 1099 m->mtx_witness->w_file, m->mtx_witness->w_line); 1100 n++; 1101 next: 1102 } 1103#ifdef DDB 1104 if (witness_ddb && n) 1105 Debugger("witness_sleep"); 1106#endif /* DDB */ 1107 return (n); 1108} 1109 1110static struct witness * 1111enroll(const char *description, int flag) 1112{ 1113 int i; 1114 struct witness *w, *w1; 1115 char **ignore; 1116 char **order; 1117 1118 if (!witness_watch) 1119 return (NULL); 1120 for (ignore = ignore_list; *ignore != NULL; ignore++) 1121 if (strcmp(description, *ignore) == 0) 1122 return (NULL); 1123 1124 if (w_inited == 0) { 1125 mtx_init(&w_mtx, "witness lock", MTX_COLD | MTX_SPIN); 1126 for (i = 0; i < WITNESS_COUNT; i++) { 1127 w = &w_data[i]; 1128 witness_free(w); 1129 } 1130 w_inited = 1; 1131 for (order = order_list; *order != NULL; order++) { 1132 w = enroll(*order, MTX_DEF); 1133 w->w_file = "order list"; 1134 for (order++; *order != NULL; order++) { 1135 w1 = enroll(*order, MTX_DEF); 1136 w1->w_file = "order list"; 1137 itismychild(w, w1); 1138 w = w1; 1139 } 1140 } 1141 } 1142 if ((flag & MTX_SPIN) && witness_skipspin) 1143 return (NULL); 1144 mtx_enter(&w_mtx, MTX_SPIN | MTX_QUIET); 1145 for (w = w_all; w; w = w->w_next) { 1146 if (strcmp(description, w->w_description) == 0) { 1147 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 1148 return (w); 1149 } 1150 } 1151 if ((w = witness_get()) == NULL) 1152 return (NULL); 1153 w->w_next = w_all; 1154 w_all = w; 1155 w->w_description = description; 1156 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 1157 if (flag & MTX_SPIN) { 1158 w->w_spin = 1; 1159 1160 i = 1; 1161 for (order = spin_order_list; *order != NULL; order++) { 1162 if (strcmp(description, *order) == 0) 1163 break; 1164 i <<= 1; 1165 } 1166 if (*order == NULL) 1167 panic("spin lock %s not in order list", description); 1168 w->w_level = i; 1169 } else 1170 w->w_sleep = 1; 1171 1172 if (flag & MTX_RECURSE) 1173 w->w_recurse = 1; 1174 1175 return (w); 1176} 1177 1178static int 1179itismychild(struct witness *parent, struct witness *child) 1180{ 1181 static int recursed; 1182 1183 /* 1184 * Insert "child" after "parent" 1185 */ 1186 while (parent->w_morechildren) 1187 parent = parent->w_morechildren; 1188 1189 if (parent->w_childcnt == WITNESS_NCHILDREN) { 1190 if ((parent->w_morechildren = witness_get()) == NULL) 1191 return (1); 1192 parent = parent->w_morechildren; 1193 } 1194 MPASS(child != NULL); 1195 parent->w_children[parent->w_childcnt++] = child; 1196 /* 1197 * now prune whole tree 1198 */ 1199 if (recursed) 1200 return (0); 1201 recursed = 1; 1202 for (child = w_all; child != NULL; child = child->w_next) { 1203 for (parent = w_all; parent != NULL; 1204 parent = parent->w_next) { 1205 if (!isitmychild(parent, child)) 1206 continue; 1207 removechild(parent, child); 1208 if (isitmydescendant(parent, child)) 1209 continue; 1210 itismychild(parent, child); 1211 } 1212 } 1213 recursed = 0; 1214 witness_levelall(); 1215 return (0); 1216} 1217 1218static void 1219removechild(struct witness *parent, struct witness *child) 1220{ 1221 struct witness *w, *w1; 1222 int i; 1223 1224 for (w = parent; w != NULL; w = w->w_morechildren) 1225 for (i = 0; i < w->w_childcnt; i++) 1226 if (w->w_children[i] == child) 1227 goto found; 1228 return; 1229found: 1230 for (w1 = w; w1->w_morechildren != NULL; w1 = w1->w_morechildren) 1231 continue; 1232 w->w_children[i] = w1->w_children[--w1->w_childcnt]; 1233 MPASS(w->w_children[i] != NULL); 1234 1235 if (w1->w_childcnt != 0) 1236 return; 1237 1238 if (w1 == parent) 1239 return; 1240 for (w = parent; w->w_morechildren != w1; w = w->w_morechildren) 1241 continue; 1242 w->w_morechildren = 0; 1243 witness_free(w1); 1244} 1245 1246static int 1247isitmychild(struct witness *parent, struct witness *child) 1248{ 1249 struct witness *w; 1250 int i; 1251 1252 for (w = parent; w != NULL; w = w->w_morechildren) { 1253 for (i = 0; i < w->w_childcnt; i++) { 1254 if (w->w_children[i] == child) 1255 return (1); 1256 } 1257 } 1258 return (0); 1259} 1260 1261static int 1262isitmydescendant(struct witness *parent, struct witness *child) 1263{ 1264 struct witness *w; 1265 int i; 1266 int j; 1267 1268 for (j = 0, w = parent; w != NULL; w = w->w_morechildren, j++) { 1269 MPASS(j < 1000); 1270 for (i = 0; i < w->w_childcnt; i++) { 1271 if (w->w_children[i] == child) 1272 return (1); 1273 } 1274 for (i = 0; i < w->w_childcnt; i++) { 1275 if (isitmydescendant(w->w_children[i], child)) 1276 return (1); 1277 } 1278 } 1279 return (0); 1280} 1281 1282void 1283witness_levelall (void) 1284{ 1285 struct witness *w, *w1; 1286 1287 for (w = w_all; w; w = w->w_next) 1288 if (!(w->w_spin)) 1289 w->w_level = 0; 1290 for (w = w_all; w; w = w->w_next) { 1291 if (w->w_spin) 1292 continue; 1293 for (w1 = w_all; w1; w1 = w1->w_next) { 1294 if (isitmychild(w1, w)) 1295 break; 1296 } 1297 if (w1 != NULL) 1298 continue; 1299 witness_leveldescendents(w, 0); 1300 } 1301} 1302 1303static void 1304witness_leveldescendents(struct witness *parent, int level) 1305{ 1306 int i; 1307 struct witness *w; 1308 1309 if (parent->w_level < level) 1310 parent->w_level = level; 1311 level++; 1312 for (w = parent; w != NULL; w = w->w_morechildren) 1313 for (i = 0; i < w->w_childcnt; i++) 1314 witness_leveldescendents(w->w_children[i], level); 1315} 1316 1317static void 1318witness_displaydescendants(void(*prnt)(const char *fmt, ...), 1319 struct witness *parent) 1320{ 1321 struct witness *w; 1322 int i; 1323 int level = parent->w_level; 1324 1325 prnt("%d", level); 1326 if (level < 10) 1327 prnt(" "); 1328 for (i = 0; i < level; i++) 1329 prnt(" "); 1330 prnt("%s", parent->w_description); 1331 if (parent->w_file != NULL) { 1332 prnt(" -- last acquired @ %s", parent->w_file); 1333#ifndef W_USE_WHERE 1334 prnt(":%d", parent->w_line); 1335#endif 1336 prnt("\n"); 1337 } 1338 1339 for (w = parent; w != NULL; w = w->w_morechildren) 1340 for (i = 0; i < w->w_childcnt; i++) 1341 witness_displaydescendants(prnt, w->w_children[i]); 1342 } 1343 1344static int 1345dup_ok(struct witness *w) 1346{ 1347 char **dup; 1348 1349 for (dup = dup_list; *dup!= NULL; dup++) 1350 if (strcmp(w->w_description, *dup) == 0) 1351 return (1); 1352 return (0); 1353} 1354 1355static int 1356blessed(struct witness *w1, struct witness *w2) 1357{ 1358 int i; 1359 struct witness_blessed *b; 1360 1361 for (i = 0; i < blessed_count; i++) { 1362 b = &blessed_list[i]; 1363 if (strcmp(w1->w_description, b->b_lock1) == 0) { 1364 if (strcmp(w2->w_description, b->b_lock2) == 0) 1365 return (1); 1366 continue; 1367 } 1368 if (strcmp(w1->w_description, b->b_lock2) == 0) 1369 if (strcmp(w2->w_description, b->b_lock1) == 0) 1370 return (1); 1371 } 1372 return (0); 1373} 1374 1375static struct witness * 1376witness_get() 1377{ 1378 struct witness *w; 1379 1380 if ((w = w_free) == NULL) { 1381 witness_dead = 1; 1382 mtx_exit(&w_mtx, MTX_SPIN | MTX_QUIET); 1383 printf("witness exhausted\n"); 1384 return (NULL); 1385 } 1386 w_free = w->w_next; 1387 bzero(w, sizeof(*w)); 1388 return (w); 1389} 1390 1391static void 1392witness_free(struct witness *w) 1393{ 1394 w->w_next = w_free; 1395 w_free = w; 1396} 1397 1398int 1399witness_list(struct proc *p) 1400{ 1401 struct mtx *m; 1402 int nheld; 1403 1404 nheld = 0; 1405 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 1406 m = LIST_NEXT(m, mtx_held)) { 1407 printf("\t\"%s\" (%p) locked at %s:%d\n", 1408 m->mtx_description, m, 1409 m->mtx_witness->w_file, m->mtx_witness->w_line); 1410 nheld++; 1411 } 1412 1413 return (nheld); 1414} 1415 1416void 1417witness_save(struct mtx *m, const char **filep, int *linep) 1418{ 1419 *filep = m->mtx_witness->w_file; 1420 *linep = m->mtx_witness->w_line; 1421} 1422 1423void 1424witness_restore(struct mtx *m, const char *file, int line) 1425{ 1426 m->mtx_witness->w_file = file; 1427 m->mtx_witness->w_line = line; 1428} 1429 1430#endif /* WITNESS */ 1431