xref: /original-bsd/sys/kern/subr_prof.c (revision f0fd5f8a)
1 /*	subr_prof.c	4.3	82/12/17	*/
2 
3 #ifdef GPROF
4 #include "../h/crt0.h"
5 #include "../h/param.h"
6 #include "../h/systm.h"
7 
8 /*
9  * Froms is actually a bunch of unsigned shorts indexing tos
10  */
11 int	profiling = 3;
12 u_short	*froms = 0;
13 struct	tostruct *tos = 0;
14 u_short	tolimit = 0;
15 #ifdef vax
16 char	*s_lowpc = (char *)0x80000000;
17 #endif
18 #ifdef sun
19 char	*s_lowpc = (char *)0x4000;
20 #endif
21 extern	char etext;
22 char	*s_highpc = &etext;
23 u_long	s_textsize = 0;
24 int	ssiz;
25 u_short	*sbuf;
26 u_short	*kcount;
27 
28 kmstartup()
29 {
30 	u_long	limit;
31 
32 	s_textsize = s_highpc - s_lowpc;
33 	ssiz = s_textsize + sizeof(struct phdr);
34 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
35 		s_textsize, s_lowpc, s_highpc);
36 	sbuf = (u_short *)wmemall(memall, ssiz);
37 	if (sbuf == 0) {
38 		printf("No space for monitor buffer(s)\n");
39 		return;
40 	}
41 	blkclr((caddr_t)sbuf, ssiz);
42 	froms = (u_short *)wmemall(memall, s_textsize);
43 	if (froms == 0) {
44 		printf("No space for monitor buffer(s)\n");
45 		wmemfree(sbuf, ssiz);
46 		sbuf = 0;
47 		return;
48 	}
49 	blkclr((caddr_t)froms, s_textsize);
50 	tos = (struct tostruct *)wmemall(memall, s_textsize);
51 	if (tos == 0) {
52 		printf("No space for monitor buffer(s)\n");
53 		wmemfree(sbuf, ssiz);
54 		sbuf = 0;
55 		wmemfree(froms, s_textsize);
56 		froms = 0;
57 		return;
58 	}
59 	blkclr((caddr_t)tos, s_textsize);
60 	tos[0].link = 0;
61 	limit = s_textsize / sizeof(struct tostruct);
62 	/*
63 	 * Tolimit is what mcount checks to see if
64 	 * all the data structures are ready!!!
65 	 * Make sure it won't overflow.
66 	 */
67 	tolimit = limit > 65534 ? 65534 : limit;
68 	((struct phdr *)sbuf)->lpc = s_lowpc;
69 	((struct phdr *)sbuf)->hpc = s_highpc;
70 	((struct phdr *)sbuf)->ncnt = ssiz;
71 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
72 #ifdef notdef
73 	profiling = 0;		/* patch by hand when you're ready */
74 #endif
75 }
76 
77 #ifdef vax
78 /*
79  * This routine is massaged so that it may be jsb'ed to
80  */
81 asm("#define _mcount mcount");
82 mcount()
83 {
84 	register char *selfpc;		/* r11 */
85 	register u_short *frompcindex;	/* r10 */
86 	register struct tostruct *top;	/* r9 */
87 
88 	asm("	forgot to run ex script on gcrt0.s");
89 	asm("#define r11 r5");
90 	asm("#define r10 r4");
91 	asm("#define r9 r3");
92 #ifdef lint
93 	selfpc = (char *) 0;
94 	frompcindex = 0;
95 #else not lint
96 	/*
97 	 * Find the return address for mcount,
98 	 * and the return address for mcount's caller.
99 	 */
100 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
101 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
102 #endif not lint
103 	/*
104 	 * Check that we are profiling
105 	 * and that we aren't recursively invoked.
106 	 */
107 	if (tolimit == 0)
108 		goto out;
109 	if (profiling)
110 		goto out;
111 	profiling++;
112 	/*
113 	 * Check that frompcindex is a reasonable pc value.
114 	 * For example:	signal catchers get called from the stack,
115 	 * 		not from text space.  too bad.
116 	 */
117 	frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc);
118 	if ((u_long)frompcindex > s_textsize)
119 		goto done;
120 	frompcindex = &froms[((long)frompcindex) >> 1];
121 	if (*frompcindex != 0)
122 		top = &tos[*frompcindex];
123 	else {
124 		*frompcindex = ++tos[0].link;
125 		if (*frompcindex >= tolimit)
126 			goto overflow;
127 		top = &tos[*frompcindex];
128 		top->selfpc = selfpc;
129 		top->count = 0;
130 		top->link = 0;
131 	}
132 	for (; /* break */; top = &tos[top->link]) {
133 		if (top->selfpc == selfpc) {
134 			top->count++;
135 			break;
136 		}
137 		if (top->link != 0)
138 			continue;
139 		top->link = ++tos[0].link;
140 		if (top->link >= tolimit)
141 			goto overflow;
142 		top = &tos[top->link];
143 		top->selfpc = selfpc;
144 		top->count = 1;
145 		top->link = 0;
146 		break;
147 	}
148 done:
149 	profiling--;
150 	/* and fall through */
151 out:
152 	asm("	rsb");
153 	asm("#undef r11");
154 	asm("#undef r10");
155 	asm("#undef r9");
156 	asm("#undef _mcount");
157 
158 overflow:
159 	tolimit = 0;
160 	printf("mcount: tos overflow\n");
161 	goto out;
162 }
163 #endif
164 #endif GPROF
165