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. --- 13 unchanged lines hidden (view full) --- 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 67676 2000-10-27 02:59:30Z jhb $ |
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 --- 6 unchanged lines hidden (view full) --- 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_witness.h" 54 |
55#include <sys/param.h> 56#include <sys/bus.h> 57#include <sys/kernel.h> 58#include <sys/malloc.h> 59#include <sys/proc.h> |
60#include <sys/sysctl.h> |
61#include <sys/systm.h> 62#include <sys/vmmeter.h> 63#include <sys/ktr.h> 64 65#include <machine/atomic.h> 66#include <machine/bus.h> 67#include <machine/clock.h> 68#include <machine/cpu.h> --- 609 unchanged lines hidden (view full) --- 678 struct witness *w_children[WITNESS_NCHILDREN]; 679}; 680 681struct witness_blessed { 682 char *b_lock1; 683 char *b_lock2; 684}; 685 |
686#ifdef DDB |
687/* |
688 * When DDB is enabled and witness_ddb is set to 1, it will cause the system to |
689 * drop into kdebug() when: 690 * - a lock heirarchy violation occurs 691 * - locks are held when going to sleep. 692 */ |
693#ifdef WITNESS_DDB 694int witness_ddb = 1; 695#else 696int witness_ddb = 0; |
697#endif |
698SYSCTL_INT(_debug, OID_AUTO, witness_ddb, CTLFLAG_RW, &witness_ddb, 0, ""); 699#endif /* DDB */ |
700 |
701#ifdef WITNESS_SKIPSPIN 702int witness_skipspin = 1; 703#else 704int witness_skipspin = 0; |
705#endif |
706SYSCTL_INT(_debug, OID_AUTO, witness_skipspin, CTLFLAG_RD, &witness_skipspin, 0, 707 ""); |
708 |
709MUTEX_DECLARE(static,w_mtx); |
710static struct witness *w_free; 711static struct witness *w_all; 712static int w_inited; 713static int witness_dead; /* fatal error, probably no memory */ 714 715static struct witness w_data[WITNESS_COUNT]; 716 717static struct witness *enroll __P((const char *description, int flag)); --- 8 unchanged lines hidden (view full) --- 726static void witness_leveldescendents __P((struct witness *parent, int level)); 727static void witness_levelall __P((void)); 728static struct witness * witness_get __P((void)); 729static void witness_free __P((struct witness *m)); 730 731 732static char *ignore_list[] = { 733 "witness lock", |
734 NULL 735}; 736 737static char *spin_order_list[] = { 738 "sched lock", |
739 "clk", 740 "sio", |
741 /* 742 * leaf locks 743 */ |
744 NULL 745}; 746 747static char *order_list[] = { |
748 NULL 749}; 750 751static char *dup_list[] = { |
752 NULL 753}; 754 755static char *sleep_list[] = { 756 "Giant lock", 757 NULL 758}; 759 --- 30 unchanged lines hidden (view full) --- 790 791void 792witness_enter(struct mtx *m, int flags, const char *file, int line) 793{ 794 struct witness *w, *w1; 795 struct mtx *m1; 796 struct proc *p; 797 int i; |
798#ifdef DDB 799 int go_into_ddb = 0; 800#endif /* DDB */ |
801 802 w = m->mtx_witness; 803 p = CURPROC; 804 805 if (flags & MTX_SPIN) { 806 if (!w->w_spin) 807 panic("mutex_enter: MTX_SPIN on MTX_DEF mutex %s @" 808 " %s:%d", m->mtx_description, file, line); --- 35 unchanged lines hidden (view full) --- 844 if ((w1 = m1->mtx_witness) == w) { 845 if (w->w_same_squawked || dup_ok(w)) 846 goto out; 847 w->w_same_squawked = 1; 848 printf("acquring duplicate lock of same type: \"%s\"\n", 849 m->mtx_description); 850 printf(" 1st @ %s:%d\n", w->w_file, w->w_line); 851 printf(" 2nd @ %s:%d\n", file, line); |
852#ifdef DDB 853 go_into_ddb = 1; 854#endif /* DDB */ |
855 goto out; 856 } 857 MPASS(!mtx_owned(&w_mtx)); 858 mtx_enter(&w_mtx, MTX_SPIN); 859 /* 860 * If we have a known higher number just say ok 861 */ 862 if (witness_watch > 1 && w->w_level > w1->w_level) { --- 25 unchanged lines hidden (view full) --- 888 } 889 printf("lock order reversal\n"); 890 printf(" 1st %s last acquired @ %s:%d\n", 891 w->w_description, w->w_file, w->w_line); 892 printf(" 2nd %p %s @ %s:%d\n", 893 m1, w1->w_description, w1->w_file, w1->w_line); 894 printf(" 3rd %p %s @ %s:%d\n", 895 m, w->w_description, file, line); |
896#ifdef DDB 897 go_into_ddb = 1; 898#endif /* DDB */ |
899 goto out; 900 } 901 } 902 m1 = LIST_FIRST(&p->p_heldmtx); 903 if (!itismychild(m1->mtx_witness, w)) 904 mtx_exit(&w_mtx, MTX_SPIN); 905 906out: |
907#ifdef DDB 908 if (witness_ddb && go_into_ddb) 909 Debugger("witness_enter"); 910#endif /* DDB */ |
911 w->w_file = file; 912 w->w_line = line; 913 m->mtx_line = line; 914 m->mtx_file = file; 915 916 /* 917 * If this pays off it likely means that a mutex being witnessed 918 * is acquired in hardclock. Put it in the ignore list. It is --- 117 unchanged lines hidden (view full) --- 1036 goto next; 1037 printf("%s:%d: %s with \"%s\" locked from %s:%d\n", 1038 file, line, check_only ? "could sleep" : "sleeping", 1039 m->mtx_description, 1040 m->mtx_witness->w_file, m->mtx_witness->w_line); 1041 n++; 1042 next: 1043 } |
1044#ifdef DDB 1045 if (witness_ddb && n) 1046 Debugger("witness_sleep"); 1047#endif /* DDB */ |
1048 return (n); 1049} 1050 1051static struct witness * 1052enroll(const char *description, int flag) 1053{ 1054 int i; 1055 struct witness *w, *w1; 1056 char **ignore; 1057 char **order; 1058 1059 if (!witness_watch) 1060 return (NULL); 1061 for (ignore = ignore_list; *ignore != NULL; ignore++) 1062 if (strcmp(description, *ignore) == 0) 1063 return (NULL); 1064 1065 if (w_inited == 0) { |
1066 mtx_init(&w_mtx, "witness lock", MTX_COLD | MTX_DEF); |
1067 for (i = 0; i < WITNESS_COUNT; i++) { 1068 w = &w_data[i]; 1069 witness_free(w); 1070 } 1071 w_inited = 1; 1072 for (order = order_list; *order != NULL; order++) { 1073 w = enroll(*order, MTX_DEF); 1074 w->w_file = "order list"; --- 287 unchanged lines hidden --- |