Annotation of OpenXM_contrib2/asir2000/gc/mark_rts.c, Revision 1.1.1.1
1.1 noro 1: /*
2: * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3: * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4: *
5: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
6: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
7: *
8: * Permission is hereby granted to use or copy this program
9: * for any purpose, provided the above notices are retained on all copies.
10: * Permission to modify the code and to distribute modified code is granted,
11: * provided the above notices are retained, and a notice that the code was
12: * modified is included with the above copyright notice.
13: */
14: /* Boehm, October 9, 1995 1:06 pm PDT */
15: # include <stdio.h>
16: # include "gc_priv.h"
17:
18: /* Data structure for list of root sets. */
19: /* We keep a hash table, so that we can filter out duplicate additions. */
20: /* Under Win32, we need to do a better job of filtering overlaps, so */
21: /* we resort to sequential search, and pay the price. */
22: /* This is really declared in gc_priv.h:
23: struct roots {
24: ptr_t r_start;
25: ptr_t r_end;
26: # ifndef MSWIN32
27: struct roots * r_next;
28: # endif
29: GC_bool r_tmp;
30: -- Delete before registering new dynamic libraries
31: };
32:
33: struct roots GC_static_roots[MAX_ROOT_SETS];
34: */
35:
36: static int n_root_sets = 0;
37:
38: /* GC_static_roots[0..n_root_sets) contains the valid root sets. */
39:
40: # if !defined(NO_DEBUGGING)
41: /* For debugging: */
42: void GC_print_static_roots()
43: {
44: register int i;
45: size_t total = 0;
46:
47: for (i = 0; i < n_root_sets; i++) {
48: GC_printf2("From 0x%lx to 0x%lx ",
49: (unsigned long) GC_static_roots[i].r_start,
50: (unsigned long) GC_static_roots[i].r_end);
51: if (GC_static_roots[i].r_tmp) {
52: GC_printf0(" (temporary)\n");
53: } else {
54: GC_printf0("\n");
55: }
56: total += GC_static_roots[i].r_end - GC_static_roots[i].r_start;
57: }
58: GC_printf1("Total size: %ld\n", (unsigned long) total);
59: if (GC_root_size != total) {
60: GC_printf1("GC_root_size incorrect: %ld!!\n",
61: (unsigned long) GC_root_size);
62: }
63: }
64: # endif /* NO_DEBUGGING */
65:
66: /* Primarily for debugging support: */
67: /* Is the address p in one of the registered static */
68: /* root sections? */
69: GC_bool GC_is_static_root(p)
70: ptr_t p;
71: {
72: static int last_root_set = 0;
73: register int i;
74:
75:
76: if (p >= GC_static_roots[last_root_set].r_start
77: && p < GC_static_roots[last_root_set].r_end) return(TRUE);
78: for (i = 0; i < n_root_sets; i++) {
79: if (p >= GC_static_roots[i].r_start
80: && p < GC_static_roots[i].r_end) {
81: last_root_set = i;
82: return(TRUE);
83: }
84: }
85: return(FALSE);
86: }
87:
88: #ifndef MSWIN32
89: /*
90: # define LOG_RT_SIZE 6
91: # define RT_SIZE (1 << LOG_RT_SIZE) -- Power of 2, may be != MAX_ROOT_SETS
92:
93: struct roots * GC_root_index[RT_SIZE];
94: -- Hash table header. Used only to check whether a range is
95: -- already present.
96: -- really defined in gc_priv.h
97: */
98:
99: static int rt_hash(addr)
100: char * addr;
101: {
102: word result = (word) addr;
103: # if CPP_WORDSZ > 8*LOG_RT_SIZE
104: result ^= result >> 8*LOG_RT_SIZE;
105: # endif
106: # if CPP_WORDSZ > 4*LOG_RT_SIZE
107: result ^= result >> 4*LOG_RT_SIZE;
108: # endif
109: result ^= result >> 2*LOG_RT_SIZE;
110: result ^= result >> LOG_RT_SIZE;
111: result &= (RT_SIZE-1);
112: return(result);
113: }
114:
115: /* Is a range starting at b already in the table? If so return a */
116: /* pointer to it, else NIL. */
117: struct roots * GC_roots_present(b)
118: char *b;
119: {
120: register int h = rt_hash(b);
121: register struct roots *p = GC_root_index[h];
122:
123: while (p != 0) {
124: if (p -> r_start == (ptr_t)b) return(p);
125: p = p -> r_next;
126: }
127: return(FALSE);
128: }
129:
130: /* Add the given root structure to the index. */
131: static void add_roots_to_index(p)
132: struct roots *p;
133: {
134: register int h = rt_hash(p -> r_start);
135:
136: p -> r_next = GC_root_index[h];
137: GC_root_index[h] = p;
138: }
139:
140: # else /* MSWIN32 */
141:
142: # define add_roots_to_index(p)
143:
144: # endif
145:
146:
147:
148:
149: word GC_root_size = 0;
150:
151: void GC_add_roots(b, e)
152: char * b; char * e;
153: {
154: DCL_LOCK_STATE;
155:
156: DISABLE_SIGNALS();
157: LOCK();
158: GC_add_roots_inner(b, e, FALSE);
159: UNLOCK();
160: ENABLE_SIGNALS();
161: }
162:
163:
164: /* Add [b,e) to the root set. Adding the same interval a second time */
165: /* is a moderately fast noop, and hence benign. We do not handle */
166: /* different but overlapping intervals efficiently. (We do handle */
167: /* them correctly.) */
168: /* Tmp specifies that the interval may be deleted before */
169: /* reregistering dynamic libraries. */
170: void GC_add_roots_inner(b, e, tmp)
171: char * b; char * e;
172: GC_bool tmp;
173: {
174: struct roots * old;
175:
176: # ifdef MSWIN32
177: /* Spend the time to ensure that there are no overlapping */
178: /* or adjacent intervals. */
179: /* This could be done faster with e.g. a */
180: /* balanced tree. But the execution time here is */
181: /* virtually guaranteed to be dominated by the time it */
182: /* takes to scan the roots. */
183: {
184: register int i;
185:
186: for (i = 0; i < n_root_sets; i++) {
187: old = GC_static_roots + i;
188: if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
189: if ((ptr_t)b < old -> r_start) {
190: old -> r_start = (ptr_t)b;
191: GC_root_size += (old -> r_start - (ptr_t)b);
192: }
193: if ((ptr_t)e > old -> r_end) {
194: old -> r_end = (ptr_t)e;
195: GC_root_size += ((ptr_t)e - old -> r_end);
196: }
197: old -> r_tmp &= tmp;
198: break;
199: }
200: }
201: if (i < n_root_sets) {
202: /* merge other overlapping intervals */
203: struct roots *other;
204:
205: for (i++; i < n_root_sets; i++) {
206: other = GC_static_roots + i;
207: b = (char *)(other -> r_start);
208: e = (char *)(other -> r_end);
209: if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
210: if ((ptr_t)b < old -> r_start) {
211: old -> r_start = (ptr_t)b;
212: GC_root_size += (old -> r_start - (ptr_t)b);
213: }
214: if ((ptr_t)e > old -> r_end) {
215: old -> r_end = (ptr_t)e;
216: GC_root_size += ((ptr_t)e - old -> r_end);
217: }
218: old -> r_tmp &= other -> r_tmp;
219: /* Delete this entry. */
220: GC_root_size -= (other -> r_end - other -> r_start);
221: other -> r_start = GC_static_roots[n_root_sets-1].r_start;
222: other -> r_end = GC_static_roots[n_root_sets-1].r_end;
223: n_root_sets--;
224: }
225: }
226: return;
227: }
228: }
229: # else
230: old = GC_roots_present(b);
231: if (old != 0) {
232: if ((ptr_t)e <= old -> r_end) /* already there */ return;
233: /* else extend */
234: GC_root_size += (ptr_t)e - old -> r_end;
235: old -> r_end = (ptr_t)e;
236: return;
237: }
238: # endif
239: if (n_root_sets == MAX_ROOT_SETS) {
240: ABORT("Too many root sets\n");
241: }
242: GC_static_roots[n_root_sets].r_start = (ptr_t)b;
243: GC_static_roots[n_root_sets].r_end = (ptr_t)e;
244: GC_static_roots[n_root_sets].r_tmp = tmp;
245: # ifndef MSWIN32
246: GC_static_roots[n_root_sets].r_next = 0;
247: # endif
248: add_roots_to_index(GC_static_roots + n_root_sets);
249: GC_root_size += (ptr_t)e - (ptr_t)b;
250: n_root_sets++;
251: }
252:
253: void GC_clear_roots GC_PROTO((void))
254: {
255: DCL_LOCK_STATE;
256:
257: DISABLE_SIGNALS();
258: LOCK();
259: n_root_sets = 0;
260: GC_root_size = 0;
261: # ifndef MSWIN32
262: {
263: register int i;
264:
265: for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
266: }
267: # endif
268: UNLOCK();
269: ENABLE_SIGNALS();
270: }
271:
272: /* Internal use only; lock held. */
273: void GC_remove_tmp_roots()
274: {
275: register int i;
276:
277: for (i = 0; i < n_root_sets; ) {
278: if (GC_static_roots[i].r_tmp) {
279: GC_root_size -=
280: (GC_static_roots[i].r_end - GC_static_roots[i].r_start);
281: GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start;
282: GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end;
283: GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp;
284: n_root_sets--;
285: } else {
286: i++;
287: }
288: }
289: # ifndef MSWIN32
290: {
291: register int i;
292:
293: for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
294: for (i = 0; i < n_root_sets; i++)
295: add_roots_to_index(GC_static_roots + i);
296: }
297: # endif
298:
299: }
300:
301: ptr_t GC_approx_sp()
302: {
303: word dummy;
304:
305: return((ptr_t)(&dummy));
306: }
307:
308: /*
309: * Data structure for excluded static roots.
310: * Real declaration is in gc_priv.h.
311:
312: struct exclusion {
313: ptr_t e_start;
314: ptr_t e_end;
315: };
316:
317: struct exclusion GC_excl_table[MAX_EXCLUSIONS];
318: -- Array of exclusions, ascending
319: -- address order.
320: */
321:
322: size_t GC_excl_table_entries = 0; /* Number of entries in use. */
323:
324: /* Return the first exclusion range that includes an address >= start_addr */
325: /* Assumes the exclusion table contains at least one entry (namely the */
326: /* GC data structures). */
327: struct exclusion * GC_next_exclusion(start_addr)
328: ptr_t start_addr;
329: {
330: size_t low = 0;
331: size_t high = GC_excl_table_entries - 1;
332: size_t mid;
333:
334: while (high > low) {
335: mid = (low + high) >> 1;
336: /* low <= mid < high */
337: if ((word) GC_excl_table[mid].e_end <= (word) start_addr) {
338: low = mid + 1;
339: } else {
340: high = mid;
341: }
342: }
343: if ((word) GC_excl_table[low].e_end <= (word) start_addr) return 0;
344: return GC_excl_table + low;
345: }
346:
347: void GC_exclude_static_roots(start, finish)
348: GC_PTR start;
349: GC_PTR finish;
350: {
351: struct exclusion * next;
352: size_t next_index, i;
353:
354: if (0 == GC_excl_table_entries) {
355: next = 0;
356: } else {
357: next = GC_next_exclusion(start);
358: }
359: if (0 != next) {
360: if ((word)(next -> e_start) < (word) finish) {
361: /* incomplete error check. */
362: ABORT("exclusion ranges overlap");
363: }
364: if ((word)(next -> e_start) == (word) finish) {
365: /* extend old range backwards */
366: next -> e_start = (ptr_t)start;
367: return;
368: }
369: next_index = next - GC_excl_table;
370: for (i = GC_excl_table_entries; i > next_index; --i) {
371: GC_excl_table[i] = GC_excl_table[i-1];
372: }
373: } else {
374: next_index = GC_excl_table_entries;
375: }
376: if (GC_excl_table_entries == MAX_EXCLUSIONS) ABORT("Too many exclusions");
377: GC_excl_table[next_index].e_start = (ptr_t)start;
378: GC_excl_table[next_index].e_end = (ptr_t)finish;
379: ++GC_excl_table_entries;
380: }
381:
382: /* Invoke push_conditional on ranges that are not excluded. */
383: void GC_push_conditional_with_exclusions(bottom, top, all)
384: ptr_t bottom;
385: ptr_t top;
386: int all;
387: {
388: struct exclusion * next;
389: ptr_t excl_start;
390:
391: while (bottom < top) {
392: next = GC_next_exclusion(bottom);
393: if (0 == next || (excl_start = next -> e_start) >= top) {
394: GC_push_conditional(bottom, top, all);
395: return;
396: }
397: if (excl_start > bottom) GC_push_conditional(bottom, excl_start, all);
398: bottom = next -> e_end;
399: }
400: }
401:
402: /*
403: * In the absence of threads, push the stack contents.
404: * In the presence of threads, push enough of the current stack
405: * to ensure that callee-save registers saved in collector frames have been
406: * seen.
407: */
408: void GC_push_current_stack(cold_gc_frame)
409: ptr_t cold_gc_frame;
410: {
411: # if defined(THREADS)
412: if (0 == cold_gc_frame) return;
413: # ifdef STACK_GROWS_DOWN
414: GC_push_all_eager(GC_approx_sp(), cold_gc_frame);
415: # else
416: GC_push_all_eager( cold_gc_frame, GC_approx_sp() );
417: # endif
418: # else
419: # ifdef STACK_GROWS_DOWN
420: GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom,
421: cold_gc_frame );
422: # else
423: GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(),
424: cold_gc_frame );
425: # endif
426: # endif /* !THREADS */
427: }
428:
429: /*
430: * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
431: * on groups of pointers) on every top level accessible pointer.
432: * If all is FALSE, arrange to push only possibly altered values.
433: * Cold_gc_frame is an address inside a GC frame that
434: * remains valid until all marking is complete.
435: * A zero value indicates that it's OK to miss some
436: * register values.
437: */
438: void GC_push_roots(all, cold_gc_frame)
439: GC_bool all;
440: ptr_t cold_gc_frame;
441: {
442: register int i;
443:
444: /*
445: * push registers - i.e., call GC_push_one(r) for each
446: * register contents r.
447: */
448: # ifdef USE_GENERIC_PUSH_REGS
449: GC_generic_push_regs(cold_gc_frame);
450: # else
451: GC_push_regs(); /* usually defined in machine_dep.c */
452: # endif
453:
454: /*
455: * Next push static data. This must happen early on, since it's
456: * not robust against mark stack overflow.
457: */
458: /* Reregister dynamic libraries, in case one got added. */
459: # if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
460: && !defined(SRC_M3)
461: GC_remove_tmp_roots();
462: GC_register_dynamic_libraries();
463: # endif
464: /* Mark everything in static data areas */
465: for (i = 0; i < n_root_sets; i++) {
466: GC_push_conditional_with_exclusions(
467: GC_static_roots[i].r_start,
468: GC_static_roots[i].r_end, all);
469: }
470:
471: /*
472: * Now traverse stacks.
473: */
474: # if !defined(USE_GENERIC_PUSH_REGS)
475: GC_push_current_stack(cold_gc_frame);
476: /* IN the threads case, this only pushes collector frames. */
477: /* In the USE_GENERIC_PUSH_REGS case, this is done inside */
478: /* GC_push_regs, so that we catch callee-save registers saved */
479: /* inside the GC_push_regs frame. */
480: # endif
481: if (GC_push_other_roots != 0) (*GC_push_other_roots)();
482: /* In the threads case, this also pushes thread stacks. */
483: }
484:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>