subr_witness.c revision 65651
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 * $FreeBSD: head/sys/kern/subr_witness.c 65651 2000-09-09 23:18:48Z jasone $ 30 */ 31 32/* 33 * Main Entry: witness 34 * Pronunciation: 'wit-n&s 35 * Function: noun 36 * Etymology: Middle English witnesse, from Old English witnes knowledge, 37 * testimony, witness, from 2wit 38 * Date: before 12th century 39 * 1 : attestation of a fact or event : TESTIMONY 40 * 2 : one that gives evidence; specifically : one who testifies in 41 * a cause or before a judicial tribunal 42 * 3 : one asked to be present at a transaction so as to be able to 43 * testify to its having taken place 44 * 4 : one who has personal knowledge of something 45 * 5 a : something serving as evidence or proof : SIGN 46 * b : public affirmation by word or example of usually 47 * religious faith or conviction <the heroic witness to divine 48 * life -- Pilot> 49 * 6 capitalized : a member of the Jehovah's Witnesses 50 */ 51 52#include <sys/param.h> 53#include <sys/proc.h> 54#include <sys/systm.h> 55#include <sys/ktr.h> 56 57#include <machine/cpu.h> 58#define _KERN_MUTEX_C_ /* Cause non-inlined mtx_*() to be compiled. */ 59#include <machine/mutex.h> 60 61/* 62 * The non-inlined versions of the mtx_*() functions are always built (above), 63 * but the witness code depends on the SMP_DEBUG and WITNESS kernel options 64 * being specified. 65 */ 66#if (defined(SMP_DEBUG) && defined(WITNESS)) 67 68#define WITNESS_COUNT 200 69#define WITNESS_NCHILDREN 2 70 71#ifndef WITNESS 72#define WITNESS 0 /* default off */ 73#endif 74 75#ifndef SMP 76extern int witness_spin_check; 77#endif 78 79int witness_watch; 80 81typedef struct witness { 82 struct witness *w_next; 83 char *w_description; 84 const char *w_file; 85 int w_line; 86 struct witness *w_morechildren; 87 u_char w_childcnt; 88 u_char w_Giant_squawked:1; 89 u_char w_other_squawked:1; 90 u_char w_same_squawked:1; 91 u_char w_sleep:1; 92 u_char w_spin:1; /* this is a spin mutex */ 93 u_int w_level; 94 struct witness *w_children[WITNESS_NCHILDREN]; 95} witness_t; 96 97typedef struct witness_blessed { 98 char *b_lock1; 99 char *b_lock2; 100} witness_blessed_t; 101 102#ifdef KDEBUG 103/* 104 * When WITNESS_KDEBUG is set to 1, it will cause the system to 105 * drop into kdebug() when: 106 * - a lock heirarchy violation occurs 107 * - locks are held when going to sleep. 108 */ 109#ifndef WITNESS_KDEBUG 110#define WITNESS_KDEBUG 0 111#endif 112int witness_kdebug = WITNESS_KDEBUG; 113#endif /* KDEBUG */ 114 115#ifndef WITNESS_SKIPSPIN 116#define WITNESS_SKIPSPIN 0 117#endif 118int witness_skipspin = WITNESS_SKIPSPIN; 119 120 121static mtx_t w_mtx; 122static witness_t *w_free; 123static witness_t *w_all; 124static int w_inited; 125static int witness_dead; /* fatal error, probably no memory */ 126 127static witness_t w_data[WITNESS_COUNT]; 128 129static witness_t *enroll __P((char *description, int flag)); 130static int itismychild __P((witness_t *parent, witness_t *child)); 131static void removechild __P((witness_t *parent, witness_t *child)); 132static int isitmychild __P((witness_t *parent, witness_t *child)); 133static int isitmydescendant __P((witness_t *parent, witness_t *child)); 134static int dup_ok __P((witness_t *)); 135static int blessed __P((witness_t *, witness_t *)); 136static void witness_displaydescendants 137 __P((void(*)(const char *fmt, ...), witness_t *)); 138static void witness_leveldescendents __P((witness_t *parent, int level)); 139static void witness_levelall __P((void)); 140static witness_t * witness_get __P((void)); 141static void witness_free __P((witness_t *m)); 142 143 144static char *ignore_list[] = { 145 "witness lock", 146 "Kdebug", /* breaks rules and may or may not work */ 147 "Page Alias", /* sparc only, witness lock won't block intr */ 148 NULL 149}; 150 151static char *spin_order_list[] = { 152 "sched lock", 153 "log mtx", 154 "zslock", /* sparc only above log, this one is a real hack */ 155 "time lock", /* above callout */ 156 "callout mtx", /* above wayout */ 157 /* 158 * leaf locks 159 */ 160 "wayout mtx", 161 "kernel_pmap", /* sparc only, logically equal "pmap" below */ 162 "pmap", /* sparc only */ 163 NULL 164}; 165 166static char *order_list[] = { 167 "tcb", "inp", "so_snd", "so_rcv", "Giant lock", NULL, 168 "udb", "inp", NULL, 169 "unp head", "unp", "so_snd", NULL, 170 "de0", "Giant lock", NULL, 171 "ifnet", "Giant lock", NULL, 172 "fifo", "so_snd", NULL, 173 "hme0", "Giant lock", NULL, 174 "esp0", "Giant lock", NULL, 175 "hfa0", "Giant lock", NULL, 176 "so_rcv", "atm_global", NULL, 177 "so_snd", "atm_global", NULL, 178 "NFS", "Giant lock", NULL, 179 NULL 180}; 181 182static char *dup_list[] = { 183 "inp", 184 "process group", 185 "session", 186 "unp", 187 "rtentry", 188 "rawcb", 189 NULL 190}; 191 192static char *sleep_list[] = { 193 "Giant lock", 194 NULL 195}; 196 197/* 198 * Pairs of locks which have been blessed 199 * Don't complain about order problems with blessed locks 200 */ 201static witness_blessed_t blessed_list[] = { 202}; 203static int blessed_count = sizeof (blessed_list) / sizeof (witness_blessed_t); 204 205void 206witness_init(mtx_t *m, int flag) 207{ 208 m->mtx_witness = enroll(m->mtx_description, flag); 209} 210 211void 212witness_destroy(mtx_t *m) 213{ 214 mtx_t *m1; 215 struct proc *p; 216 p = CURPROC; 217 for ((m1 = LIST_FIRST(&p->p_heldmtx)); m1 != NULL; 218 m1 = LIST_NEXT(m1, mtx_held)) { 219 if (m1 == m) { 220 LIST_REMOVE(m, mtx_held); 221 break; 222 } 223 } 224 return; 225 226} 227 228void 229witness_enter(mtx_t *m, int flags, const char *file, int line) 230{ 231 witness_t *w, *w1; 232 mtx_t *m1; 233 struct proc *p; 234 int i; 235#ifdef KDEBUG 236 int go_into_kdebug = 0; 237#endif /* KDEBUG */ 238 239 w = m->mtx_witness; 240 p = CURPROC; 241 242 if (flags & MTX_SPIN) { 243 if (!w->w_spin) 244 panic("mutex_enter: MTX_SPIN on MTX_DEF mutex %s @" 245 " %s:%d", m->mtx_description, file, line); 246 if (m->mtx_recurse != 0) 247 return; 248 mtx_enter(&w_mtx, MTX_SPIN); 249 i = witness_spin_check; 250 if (i != 0 && w->w_level < i) { 251 mtx_exit(&w_mtx, MTX_SPIN); 252 panic("mutex_enter(%s:%x, MTX_SPIN) out of order @" 253 " %s:%d already holding %s:%x", 254 m->mtx_description, w->w_level, file, line, 255 spin_order_list[ffs(i)-1], i); 256 } 257 PCPU_SET(witness_spin_check, i | w->w_level); 258 mtx_exit(&w_mtx, MTX_SPIN); 259 return; 260 } 261 if (w->w_spin) 262 panic("mutex_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 263 m->mtx_description, file, line); 264 265 if (m->mtx_recurse != 0) 266 return; 267 if (witness_dead) 268 goto out; 269 if (cold) 270 goto out; 271 272 if (!mtx_legal2block()) 273 panic("blockable mtx_enter() of %s when not legal @ %s:%d", 274 m->mtx_description, file, line); 275 /* 276 * Is this the first mutex acquired 277 */ 278 if ((m1 = LIST_FIRST(&p->p_heldmtx)) == NULL) 279 goto out; 280 281 if ((w1 = m1->mtx_witness) == w) { 282 if (w->w_same_squawked || dup_ok(w)) 283 goto out; 284 w->w_same_squawked = 1; 285 printf("acquring duplicate lock of same type: \"%s\"\n", 286 m->mtx_description); 287 printf(" 1st @ %s:%d\n", w->w_file, w->w_line); 288 printf(" 2nd @ %s:%d\n", file, line); 289#ifdef KDEBUG 290 go_into_kdebug = 1; 291#endif /* KDEBUG */ 292 goto out; 293 } 294 MPASS(!mtx_owned(&w_mtx)); 295 mtx_enter(&w_mtx, MTX_SPIN); 296 /* 297 * If we have a known higher number just say ok 298 */ 299 if (witness_watch > 1 && w->w_level > w1->w_level) { 300 mtx_exit(&w_mtx, MTX_SPIN); 301 goto out; 302 } 303 if (isitmydescendant(m1->mtx_witness, w)) { 304 mtx_exit(&w_mtx, MTX_SPIN); 305 goto out; 306 } 307 for (i = 0; m1 != NULL; m1 = LIST_NEXT(m1, mtx_held), i++) { 308 309 ASS(i < 200); 310 w1 = m1->mtx_witness; 311 if (isitmydescendant(w, w1)) { 312 mtx_exit(&w_mtx, MTX_SPIN); 313 if (blessed(w, w1)) 314 goto out; 315 if (m1 == &Giant) { 316 if (w1->w_Giant_squawked) 317 goto out; 318 else 319 w1->w_Giant_squawked = 1; 320 } else { 321 if (w1->w_other_squawked) 322 goto out; 323 else 324 w1->w_other_squawked = 1; 325 } 326 printf("lock order reversal\n"); 327 printf(" 1st %s last acquired @ %s:%d\n", 328 w->w_description, w->w_file, w->w_line); 329 printf(" 2nd %p %s @ %s:%d\n", 330 m1, w1->w_description, w1->w_file, w1->w_line); 331 printf(" 3rd %p %s @ %s:%d\n", 332 m, w->w_description, file, line); 333#ifdef KDEBUG 334 go_into_kdebug = 1; 335#endif /* KDEBUG */ 336 goto out; 337 } 338 } 339 m1 = LIST_FIRST(&p->p_heldmtx); 340 if (!itismychild(m1->mtx_witness, w)) 341 mtx_exit(&w_mtx, MTX_SPIN); 342 343out: 344#ifdef KDEBUG 345 if (witness_kdebug && go_into_kdebug) 346 kdebug(); 347#endif /* KDEBUG */ 348 w->w_file = file; 349 w->w_line = line; 350 m->mtx_line = line; 351 m->mtx_file = file; 352 353 /* 354 * If this pays off it likely means that a mutex being witnessed 355 * is acquired in hardclock. Put it in the ignore list. It is 356 * likely not the mutex this assert fails on. 357 */ 358 ASS(m->mtx_held.le_prev == NULL); 359 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 360} 361 362void 363witness_exit(mtx_t *m, int flags, const char *file, int line) 364{ 365 witness_t *w; 366 367 w = m->mtx_witness; 368 369 if (flags & MTX_SPIN) { 370 if (!w->w_spin) 371 panic("mutex_exit: MTX_SPIN on MTX_DEF mutex %s @" 372 " %s:%d", m->mtx_description, file, line); 373 if (m->mtx_recurse != 0) 374 return; 375 mtx_enter(&w_mtx, MTX_SPIN); 376 PCPU_SET(witness_spin_check, witness_spin_check & ~w->w_level); 377 mtx_exit(&w_mtx, MTX_SPIN); 378 return; 379 } 380 if (w->w_spin) 381 panic("mutex_exit: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 382 m->mtx_description, file, line); 383 384 if (m->mtx_recurse != 0) 385 return; 386 387 if ((flags & MTX_NOSWITCH) == 0 && !mtx_legal2block() && !cold) 388 panic("switchable mtx_exit() of %s when not legal @ %s:%d", 389 m->mtx_description, file, line); 390 LIST_REMOVE(m, mtx_held); 391 m->mtx_held.le_prev = NULL; 392} 393 394void 395witness_try_enter(mtx_t *m, int flags, const char *file, int line) 396{ 397 struct proc *p; 398 witness_t *w = m->mtx_witness; 399 400 if (flags & MTX_SPIN) { 401 if (!w->w_spin) 402 panic("mutex_try_enter: " 403 "MTX_SPIN on MTX_DEF mutex %s @ %s:%d", 404 m->mtx_description, file, line); 405 if (m->mtx_recurse != 0) 406 return; 407 mtx_enter(&w_mtx, MTX_SPIN); 408 PCPU_SET(witness_spin_check, witness_spin_check | w->w_level); 409 mtx_exit(&w_mtx, MTX_SPIN); 410 return; 411 } 412 413 if (w->w_spin) 414 panic("mutex_try_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 415 m->mtx_description, file, line); 416 417 if (m->mtx_recurse != 0) 418 return; 419 420 w->w_file = file; 421 w->w_line = line; 422 m->mtx_line = line; 423 m->mtx_file = file; 424 p = CURPROC; 425 ASS(m->mtx_held.le_prev == NULL); 426 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 427} 428 429void 430witness_display(void(*prnt)(const char *fmt, ...)) 431{ 432 witness_t *w, *w1; 433 434 witness_levelall(); 435 436 for (w = w_all; w; w = w->w_next) { 437 if (w->w_file == NULL) 438 continue; 439 for (w1 = w_all; w1; w1 = w1->w_next) { 440 if (isitmychild(w1, w)) 441 break; 442 } 443 if (w1 != NULL) 444 continue; 445 /* 446 * This lock has no anscestors, display its descendants. 447 */ 448 witness_displaydescendants(prnt, w); 449 } 450 prnt("\nMutex which were never acquired\n"); 451 for (w = w_all; w; w = w->w_next) { 452 if (w->w_file != NULL) 453 continue; 454 prnt("%s\n", w->w_description); 455 } 456} 457 458int 459witness_sleep(int check_only, mtx_t *mtx, const char *file, int line) 460{ 461 mtx_t *m; 462 struct proc *p; 463 char **sleep; 464 int n = 0; 465 466 p = CURPROC; 467 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 468 m = LIST_NEXT(m, mtx_held)) { 469 if (m == mtx) 470 continue; 471 for (sleep = sleep_list; *sleep!= NULL; sleep++) 472 if (strcmp(m->mtx_description, *sleep) == 0) 473 goto next; 474 printf("%s:%d: %s with \"%s\" locked from %s:%d\n", 475 file, line, check_only ? "could sleep" : "sleeping", 476 m->mtx_description, 477 m->mtx_witness->w_file, m->mtx_witness->w_line); 478 n++; 479 next: 480 } 481#ifdef KDEBUG 482 if (witness_kdebug && n) 483 kdebug(); 484#endif /* KDEBUG */ 485 return (n); 486} 487 488static witness_t * 489enroll(char *description, int flag) 490{ 491 int i; 492 witness_t *w, *w1; 493 char **ignore; 494 char **order; 495 496 if (!witness_watch) 497 return (NULL); 498 for (ignore = ignore_list; *ignore != NULL; ignore++) 499 if (strcmp(description, *ignore) == 0) 500 return (NULL); 501 502 if (w_inited == 0) { 503 mtx_init(&w_mtx, "witness lock", MTX_DEF); 504 for (i = 0; i < WITNESS_COUNT; i++) { 505 w = &w_data[i]; 506 witness_free(w); 507 } 508 w_inited = 1; 509 for (order = order_list; *order != NULL; order++) { 510 w = enroll(*order, MTX_DEF); 511 w->w_file = "order list"; 512 for (order++; *order != NULL; order++) { 513 w1 = enroll(*order, MTX_DEF); 514 w1->w_file = "order list"; 515 itismychild(w, w1); 516 w = w1; 517 } 518 } 519 } 520 if ((flag & MTX_SPIN) && witness_skipspin) 521 return (NULL); 522 mtx_enter(&w_mtx, MTX_SPIN); 523 for (w = w_all; w; w = w->w_next) { 524 if (strcmp(description, w->w_description) == 0) { 525 mtx_exit(&w_mtx, MTX_SPIN); 526 return (w); 527 } 528 } 529 if ((w = witness_get()) == NULL) 530 return (NULL); 531 w->w_next = w_all; 532 w_all = w; 533 w->w_description = description; 534 mtx_exit(&w_mtx, MTX_SPIN); 535 if (flag & MTX_SPIN) { 536 w->w_spin = 1; 537 538 i = 1; 539 for (order = spin_order_list; *order != NULL; order++) { 540 if (strcmp(description, *order) == 0) 541 break; 542 i <<= 1; 543 } 544 if (*order == NULL) 545 panic("spin lock %s not in order list", description); 546 w->w_level = i; 547 } 548 return (w); 549} 550 551static int 552itismychild(witness_t *parent, witness_t *child) 553{ 554 static int recursed; 555 556 /* 557 * Insert "child" after "parent" 558 */ 559 while (parent->w_morechildren) 560 parent = parent->w_morechildren; 561 562 if (parent->w_childcnt == WITNESS_NCHILDREN) { 563 if ((parent->w_morechildren = witness_get()) == NULL) 564 return (1); 565 parent = parent->w_morechildren; 566 } 567 ASS(child != NULL); 568 parent->w_children[parent->w_childcnt++] = child; 569 /* 570 * now prune whole tree 571 */ 572 if (recursed) 573 return (0); 574 recursed = 1; 575 for (child = w_all; child != NULL; child = child->w_next) { 576 for (parent = w_all; parent != NULL; 577 parent = parent->w_next) { 578 if (!isitmychild(parent, child)) 579 continue; 580 removechild(parent, child); 581 if (isitmydescendant(parent, child)) 582 continue; 583 itismychild(parent, child); 584 } 585 } 586 recursed = 0; 587 witness_levelall(); 588 return (0); 589} 590 591static void 592removechild(witness_t *parent, witness_t *child) 593{ 594 witness_t *w, *w1; 595 int i; 596 597 for (w = parent; w != NULL; w = w->w_morechildren) 598 for (i = 0; i < w->w_childcnt; i++) 599 if (w->w_children[i] == child) 600 goto found; 601 return; 602found: 603 for (w1 = w; w1->w_morechildren != NULL; w1 = w1->w_morechildren) 604 continue; 605 w->w_children[i] = w1->w_children[--w1->w_childcnt]; 606 ASS(w->w_children[i] != NULL); 607 608 if (w1->w_childcnt != 0) 609 return; 610 611 if (w1 == parent) 612 return; 613 for (w = parent; w->w_morechildren != w1; w = w->w_morechildren) 614 continue; 615 w->w_morechildren = 0; 616 witness_free(w1); 617} 618 619static int 620isitmychild(witness_t *parent, witness_t *child) 621{ 622 witness_t *w; 623 int i; 624 625 for (w = parent; w != NULL; w = w->w_morechildren) { 626 for (i = 0; i < w->w_childcnt; i++) { 627 if (w->w_children[i] == child) 628 return (1); 629 } 630 } 631 return (0); 632} 633 634static int 635isitmydescendant(witness_t *parent, witness_t *child) 636{ 637 witness_t *w; 638 int i; 639 int j; 640 641 for (j = 0, w = parent; w != NULL; w = w->w_morechildren, j++) { 642 ASS(j < 1000); 643 for (i = 0; i < w->w_childcnt; i++) { 644 if (w->w_children[i] == child) 645 return (1); 646 } 647 for (i = 0; i < w->w_childcnt; i++) { 648 if (isitmydescendant(w->w_children[i], child)) 649 return (1); 650 } 651 } 652 return (0); 653} 654 655void 656witness_levelall (void) 657{ 658 witness_t *w, *w1; 659 660 for (w = w_all; w; w = w->w_next) 661 if (!w->w_spin) 662 w->w_level = 0; 663 for (w = w_all; w; w = w->w_next) { 664 if (w->w_spin) 665 continue; 666 for (w1 = w_all; w1; w1 = w1->w_next) { 667 if (isitmychild(w1, w)) 668 break; 669 } 670 if (w1 != NULL) 671 continue; 672 witness_leveldescendents(w, 0); 673 } 674} 675 676static void 677witness_leveldescendents(witness_t *parent, int level) 678{ 679 int i; 680 witness_t *w; 681 682 if (parent->w_level < level) 683 parent->w_level = level; 684 level++; 685 for (w = parent; w != NULL; w = w->w_morechildren) 686 for (i = 0; i < w->w_childcnt; i++) 687 witness_leveldescendents(w->w_children[i], level); 688} 689 690static void 691witness_displaydescendants(void(*prnt)(const char *fmt, ...), witness_t *parent) 692{ 693 witness_t *w; 694 int i; 695 int level = parent->w_level; 696 697 prnt("%d", level); 698 if (level < 10) 699 prnt(" "); 700 for (i = 0; i < level; i++) 701 prnt(" "); 702 prnt("%s", parent->w_description); 703 if (parent->w_file != NULL) { 704 prnt(" -- last acquired @ %s", parent->w_file); 705#ifndef W_USE_WHERE 706 prnt(":%d", parent->w_line); 707#endif 708 prnt("\n"); 709 } 710 711 for (w = parent; w != NULL; w = w->w_morechildren) 712 for (i = 0; i < w->w_childcnt; i++) 713 witness_displaydescendants(prnt, w->w_children[i]); 714 } 715 716static int 717dup_ok(witness_t *w) 718{ 719 char **dup; 720 721 for (dup = dup_list; *dup!= NULL; dup++) 722 if (strcmp(w->w_description, *dup) == 0) 723 return (1); 724 return (0); 725} 726 727static int 728blessed(witness_t *w1, witness_t *w2) 729{ 730 int i; 731 witness_blessed_t *b; 732 733 for (i = 0; i < blessed_count; i++) { 734 b = &blessed_list[i]; 735 if (strcmp(w1->w_description, b->b_lock1) == 0) { 736 if (strcmp(w2->w_description, b->b_lock2) == 0) 737 return (1); 738 continue; 739 } 740 if (strcmp(w1->w_description, b->b_lock2) == 0) 741 if (strcmp(w2->w_description, b->b_lock1) == 0) 742 return (1); 743 } 744 return (0); 745} 746 747static witness_t * 748witness_get() 749{ 750 witness_t *w; 751 752 if ((w = w_free) == NULL) { 753 witness_dead = 1; 754 mtx_exit(&w_mtx, MTX_SPIN); 755 printf("witness exhausted\n"); 756 return (NULL); 757 } 758 w_free = w->w_next; 759 bzero(w, sizeof (*w)); 760 return (w); 761} 762 763static void 764witness_free(witness_t *w) 765{ 766 w->w_next = w_free; 767 w_free = w; 768} 769 770void 771witness_list(struct proc *p) 772{ 773 mtx_t *m; 774 775 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 776 m = LIST_NEXT(m, mtx_held)) { 777 printf("\t\"%s\" (%p) locked at %s:%d\n", 778 m->mtx_description, m, 779 m->mtx_witness->w_file, m->mtx_witness->w_line); 780 } 781} 782 783void 784witness_save(mtx_t *m, const char **filep, int *linep) 785{ 786 *filep = m->mtx_witness->w_file; 787 *linep = m->mtx_witness->w_line; 788} 789 790void 791witness_restore(mtx_t *m, const char *file, int line) 792{ 793 m->mtx_witness->w_file = file; 794 m->mtx_witness->w_line = line; 795} 796 797#endif /* (defined(SMP_DEBUG) && defined(WITNESS)) */ 798