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
21static int Trfile = -1;
22static char Trbuf[128];
23
24static 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 */
42static 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 */
85static 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
137int 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
150int 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