xref: /plan9-contrib/sys/src/libc/port/profile.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	<u.h>
2 #include	<libc.h>
3 
4 extern	long*	_clock;
5 extern	long	_callpc(void**);
6 extern	long	_savearg(void);
7 
8 typedef	struct	Plink	Plink;
9 struct	Plink
10 {
11 	Plink	*old;		/* known to be 0(ptr) */
12 	Plink	*down;
13 	Plink	*link;
14 	long	pc;
15 	long	count;
16 	long	time;		/* known to be 20(ptr) */
17 };
18 
19 struct
20 {
21 	Plink	*pp;		/* known to be 0(ptr) */
22 	Plink	*next;		/* known to be 4(ptr) */
23 	Plink	*last;
24 	Plink	*first;
25 } __prof;
26 
27 ulong
28 _profin(void)
29 {
30 	void *dummy;
31 	long pc;
32 	Plink *pp, *p;
33 	ulong arg;
34 
35 	arg = _savearg();
36 	pc = _callpc(&dummy);
37 	pp = __prof.pp;
38 	if(pp == 0)
39 		return arg;
40 
41 	for(p=pp->down; p; p=p->link)
42 		if(p->pc == pc)
43 			goto out;
44 	p = __prof.next + 1;
45 	if(p >= __prof.last) {
46 		__prof.pp = 0;
47 		write(2, "/env/profsize too small\n", 24);
48 		return arg;
49 	}
50 	__prof.next = p;
51 	p->link = pp->down;
52 	pp->down = p;
53 	p->pc = pc;
54 	p->old = pp;
55 	p->down = 0;
56 	p->count = 0;
57 
58 out:
59 	__prof.pp = p;
60 	p->count++;
61 	p->time += *_clock;
62 	return arg;		/* disgusting linkage */
63 }
64 
65 ulong
66 _profout(void)
67 {
68 	Plink *p;
69 	ulong arg;
70 
71 	arg = _savearg();
72 	p = __prof.pp;
73 	if(p) {
74 		p->time -= *_clock;
75 		__prof.pp = p->old;
76 	}
77 	return arg;
78 }
79 
80 void
81 _profdump(void)
82 {
83 	int f;
84 	long n;
85 	Plink *p;
86 	char *vp;
87 
88 	__prof.pp = 0;
89 	f = create("prof.out", 1, 0666);
90 	if(f < 0) {
91 		perror("create prof.out");
92 		return;
93 	}
94 	__prof.first->time = -*_clock;
95 	vp = (char*)__prof.first;
96 	for(p = __prof.first; p <= __prof.next; p++) {
97 		/*
98 		 * short down
99 		 */
100 		n = 0xffff;
101 		if(p->down)
102 			n = p->down - __prof.first;
103 		vp[0] = n>>8;
104 		vp[1] = n;
105 
106 		/*
107 		 * short right
108 		 */
109 		n = 0xffff;
110 		if(p->link)
111 			n = p->link - __prof.first;
112 		vp[2] = n>>8;
113 		vp[3] = n;
114 		vp += 4;
115 
116 		/*
117 		 * long pc
118 		 */
119 		n = p->pc;
120 		vp[0] = n>>24;
121 		vp[1] = n>>16;
122 		vp[2] = n>>8;
123 		vp[3] = n;
124 		vp += 4;
125 
126 		/*
127 		 * long count
128 		 */
129 		n = p->count;
130 		vp[0] = n>>24;
131 		vp[1] = n>>16;
132 		vp[2] = n>>8;
133 		vp[3] = n;
134 		vp += 4;
135 
136 		/*
137 		 * long time
138 		 */
139 		n = -p->time;
140 		vp[0] = n>>24;
141 		vp[1] = n>>16;
142 		vp[2] = n>>8;
143 		vp[3] = n;
144 		vp += 4;
145 	}
146 	write(f, (char*)__prof.first, vp - (char*)__prof.first);
147 	close(f);
148 }
149 
150 void
151 _profmain(void)
152 {
153 	char ename[50];
154 	int n, f;
155 
156 	n = 2000;
157 	f = open("/env/profsize", OREAD);
158 	if(f >= 0) {
159 		memset(ename, 0, sizeof(ename));
160 		read(f, ename, sizeof(ename)-1);
161 		close(f);
162 		n = atol(ename);
163 	}
164 	__prof.first = sbrk(n*sizeof(Plink));
165 	__prof.last = sbrk(0);
166 	__prof.next = __prof.first;
167 	atexit(_profdump);
168 	*_clock = 1;
169 }
170