subr_witness.c revision 65624
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 65624 2000-09-08 21:48:06Z 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, 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 @ %s:%d", 245 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 @ %s:%d" 253 " 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 282 if ((w1 = m1->mtx_witness) == w) { 283 if (w->w_same_squawked || dup_ok(w)) 284 goto out; 285 w->w_same_squawked = 1; 286 printf("acquring duplicate lock of same type: \"%s\"\n", 287 m->mtx_description); 288 printf(" 1st @ %s:%d\n", w->w_file, w->w_line); 289 printf(" 2nd @ %s:%d\n", file, line); 290#ifdef KDEBUG 291 go_into_kdebug = 1; 292#endif /* KDEBUG */ 293 goto out; 294 } 295 MPASS(!mtx_owned(&w_mtx)); 296 mtx_enter(&w_mtx, MTX_SPIN); 297 /* 298 * If we have a known higher number just say ok 299 */ 300 if (witness_watch > 1 && w->w_level > w1->w_level) { 301 mtx_exit(&w_mtx, MTX_SPIN); 302 goto out; 303 } 304 if (isitmydescendant(m1->mtx_witness, w)) { 305 mtx_exit(&w_mtx, MTX_SPIN); 306 goto out; 307 } 308 for (i = 0; m1 != NULL; m1 = LIST_NEXT(m1, mtx_held), i++) { 309 310 ASS(i < 200); 311 w1 = m1->mtx_witness; 312 if (isitmydescendant(w, w1)) { 313 mtx_exit(&w_mtx, MTX_SPIN); 314 if (blessed(w, w1)) 315 goto out; 316 if (m1 == &Giant) { 317 if (w1->w_Giant_squawked) 318 goto out; 319 else 320 w1->w_Giant_squawked = 1; 321 } else { 322 if (w1->w_other_squawked) 323 goto out; 324 else 325 w1->w_other_squawked = 1; 326 } 327 printf("lock order reversal\n"); 328 printf(" 1st %s last acquired @ %s:%d\n", 329 w->w_description, w->w_file, w->w_line); 330 printf(" 2nd %p %s @ %s:%d\n", 331 m1, w1->w_description, w1->w_file, w1->w_line); 332 printf(" 3rd %p %s @ %s:%d\n", 333 m, w->w_description, file, line); 334#ifdef KDEBUG 335 go_into_kdebug = 1; 336#endif /* KDEBUG */ 337 goto out; 338 } 339 } 340 m1 = LIST_FIRST(&p->p_heldmtx); 341 if (!itismychild(m1->mtx_witness, w)) 342 mtx_exit(&w_mtx, MTX_SPIN); 343 344out: 345#ifdef KDEBUG 346 if (witness_kdebug && go_into_kdebug) 347 kdebug(); 348#endif /* KDEBUG */ 349 w->w_file = file; 350 w->w_line = line; 351 m->mtx_line = line; 352 m->mtx_file = file; 353 354 /* 355 * If this pays off it likely means that a mutex being witnessed 356 * is acquired in hardclock. Put it in the ignore list. It is 357 * likely not the mutex this assert fails on. 358 */ 359 ASS(m->mtx_held.le_prev == NULL); 360 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 361} 362 363void 364witness_exit(mtx_t *m, int flags, char *file, int line) 365{ 366 witness_t *w; 367 368 w = m->mtx_witness; 369 370 if (flags & MTX_SPIN) { 371 if (!w->w_spin) 372 panic("mutex_exit: MTX_SPIN on MTX_DEF mutex %s @ %s:%d", 373 m->mtx_description, file, line); 374 if (m->mtx_recurse != 0) 375 return; 376 mtx_enter(&w_mtx, MTX_SPIN); 377 PCPU_SET(witness_spin_check, witness_spin_check & ~w->w_level); 378 mtx_exit(&w_mtx, MTX_SPIN); 379 return; 380 } 381 if (w->w_spin) 382 panic("mutex_exit: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 383 m->mtx_description, file, line); 384 385 if (m->mtx_recurse != 0) 386 return; 387 388 if ((flags & MTX_NOSWITCH) == 0 && !mtx_legal2block() && !cold) 389 panic("switchable mtx_exit() of %s when not legal @ %s:%d", 390 m->mtx_description, file, line); 391 LIST_REMOVE(m, mtx_held); 392 m->mtx_held.le_prev = NULL; 393} 394 395void 396witness_try_enter(mtx_t *m, int flags, const char *file, int line) 397{ 398 struct proc *p; 399 witness_t *w = m->mtx_witness; 400 401 402 if (flags & MTX_SPIN) { 403 if (!w->w_spin) 404 panic("mutex_try_enter: " 405 "MTX_SPIN on MTX_DEF mutex %s @ %s:%d", 406 m->mtx_description, file, line); 407 if (m->mtx_recurse != 0) 408 return; 409 mtx_enter(&w_mtx, MTX_SPIN); 410 PCPU_SET(witness_spin_check, witness_spin_check | w->w_level); 411 mtx_exit(&w_mtx, MTX_SPIN); 412 return; 413 } 414 415 if (w->w_spin) 416 panic("mutex_try_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d", 417 m->mtx_description, file, line); 418 419 if (m->mtx_recurse != 0) 420 return; 421 422 w->w_file = file; 423 w->w_line = line; 424 m->mtx_line = line; 425 m->mtx_file = file; 426 p = CURPROC; 427 ASS(m->mtx_held.le_prev == NULL); 428 LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held); 429} 430 431void 432witness_display(void(*prnt)(const char *fmt, ...)) 433{ 434 witness_t *w, *w1; 435 436 witness_levelall(); 437 438 for (w = w_all; w; w = w->w_next) { 439 if (w->w_file == NULL) 440 continue; 441 for (w1 = w_all; w1; w1 = w1->w_next) { 442 if (isitmychild(w1, w)) 443 break; 444 } 445 if (w1 != NULL) 446 continue; 447 /* 448 * This lock has no anscestors, display its descendants. 449 */ 450 witness_displaydescendants(prnt, w); 451 } 452 prnt("\nMutex which were never acquired\n"); 453 for (w = w_all; w; w = w->w_next) { 454 if (w->w_file != NULL) 455 continue; 456 prnt("%s\n", w->w_description); 457 } 458} 459 460int 461witness_sleep(int check_only, mtx_t *mtx, char *file, int line) 462{ 463 mtx_t *m; 464 struct proc *p; 465 char **sleep; 466 int n = 0; 467 468 p = CURPROC; 469 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 470 m = LIST_NEXT(m, mtx_held)) { 471 if (m == mtx) 472 continue; 473 for (sleep = sleep_list; *sleep!= NULL; sleep++) 474 if (strcmp(m->mtx_description, *sleep) == 0) 475 goto next; 476 printf("%s:%d: %s with \"%s\" locked from %s:%d\n", 477 file, line, check_only ? "could sleep" : "sleeping", 478 m->mtx_description, 479 m->mtx_witness->w_file, m->mtx_witness->w_line); 480 n++; 481 next: 482 } 483#ifdef KDEBUG 484 if (witness_kdebug && n) 485 kdebug(); 486#endif /* KDEBUG */ 487 return (n); 488} 489 490static witness_t * 491enroll(char *description, int flag) 492{ 493 int i; 494 witness_t *w, *w1; 495 char **ignore; 496 char **order; 497 498 if (!witness_watch) 499 return (NULL); 500 for (ignore = ignore_list; *ignore != NULL; ignore++) 501 if (strcmp(description, *ignore) == 0) 502 return (NULL); 503 504 if (w_inited == 0) { 505 mtx_init(&w_mtx, "witness lock", MTX_DEF); 506 for (i = 0; i < WITNESS_COUNT; i++) { 507 w = &w_data[i]; 508 witness_free(w); 509 } 510 w_inited = 1; 511 for (order = order_list; *order != NULL; order++) { 512 w = enroll(*order, MTX_DEF); 513 w->w_file = "order list"; 514 for (order++; *order != NULL; order++) { 515 w1 = enroll(*order, MTX_DEF); 516 w1->w_file = "order list"; 517 itismychild(w, w1); 518 w = w1; 519 } 520 } 521 } 522 if ((flag & MTX_SPIN) && witness_skipspin) 523 return (NULL); 524 mtx_enter(&w_mtx, MTX_SPIN); 525 for (w = w_all; w; w = w->w_next) { 526 if (strcmp(description, w->w_description) == 0) { 527 mtx_exit(&w_mtx, MTX_SPIN); 528 return (w); 529 } 530 } 531 if ((w = witness_get()) == NULL) 532 return (NULL); 533 w->w_next = w_all; 534 w_all = w; 535 w->w_description = description; 536 mtx_exit(&w_mtx, MTX_SPIN); 537 if (flag & MTX_SPIN) { 538 w->w_spin = 1; 539 540 i = 1; 541 for (order = spin_order_list; *order != NULL; order++) { 542 if (strcmp(description, *order) == 0) 543 break; 544 i <<= 1; 545 } 546 if (*order == NULL) 547 panic("spin lock %s not in order list", description); 548 w->w_level = i; 549 } 550 return (w); 551} 552 553static int 554itismychild(witness_t *parent, witness_t *child) 555{ 556 static int recursed; 557 558 /* 559 * Insert "child" after "parent" 560 */ 561 while (parent->w_morechildren) 562 parent = parent->w_morechildren; 563 564 if (parent->w_childcnt == WITNESS_NCHILDREN) { 565 if ((parent->w_morechildren = witness_get()) == NULL) 566 return (1); 567 parent = parent->w_morechildren; 568 } 569 ASS(child != NULL); 570 parent->w_children[parent->w_childcnt++] = child; 571 /* 572 * now prune whole tree 573 */ 574 if (recursed) 575 return (0); 576 recursed = 1; 577 for (child = w_all; child != NULL; child = child->w_next) { 578 for (parent = w_all; parent != NULL; 579 parent = parent->w_next) { 580 if (!isitmychild(parent, child)) 581 continue; 582 removechild(parent, child); 583 if (isitmydescendant(parent, child)) 584 continue; 585 itismychild(parent, child); 586 } 587 } 588 recursed = 0; 589 witness_levelall(); 590 return (0); 591} 592 593static void 594removechild(witness_t *parent, witness_t *child) 595{ 596 witness_t *w, *w1; 597 int i; 598 599 for (w = parent; w != NULL; w = w->w_morechildren) 600 for (i = 0; i < w->w_childcnt; i++) 601 if (w->w_children[i] == child) 602 goto found; 603 return; 604found: 605 for (w1 = w; w1->w_morechildren != NULL; w1 = w1->w_morechildren) 606 continue; 607 w->w_children[i] = w1->w_children[--w1->w_childcnt]; 608 ASS(w->w_children[i] != NULL); 609 610 if (w1->w_childcnt != 0) 611 return; 612 613 if (w1 == parent) 614 return; 615 for (w = parent; w->w_morechildren != w1; w = w->w_morechildren) 616 continue; 617 w->w_morechildren = 0; 618 witness_free(w1); 619} 620 621static int 622isitmychild(witness_t *parent, witness_t *child) 623{ 624 witness_t *w; 625 int i; 626 627 for (w = parent; w != NULL; w = w->w_morechildren) { 628 for (i = 0; i < w->w_childcnt; i++) { 629 if (w->w_children[i] == child) 630 return (1); 631 } 632 } 633 return (0); 634} 635 636static int 637isitmydescendant(witness_t *parent, witness_t *child) 638{ 639 witness_t *w; 640 int i; 641 int j; 642 643 for (j = 0, w = parent; w != NULL; w = w->w_morechildren, j++) { 644 ASS(j < 1000); 645 for (i = 0; i < w->w_childcnt; i++) { 646 if (w->w_children[i] == child) 647 return (1); 648 } 649 for (i = 0; i < w->w_childcnt; i++) { 650 if (isitmydescendant(w->w_children[i], child)) 651 return (1); 652 } 653 } 654 return (0); 655} 656 657void 658witness_levelall (void) 659{ 660 witness_t *w, *w1; 661 662 for (w = w_all; w; w = w->w_next) 663 if (!w->w_spin) 664 w->w_level = 0; 665 for (w = w_all; w; w = w->w_next) { 666 if (w->w_spin) 667 continue; 668 for (w1 = w_all; w1; w1 = w1->w_next) { 669 if (isitmychild(w1, w)) 670 break; 671 } 672 if (w1 != NULL) 673 continue; 674 witness_leveldescendents(w, 0); 675 } 676} 677 678static void 679witness_leveldescendents(witness_t *parent, int level) 680{ 681 int i; 682 witness_t *w; 683 684 if (parent->w_level < level) 685 parent->w_level = level; 686 level++; 687 for (w = parent; w != NULL; w = w->w_morechildren) 688 for (i = 0; i < w->w_childcnt; i++) 689 witness_leveldescendents(w->w_children[i], level); 690} 691 692static void 693witness_displaydescendants(void(*prnt)(const char *fmt, ...), witness_t *parent) 694{ 695 witness_t *w; 696 int i; 697 int level = parent->w_level; 698 699 prnt("%d", level); 700 if (level < 10) 701 prnt(" "); 702 for (i = 0; i < level; i++) 703 prnt(" "); 704 prnt("%s", parent->w_description); 705 if (parent->w_file != NULL) { 706 prnt(" -- last acquired @ %s", parent->w_file); 707#ifndef W_USE_WHERE 708 prnt(":%d", parent->w_line); 709#endif 710 prnt("\n"); 711 } 712 713 for (w = parent; w != NULL; w = w->w_morechildren) 714 for (i = 0; i < w->w_childcnt; i++) 715 witness_displaydescendants(prnt, w->w_children[i]); 716 } 717 718static int 719dup_ok(witness_t *w) 720{ 721 char **dup; 722 723 for (dup = dup_list; *dup!= NULL; dup++) 724 if (strcmp(w->w_description, *dup) == 0) 725 return (1); 726 return (0); 727} 728 729static int 730blessed(witness_t *w1, witness_t *w2) 731{ 732 int i; 733 witness_blessed_t *b; 734 735 for (i = 0; i < blessed_count; i++) { 736 b = &blessed_list[i]; 737 if (strcmp(w1->w_description, b->b_lock1) == 0) { 738 if (strcmp(w2->w_description, b->b_lock2) == 0) 739 return (1); 740 continue; 741 } 742 if (strcmp(w1->w_description, b->b_lock2) == 0) 743 if (strcmp(w2->w_description, b->b_lock1) == 0) 744 return (1); 745 } 746 return (0); 747} 748 749static witness_t * 750witness_get() 751{ 752 witness_t *w; 753 754 if ((w = w_free) == NULL) { 755 witness_dead = 1; 756 mtx_exit(&w_mtx, MTX_SPIN); 757 printf("witness exhausted\n"); 758 return (NULL); 759 } 760 w_free = w->w_next; 761 bzero(w, sizeof (*w)); 762 return (w); 763} 764 765static void 766witness_free(witness_t *w) 767{ 768 w->w_next = w_free; 769 w_free = w; 770} 771 772void 773witness_list(struct proc *p) 774{ 775 mtx_t *m; 776 777 for ((m = LIST_FIRST(&p->p_heldmtx)); m != NULL; 778 m = LIST_NEXT(m, mtx_held)) { 779 printf("\t\"%s\" (%p) locked at %s:%d\n", 780 m->mtx_description, m, 781 m->mtx_witness->w_file, m->mtx_witness->w_line); 782 } 783} 784 785void 786witness_save(mtx_t *m, const char **filep, int *linep) 787{ 788 *filep = m->mtx_witness->w_file; 789 *linep = m->mtx_witness->w_line; 790} 791 792void 793witness_restore(mtx_t *m, const char *file, int line) 794{ 795 m->mtx_witness->w_file = file; 796 m->mtx_witness->w_line = line; 797} 798 799#endif /* (defined(SMP_DEBUG) && defined(WITNESS)) */ 800