xref: /illumos-gate/usr/src/uts/common/os/unix_bb.c (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Kernel Basic Block Profiling - profiling initialization hooks
31  */
32 
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/t_lock.h>
36 #include <sys/cpuvar.h>
37 #include <sys/systm.h>
38 #include <sys/spl.h>
39 #include <sys/unix_bb_info.h>
40 
41 #ifdef KCOV
42 
43 /*
44  * routines to do kernel basic block coverage.
45  */
46 
47 struct bb_info	*unix_bb_list;
48 lock_t		unix_bb_lock;
49 
50 /*
51  *  There is the potential that we will be called by any C routine.
52  *  So we avoid calling any C routines from here, as we'll get
53  *  a recursive call.
54  *  Also, we wish to avoid a deadlock due to being called by
55  *  an interrupt handler, so we lock at the NMI level.
56  *  Of course, that leaves the possibility that we'll
57  *  be called from an NMI handler.  If the lock is available,
58  *  fine, otherwise, if we're on the interrupt stack at the
59  *  NMI level, we just return.
60  *
61  *  We will probably get another chance to add the bb_info structure
62  *  to the list, since the bb_info structure is for the entire object file.
63  */
64 #ifdef	KCOV_TEST
65 int		unix_bb_a, unix_bb_b, unix_bb_c;
66 int		unix_bb_d, unix_bb_e, unix_bb_f, unix_bb_g;
67 processorid_t	bb_last_who;
68 char 		*bb_last_where;
69 #endif
70 
71 void
72 __bb_init_func(struct bb_info *bb)
73 {
74 	u_short s;
75 
76 /*
77  *	a = c + g
78  *	b = c + d
79  *	a = c + e
80  *	e = g
81  *
82  *	a->b->c
83  *	a->b->d->e->g
84  *	a->b->d->e->f->g
85  *	a->e->g
86  *	a->e->f->g
87  */
88 
89 	/*
90 	 *  Raise the pil and try to get the lock.
91 	 */
92 	s = spl8();
93 #ifdef	KCOV_TEST
94 	unix_bb_a++;
95 #endif
96 
97 	if (!lock_try(&unix_bb_lock)) {
98 		/*
99 		 *  If we're on the interrrupt stack, we just return
100 		 *  in case it's an NMI and we're looking at a deadlock
101 		 *  situation.  Otherwise, we use lock_set_spl()
102 		 */
103 #ifdef	KCOV_TEST
104 		unix_bb_b++;
105 #endif
106 		if (CPU_ON_INTR(CPU)) {
107 #ifdef	KCOV_TEST
108 			unix_bb_c++;
109 #endif
110 			splx(s);
111 			return;
112 		}
113 #ifdef	KCOV_TEST
114 		unix_bb_d++;
115 #endif
116 		splx(s);
117 		lock_set_spl(&unix_bb_lock, ipltospl(NMI_LEVEL), &s);
118 	}
119 
120 #ifdef	KCOV_TEST
121 	bb_last_who = CPU->cpu_id;
122 	bb_last_where = bb->bb_filename;
123 	unix_bb_e++;
124 #endif
125 	/*
126 	 *  We've got the lock.  If we have not been initialized, add us
127 	 *  to the list and set the initialized flag.
128 	 */
129 #ifdef	KCOV_TEST
130 	if (bb->bb_next == 0) {
131 		unix_bb_f++;
132 #else
133 	if (bb->bb_initflag == 0) {
134 		bb->bb_initflag = 1;
135 #endif
136 		bb->bb_next = unix_bb_list;
137 		unix_bb_list = bb;
138 	}
139 
140 #ifdef	KCOV_TEST
141 	unix_bb_g++;
142 #endif
143 	lock_clear_splx(&unix_bb_lock, s);
144 }
145 #endif /* KCOV */
146