xref: /illumos-gate/usr/src/uts/common/os/unix_bb.c (revision 16b76d3cb933ff92018a2a75594449010192eacb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1997 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * Kernel Basic Block Profiling - profiling initialization hooks
29  */
30 
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/t_lock.h>
34 #include <sys/cpuvar.h>
35 #include <sys/systm.h>
36 #include <sys/spl.h>
37 #include <sys/unix_bb_info.h>
38 
39 #ifdef KCOV
40 
41 /*
42  * routines to do kernel basic block coverage.
43  */
44 
45 struct bb_info	*unix_bb_list;
46 lock_t		unix_bb_lock;
47 
48 /*
49  *  There is the potential that we will be called by any C routine.
50  *  So we avoid calling any C routines from here, as we'll get
51  *  a recursive call.
52  *  Also, we wish to avoid a deadlock due to being called by
53  *  an interrupt handler, so we lock at the NMI level.
54  *  Of course, that leaves the possibility that we'll
55  *  be called from an NMI handler.  If the lock is available,
56  *  fine, otherwise, if we're on the interrupt stack at the
57  *  NMI level, we just return.
58  *
59  *  We will probably get another chance to add the bb_info structure
60  *  to the list, since the bb_info structure is for the entire object file.
61  */
62 #ifdef	KCOV_TEST
63 int		unix_bb_a, unix_bb_b, unix_bb_c;
64 int		unix_bb_d, unix_bb_e, unix_bb_f, unix_bb_g;
65 processorid_t	bb_last_who;
66 char 		*bb_last_where;
67 #endif
68 
69 void
70 __bb_init_func(struct bb_info *bb)
71 {
72 	u_short s;
73 
74 /*
75  *	a = c + g
76  *	b = c + d
77  *	a = c + e
78  *	e = g
79  *
80  *	a->b->c
81  *	a->b->d->e->g
82  *	a->b->d->e->f->g
83  *	a->e->g
84  *	a->e->f->g
85  */
86 
87 	/*
88 	 *  Raise the pil and try to get the lock.
89 	 */
90 	s = spl8();
91 #ifdef	KCOV_TEST
92 	unix_bb_a++;
93 #endif
94 
95 	if (!lock_try(&unix_bb_lock)) {
96 		/*
97 		 *  If we're on the interrrupt stack, we just return
98 		 *  in case it's an NMI and we're looking at a deadlock
99 		 *  situation.  Otherwise, we use lock_set_spl()
100 		 */
101 #ifdef	KCOV_TEST
102 		unix_bb_b++;
103 #endif
104 		if (CPU_ON_INTR(CPU)) {
105 #ifdef	KCOV_TEST
106 			unix_bb_c++;
107 #endif
108 			splx(s);
109 			return;
110 		}
111 #ifdef	KCOV_TEST
112 		unix_bb_d++;
113 #endif
114 		splx(s);
115 		lock_set_spl(&unix_bb_lock, ipltospl(NMI_LEVEL), &s);
116 	}
117 
118 #ifdef	KCOV_TEST
119 	bb_last_who = CPU->cpu_id;
120 	bb_last_where = bb->bb_filename;
121 	unix_bb_e++;
122 #endif
123 	/*
124 	 *  We've got the lock.  If we have not been initialized, add us
125 	 *  to the list and set the initialized flag.
126 	 */
127 #ifdef	KCOV_TEST
128 	if (bb->bb_next == 0) {
129 		unix_bb_f++;
130 #else
131 	if (bb->bb_initflag == 0) {
132 		bb->bb_initflag = 1;
133 #endif
134 		bb->bb_next = unix_bb_list;
135 		unix_bb_list = bb;
136 	}
137 
138 #ifdef	KCOV_TEST
139 	unix_bb_g++;
140 #endif
141 	lock_clear_splx(&unix_bb_lock, s);
142 }
143 #endif /* KCOV */
144