1 | /* $Id$ $Revision$ */ |
2 | /* vim:set shiftwidth=4 ts=8: */ |
3 | |
4 | /************************************************************************* |
5 | * Copyright (c) 2011 AT&T Intellectual Property |
6 | * All rights reserved. This program and the accompanying materials |
7 | * are made available under the terms of the Eclipse Public License v1.0 |
8 | * which accompanies this distribution, and is available at |
9 | * http://www.eclipse.org/legal/epl-v10.html |
10 | * |
11 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ |
12 | *************************************************************************/ |
13 | |
14 | #include "vmhdr.h" |
15 | |
16 | /* Turn on tracing for regions |
17 | ** |
18 | ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94. |
19 | */ |
20 | |
21 | static int Trfile = -1; |
22 | static char Trbuf[128]; |
23 | |
24 | static char *trstrcpy(char *to, char *from, int endc) |
25 | { |
26 | reg int n; |
27 | |
28 | n = strlen(from); |
29 | memcpy(to, from, n); |
30 | to += n; |
31 | if ((*to = endc)) |
32 | to += 1; |
33 | return to; |
34 | } |
35 | |
36 | /* |
37 | * convert a long value to an ascii representation |
38 | * |
39 | * @param v value to convert |
40 | * @param type =0 base-16, >0: unsigned base-10, <0: signed base-10 |
41 | */ |
42 | static char *tritoa(Vmulong_t v, int type) |
43 | { |
44 | char *s; |
45 | |
46 | s = &Trbuf[sizeof(Trbuf) - 1]; |
47 | *s-- = '\0'; |
48 | |
49 | if (type == 0) { /* base-16 */ |
50 | reg char *digit = "0123456789abcdef" ; |
51 | do { |
52 | *s-- = digit[v & 0xf]; |
53 | v >>= 4; |
54 | } while (v); |
55 | *s-- = 'x'; |
56 | *s-- = '0'; |
57 | } else if (type > 0) { /* unsigned base-10 */ |
58 | do { |
59 | *s-- = (char) ('0' + (v % 10)); |
60 | v /= 10; |
61 | } while (v); |
62 | } else { /* signed base-10 */ |
63 | int sign = ((long) v < 0); |
64 | if (sign) |
65 | v = (Vmulong_t) (-((long) v)); |
66 | do { |
67 | *s-- = (char) ('0' + (v % 10)); |
68 | v /= 10; |
69 | } while (v); |
70 | if (sign) |
71 | *s-- = '-'; |
72 | } |
73 | |
74 | return s + 1; |
75 | } |
76 | |
77 | /** |
78 | * generate a trace of some call |
79 | * @param vm region call was made from |
80 | * @param newaddr old data address |
81 | * @param newaddr new data address |
82 | * @param size size of piece |
83 | * @param align alignment |
84 | */ |
85 | static void trtrace(Vmalloc_t * vm, |
86 | Vmuchar_t * oldaddr, Vmuchar_t * newaddr, size_t size, |
87 | size_t align) |
88 | { |
89 | char buf[1024], *bufp, *endbuf; |
90 | reg Vmdata_t *vd = vm->data; |
91 | reg char *file = NIL(char *); |
92 | reg int line = 0; |
93 | int type; |
94 | #define SLOP 32 |
95 | |
96 | if (oldaddr == (Vmuchar_t *) (-1)) { /* printing busy blocks */ |
97 | type = 0; |
98 | oldaddr = NIL(Vmuchar_t *); |
99 | } else { |
100 | type = vd->mode & VM_METHODS; |
101 | VMFILELINE(vm, file, line); |
102 | } |
103 | |
104 | if (Trfile < 0) |
105 | return; |
106 | |
107 | bufp = buf; |
108 | endbuf = buf + sizeof(buf); |
109 | bufp = trstrcpy(bufp, tritoa(oldaddr ? VLONG(oldaddr) : 0L, 0), ':'); |
110 | bufp = trstrcpy(bufp, tritoa(newaddr ? VLONG(newaddr) : 0L, 0), ':'); |
111 | bufp = trstrcpy(bufp, tritoa((Vmulong_t) size, 1), ':'); |
112 | bufp = trstrcpy(bufp, tritoa((Vmulong_t) align, 1), ':'); |
113 | bufp = trstrcpy(bufp, tritoa(VLONG(vm), 0), ':'); |
114 | if (type & VM_MTBEST) |
115 | bufp = trstrcpy(bufp, "best" , ':'); |
116 | else if (type & VM_MTLAST) |
117 | bufp = trstrcpy(bufp, "last" , ':'); |
118 | else if (type & VM_MTPOOL) |
119 | bufp = trstrcpy(bufp, "pool" , ':'); |
120 | else if (type & VM_MTPROFILE) |
121 | bufp = trstrcpy(bufp, "profile" , ':'); |
122 | else if (type & VM_MTDEBUG) |
123 | bufp = trstrcpy(bufp, "debug" , ':'); |
124 | else |
125 | bufp = trstrcpy(bufp, "busy" , ':'); |
126 | if (file && file[0] && line > 0 |
127 | && (bufp + strlen(file) + SLOP) < endbuf) { |
128 | bufp = trstrcpy(bufp, file, ','); |
129 | bufp = trstrcpy(bufp, tritoa((Vmulong_t) line, 1), ':'); |
130 | } |
131 | *bufp++ = '\n'; |
132 | *bufp = '\0'; |
133 | |
134 | write(Trfile, buf, (bufp - buf)); |
135 | } |
136 | |
137 | int vmtrace(int file) |
138 | { |
139 | int fd; |
140 | |
141 | _Vmstrcpy = trstrcpy; |
142 | _Vmitoa = tritoa; |
143 | _Vmtrace = trtrace; |
144 | |
145 | fd = Trfile; |
146 | Trfile = file; |
147 | return fd; |
148 | } |
149 | |
150 | int vmtrbusy(Vmalloc_t * vm) |
151 | { |
152 | Seg_t *seg; |
153 | Vmdata_t *vd = vm->data; |
154 | |
155 | if (Trfile < 0 |
156 | || !(vd->mode & (VM_MTBEST | VM_MTDEBUG | VM_MTPROFILE))) |
157 | return -1; |
158 | |
159 | for (seg = vd->seg; seg; seg = seg->next) { |
160 | Block_t *b, *endb; |
161 | Vmuchar_t *data; |
162 | size_t s; |
163 | |
164 | for (b = SEGBLOCK(seg), endb = BLOCK(seg->baddr); b < endb;) { |
165 | if (ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b))) |
166 | continue; |
167 | |
168 | data = DATA(b); |
169 | if (vd->mode & VM_MTDEBUG) { |
170 | data = DB2DEBUG(data); |
171 | s = DBSIZE(data); |
172 | } else if (vd->mode & VM_MTPROFILE) |
173 | s = PFSIZE(data); |
174 | else |
175 | s = SIZE(b) & ~BITS; |
176 | |
177 | trtrace(vm, (Vmuchar_t *) (-1), data, s, 0); |
178 | |
179 | b = (Block_t *) ((Vmuchar_t *) DATA(b) + (SIZE(b) & ~BITS)); |
180 | } |
181 | } |
182 | |
183 | return 0; |
184 | } |
185 | |