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