1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <mach.h>
# MGC Interface - Simple memory garbage collector interface. Our strategy
# here is simply to store the pointer and its type (so we can dereference to
# a host pointer). As pointers are allocated they are saved here, and when
# freed the pointer value is made negative to indicate it is invalid and
# that slot is available for later reuse.
# When a task completes, we run through the buffer looking for un-freed
# pointers and manually reclaim the space. This is not especially clever but
# we are only used (presumably by developers) when requested so normal use
# of MEMIO should see no added overhead.
#
# mgc_init ()
# mgc_close ()
# mgc_save (ptr, dtype)
# mgc_update (ptr)
# index = mgc_getindex (ptr)
# type = mgc_gettype (ptr)
# mgc_collect ()
define SZ_GC_BUFFER 10240
# A zero-indexed structure saving the (ptr,type) pairs.
define GC_PTR Memi[$1+($2 * 2)]
define GC_TYPE Memi[$1+($2 * 2 + 1)]
# MGC_INIT -- Initialize the MGC interface.
procedure mgc_init ()
include "nmemio.com"
begin
if (mcollect > 0)
call calloc (mgc, SZ_GC_BUFFER, TY_STRUCT)
else
mgc = NULL
end
# MGC_CLOSE -- Close the MGC buffer.
procedure mgc_close ()
include "nmemio.com"
begin
if (mcollect > 0 && mgc != NULL) {
call mfree (mgc, TY_STRUCT)
mgc = NULL
}
end
# MGC_SAVE -- Save a pointer in the GC buffer.
procedure mgc_save (ptr, dtype)
pointer ptr #i pointer to save
int dtype #i pointer type
int i, bmax
include "nmemio.com"
begin
if (mcollect <= 0 || mgc == NULL)
return
bmax = SZ_GC_BUFFER - 1
for (i=0; i < bmax; i=i+1) {
if (GC_PTR(mgc,i) <= 0) {
# Space is re-used if negative, otherwise first free slot.
GC_PTR(mgc,i) = ptr
GC_TYPE(mgc,i) = dtype
if (mdebug > 0) {
call eprintf ("save %d: ptr 0x%x\n")
call pargi (i); call pargi (GC_PTR(mgc,i))
}
return
}
}
# If we get this far we've exhausted the GC buffer. Print a warning
# if reporting and just ignore it since the chances this would be
# a leaked pointer are rather small.
if (mreport > 0)
call eprintf ("Warning: GC buffer overflow\n")
end
# MGC_UPDATE -- Update the status of the pointer in the GC buffer.
procedure mgc_update (ptr)
pointer ptr #i pointer to save
int i, bmax
include "nmemio.com"
begin
if (mgc == NULL || in_task == 0)
return
if (in_task > 0 && mdebug > 0) {
call eprintf ("update 0x%x collect = %d\n")
call pargi (ptr)
call pargi (mcollect)
}
bmax = SZ_GC_BUFFER - 1
do i = 0, bmax {
if (GC_PTR(mgc,i) == ptr) {
if (in_task > 0 && mdebug > 0) {
call eprintf ("update %d: 0x%x %d\n")
call pargi (i); call pargi (GC_PTR(mgc,i)); call pargi (ptr)
}
GC_PTR(mgc,i) = (- ptr)
return
}
if (GC_PTR(mgc,i) == NULL)
return
}
end
# MGC_GETINDEX -- Given a pointer, return its GC index.
int procedure mgc_getindex (ptr)
pointer ptr #i pointer to save
int i, bmax
include "nmemio.com"
begin
if (mcollect <= 0 || mgc == NULL)
return
bmax = SZ_GC_BUFFER - 1
do i = 0, bmax {
if (abs (GC_PTR(mgc,i)) == ptr)
return (i)
if (GC_PTR(mgc,i) == NULL)
return (NULL)
}
return (NULL)
end
# MGC_GETTYPE -- Given a pointer, return its type.
int procedure mgc_gettype (ptr)
pointer ptr #i pointer to save
int i, bmax
include "nmemio.com"
begin
if (mcollect <= 0 || mgc == NULL)
return
bmax = SZ_GC_BUFFER - 1
do i = 0, bmax {
if (abs (GC_PTR(mgc,i)) == ptr)
return (GC_TYPE(mgc,i))
if (GC_PTR(mgc,i) == NULL)
return (NULL)
}
return (NULL)
end
# MGC_COLLECT -- Do the final garbage collection.
procedure mgc_collect ()
int i, bmax, nchars
pointer bp
int sizeof ()
pointer coerce ()
include "nmemio.com"
begin
if (mcollect <= 0 || mgc == NULL)
return
mcollect = -1
bmax = SZ_GC_BUFFER - 1
do i = 0, bmax {
if (GC_PTR(mgc,i) > 0) {
if (mdebug > 0) {
call eprintf ("collect %d: recovering ptr 0x%x\n")
call pargi (i); call pargi (GC_PTR(mgc,i))
}
bp = coerce (GC_PTR(mgc,i), GC_TYPE(mgc,i), TY_INT)
nleaked = nleaked + 1
nchars = Memi[bp - 2] * sizeof (GC_TYPE(mgc,i))
leaked = leaked + (nchars * SZB_CHAR)
call mfree (GC_PTR(mgc,i), GC_TYPE(mgc,i))
} else if (GC_PTR(mgc,i) == NULL)
return
}
end
|