aboutsummaryrefslogtreecommitdiff
path: root/sys/nmemio/mgc.x
blob: 8ef2b58c4e92e088c8b7c72a0e69b199adfbe928 (plain) (blame)
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