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