Annotation of OpenXM_contrib2/asir2000/gc/reclaim.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, February 15, 1996 2:41 pm PST */
15:
16: #include <stdio.h>
17: #include "gc_priv.h"
18:
19: void GC_timerstart(), GC_timerstop();
20:
21: signed_word GC_mem_found = 0;
22: /* Number of words of memory reclaimed */
23:
24: # ifdef FIND_LEAK
25: static void report_leak(p, sz)
26: ptr_t p;
27: word sz;
28: {
29: if (HDR(p) -> hb_obj_kind == PTRFREE) {
30: GC_err_printf0("Leaked atomic object at ");
31: } else {
32: GC_err_printf0("Leaked composite object at ");
33: }
34: if (GC_debugging_started && GC_has_debug_info(p)) {
35: GC_print_obj(p);
36: } else {
37: GC_err_printf2("0x%lx (appr. size = %ld)\n",
38: (unsigned long)p,
39: (unsigned long)WORDS_TO_BYTES(sz));
40: }
41: }
42:
43: # define FOUND_FREE(hblk, word_no) \
44: if (abort_if_found) { \
45: report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \
46: HDR(hblk) -> hb_sz); \
47: }
48: # else
49: # define FOUND_FREE(hblk, word_no)
50: # endif
51:
52: /*
53: * reclaim phase
54: *
55: */
56:
57:
58: /*
59: * Test whether a block is completely empty, i.e. contains no marked
60: * objects. This does not require the block to be in physical
61: * memory.
62: */
63:
64: GC_bool GC_block_empty(hhdr)
65: register hdr * hhdr;
66: {
67: register word *p = (word *)(&(hhdr -> hb_marks[0]));
68: register word * plim =
69: (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
70: while (p < plim) {
71: if (*p++) return(FALSE);
72: }
73: return(TRUE);
74: }
75:
76: # ifdef GATHERSTATS
77: # define INCR_WORDS(sz) n_words_found += (sz)
78: # else
79: # define INCR_WORDS(sz)
80: # endif
81: /*
82: * Restore unmarked small objects in h of size sz to the object
83: * free list. Returns the new list.
84: * Clears unmarked objects.
85: */
86: /*ARGSUSED*/
87: ptr_t GC_reclaim_clear(hbp, hhdr, sz, list, abort_if_found)
88: register struct hblk *hbp; /* ptr to current heap block */
89: register hdr * hhdr;
90: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
91: register ptr_t list;
92: register word sz;
93: {
94: register int word_no;
95: register word *p, *q, *plim;
96: # ifdef GATHERSTATS
97: register int n_words_found = 0;
98: # endif
99:
100: p = (word *)(hbp->hb_body);
101: word_no = HDR_WORDS;
102: plim = (word *)((((word)hbp) + HBLKSIZE)
103: - WORDS_TO_BYTES(sz));
104:
105: /* go through all words in block */
106: while( p <= plim ) {
107: if( mark_bit_from_hdr(hhdr, word_no) ) {
108: p += sz;
109: } else {
110: FOUND_FREE(hbp, word_no);
111: INCR_WORDS(sz);
112: /* object is available - put on list */
113: obj_link(p) = list;
114: list = ((ptr_t)p);
115: /* Clear object, advance p to next object in the process */
116: q = p + sz;
117: p++; /* Skip link field */
118: while (p < q) {
119: *p++ = 0;
120: }
121: }
122: word_no += sz;
123: }
124: # ifdef GATHERSTATS
125: GC_mem_found += n_words_found;
126: # endif
127: return(list);
128: }
129:
130: #ifndef SMALL_CONFIG
131:
132: /*
133: * A special case for 2 word composite objects (e.g. cons cells):
134: */
135: /*ARGSUSED*/
136: ptr_t GC_reclaim_clear2(hbp, hhdr, list, abort_if_found)
137: register struct hblk *hbp; /* ptr to current heap block */
138: hdr * hhdr;
139: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
140: register ptr_t list;
141: {
142: register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
143: register word *p, *plim;
144: # ifdef GATHERSTATS
145: register int n_words_found = 0;
146: # endif
147: register word mark_word;
148: register int i;
149: # define DO_OBJ(start_displ) \
150: if (!(mark_word & ((word)1 << start_displ))) { \
151: FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
152: p[start_displ] = (word)list; \
153: list = (ptr_t)(p+start_displ); \
154: p[start_displ+1] = 0; \
155: INCR_WORDS(2); \
156: }
157:
158: p = (word *)(hbp->hb_body);
159: plim = (word *)(((word)hbp) + HBLKSIZE);
160:
161: /* go through all words in block */
162: while( p < plim ) {
163: mark_word = *mark_word_addr++;
164: for (i = 0; i < WORDSZ; i += 8) {
165: DO_OBJ(0);
166: DO_OBJ(2);
167: DO_OBJ(4);
168: DO_OBJ(6);
169: p += 8;
170: mark_word >>= 8;
171: }
172: }
173: # ifdef GATHERSTATS
174: GC_mem_found += n_words_found;
175: # endif
176: return(list);
177: # undef DO_OBJ
178: }
179:
180: /*
181: * Another special case for 4 word composite objects:
182: */
183: /*ARGSUSED*/
184: ptr_t GC_reclaim_clear4(hbp, hhdr, list, abort_if_found)
185: register struct hblk *hbp; /* ptr to current heap block */
186: hdr * hhdr;
187: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
188: register ptr_t list;
189: {
190: register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
191: register word *p, *plim;
192: # ifdef GATHERSTATS
193: register int n_words_found = 0;
194: # endif
195: register word mark_word;
196: # define DO_OBJ(start_displ) \
197: if (!(mark_word & ((word)1 << start_displ))) { \
198: FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
199: p[start_displ] = (word)list; \
200: list = (ptr_t)(p+start_displ); \
201: p[start_displ+1] = 0; \
202: p[start_displ+2] = 0; \
203: p[start_displ+3] = 0; \
204: INCR_WORDS(4); \
205: }
206:
207: p = (word *)(hbp->hb_body);
208: plim = (word *)(((word)hbp) + HBLKSIZE);
209:
210: /* go through all words in block */
211: while( p < plim ) {
212: mark_word = *mark_word_addr++;
213: DO_OBJ(0);
214: DO_OBJ(4);
215: DO_OBJ(8);
216: DO_OBJ(12);
217: DO_OBJ(16);
218: DO_OBJ(20);
219: DO_OBJ(24);
220: DO_OBJ(28);
221: # if CPP_WORDSZ == 64
222: DO_OBJ(32);
223: DO_OBJ(36);
224: DO_OBJ(40);
225: DO_OBJ(44);
226: DO_OBJ(48);
227: DO_OBJ(52);
228: DO_OBJ(56);
229: DO_OBJ(60);
230: # endif
231: p += WORDSZ;
232: }
233: # ifdef GATHERSTATS
234: GC_mem_found += n_words_found;
235: # endif
236: return(list);
237: # undef DO_OBJ
238: }
239:
240: #endif /* !SMALL_CONFIG */
241:
242: /* The same thing, but don't clear objects: */
243: /*ARGSUSED*/
244: ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list, abort_if_found)
245: register struct hblk *hbp; /* ptr to current heap block */
246: register hdr * hhdr;
247: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
248: register ptr_t list;
249: register word sz;
250: {
251: register int word_no;
252: register word *p, *plim;
253: # ifdef GATHERSTATS
254: register int n_words_found = 0;
255: # endif
256:
257: p = (word *)(hbp->hb_body);
258: word_no = HDR_WORDS;
259: plim = (word *)((((word)hbp) + HBLKSIZE)
260: - WORDS_TO_BYTES(sz));
261:
262: /* go through all words in block */
263: while( p <= plim ) {
264: if( !mark_bit_from_hdr(hhdr, word_no) ) {
265: FOUND_FREE(hbp, word_no);
266: INCR_WORDS(sz);
267: /* object is available - put on list */
268: obj_link(p) = list;
269: list = ((ptr_t)p);
270: }
271: p += sz;
272: word_no += sz;
273: }
274: # ifdef GATHERSTATS
275: GC_mem_found += n_words_found;
276: # endif
277: return(list);
278: }
279:
280: #ifndef SMALL_CONFIG
281: /*
282: * Another special case for 2 word atomic objects:
283: */
284: /*ARGSUSED*/
285: ptr_t GC_reclaim_uninit2(hbp, hhdr, list, abort_if_found)
286: register struct hblk *hbp; /* ptr to current heap block */
287: hdr * hhdr;
288: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
289: register ptr_t list;
290: {
291: register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
292: register word *p, *plim;
293: # ifdef GATHERSTATS
294: register int n_words_found = 0;
295: # endif
296: register word mark_word;
297: register int i;
298: # define DO_OBJ(start_displ) \
299: if (!(mark_word & ((word)1 << start_displ))) { \
300: FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
301: p[start_displ] = (word)list; \
302: list = (ptr_t)(p+start_displ); \
303: INCR_WORDS(2); \
304: }
305:
306: p = (word *)(hbp->hb_body);
307: plim = (word *)(((word)hbp) + HBLKSIZE);
308:
309: /* go through all words in block */
310: while( p < plim ) {
311: mark_word = *mark_word_addr++;
312: for (i = 0; i < WORDSZ; i += 8) {
313: DO_OBJ(0);
314: DO_OBJ(2);
315: DO_OBJ(4);
316: DO_OBJ(6);
317: p += 8;
318: mark_word >>= 8;
319: }
320: }
321: # ifdef GATHERSTATS
322: GC_mem_found += n_words_found;
323: # endif
324: return(list);
325: # undef DO_OBJ
326: }
327:
328: /*
329: * Another special case for 4 word atomic objects:
330: */
331: /*ARGSUSED*/
332: ptr_t GC_reclaim_uninit4(hbp, hhdr, list, abort_if_found)
333: register struct hblk *hbp; /* ptr to current heap block */
334: hdr * hhdr;
335: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
336: register ptr_t list;
337: {
338: register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
339: register word *p, *plim;
340: # ifdef GATHERSTATS
341: register int n_words_found = 0;
342: # endif
343: register word mark_word;
344: # define DO_OBJ(start_displ) \
345: if (!(mark_word & ((word)1 << start_displ))) { \
346: FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
347: p[start_displ] = (word)list; \
348: list = (ptr_t)(p+start_displ); \
349: INCR_WORDS(4); \
350: }
351:
352: p = (word *)(hbp->hb_body);
353: plim = (word *)(((word)hbp) + HBLKSIZE);
354:
355: /* go through all words in block */
356: while( p < plim ) {
357: mark_word = *mark_word_addr++;
358: DO_OBJ(0);
359: DO_OBJ(4);
360: DO_OBJ(8);
361: DO_OBJ(12);
362: DO_OBJ(16);
363: DO_OBJ(20);
364: DO_OBJ(24);
365: DO_OBJ(28);
366: # if CPP_WORDSZ == 64
367: DO_OBJ(32);
368: DO_OBJ(36);
369: DO_OBJ(40);
370: DO_OBJ(44);
371: DO_OBJ(48);
372: DO_OBJ(52);
373: DO_OBJ(56);
374: DO_OBJ(60);
375: # endif
376: p += WORDSZ;
377: }
378: # ifdef GATHERSTATS
379: GC_mem_found += n_words_found;
380: # endif
381: return(list);
382: # undef DO_OBJ
383: }
384:
385: /* Finally the one word case, which never requires any clearing: */
386: /*ARGSUSED*/
387: ptr_t GC_reclaim1(hbp, hhdr, list, abort_if_found)
388: register struct hblk *hbp; /* ptr to current heap block */
389: hdr * hhdr;
390: GC_bool abort_if_found; /* Abort if a reclaimable object is found */
391: register ptr_t list;
392: {
393: register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
394: register word *p, *plim;
395: # ifdef GATHERSTATS
396: register int n_words_found = 0;
397: # endif
398: register word mark_word;
399: register int i;
400: # define DO_OBJ(start_displ) \
401: if (!(mark_word & ((word)1 << start_displ))) { \
402: FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
403: p[start_displ] = (word)list; \
404: list = (ptr_t)(p+start_displ); \
405: INCR_WORDS(1); \
406: }
407:
408: p = (word *)(hbp->hb_body);
409: plim = (word *)(((word)hbp) + HBLKSIZE);
410:
411: /* go through all words in block */
412: while( p < plim ) {
413: mark_word = *mark_word_addr++;
414: for (i = 0; i < WORDSZ; i += 4) {
415: DO_OBJ(0);
416: DO_OBJ(1);
417: DO_OBJ(2);
418: DO_OBJ(3);
419: p += 4;
420: mark_word >>= 4;
421: }
422: }
423: # ifdef GATHERSTATS
424: GC_mem_found += n_words_found;
425: # endif
426: return(list);
427: # undef DO_OBJ
428: }
429:
430: #endif /* !SMALL_CONFIG */
431:
432: /*
433: * Restore unmarked small objects in the block pointed to by hbp
434: * to the appropriate object free list.
435: * If entirely empty blocks are to be completely deallocated, then
436: * caller should perform that check.
437: */
438: void GC_reclaim_small_nonempty_block(hbp, abort_if_found)
439: register struct hblk *hbp; /* ptr to current heap block */
440: int abort_if_found; /* Abort if a reclaimable object is found */
441: {
442: hdr * hhdr;
443: register word sz; /* size of objects in current block */
444: register struct obj_kind * ok;
445: register ptr_t * flh;
446: register int kind;
447:
448: hhdr = HDR(hbp);
449: sz = hhdr -> hb_sz;
450: hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
451: kind = hhdr -> hb_obj_kind;
452: ok = &GC_obj_kinds[kind];
453: flh = &(ok -> ok_freelist[sz]);
454: GC_write_hint(hbp);
455:
456: if (ok -> ok_init) {
457: switch(sz) {
458: # ifndef SMALL_CONFIG
459: case 1:
460: *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
461: break;
462: case 2:
463: *flh = GC_reclaim_clear2(hbp, hhdr, *flh, abort_if_found);
464: break;
465: case 4:
466: *flh = GC_reclaim_clear4(hbp, hhdr, *flh, abort_if_found);
467: break;
468: # endif
469: default:
470: *flh = GC_reclaim_clear(hbp, hhdr, sz, *flh, abort_if_found);
471: break;
472: }
473: } else {
474: switch(sz) {
475: # ifndef SMALL_CONFIG
476: case 1:
477: *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
478: break;
479: case 2:
480: *flh = GC_reclaim_uninit2(hbp, hhdr, *flh, abort_if_found);
481: break;
482: case 4:
483: *flh = GC_reclaim_uninit4(hbp, hhdr, *flh, abort_if_found);
484: break;
485: # endif
486: default:
487: *flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh, abort_if_found);
488: break;
489: }
490: }
491: if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(hhdr);
492: }
493:
494: /*
495: * Restore an unmarked large object or an entirely empty blocks of small objects
496: * to the heap block free list.
497: * Otherwise enqueue the block for later processing
498: * by GC_reclaim_small_nonempty_block.
499: * If abort_if_found is TRUE, then process any block immediately.
500: */
501: void GC_reclaim_block(hbp, abort_if_found)
502: register struct hblk *hbp; /* ptr to current heap block */
503: word abort_if_found; /* Abort if a reclaimable object is found */
504: {
505: register hdr * hhdr;
506: register word sz; /* size of objects in current block */
507: register struct obj_kind * ok;
508: struct hblk ** rlh;
509:
510: hhdr = HDR(hbp);
511: sz = hhdr -> hb_sz;
512: ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
513:
514: if( sz > MAXOBJSZ ) { /* 1 big object */
515: if( !mark_bit_from_hdr(hhdr, HDR_WORDS) ) {
516: FOUND_FREE(hbp, HDR_WORDS);
517: # ifdef GATHERSTATS
518: GC_mem_found += sz;
519: # endif
520: GC_freehblk(hbp);
521: }
522: } else {
523: GC_bool empty = GC_block_empty(hhdr);
524: if (abort_if_found) {
525: GC_reclaim_small_nonempty_block(hbp, (int)abort_if_found);
526: } else if (empty) {
527: # ifdef GATHERSTATS
528: GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
529: # endif
530: GC_freehblk(hbp);
531: } else {
532: /* group of smaller objects, enqueue the real work */
533: rlh = &(ok -> ok_reclaim_list[sz]);
534: hhdr -> hb_next = *rlh;
535: *rlh = hbp;
536: }
537: }
538: }
539:
540: #if !defined(NO_DEBUGGING)
541: /* Routines to gather and print heap block info */
542: /* intended for debugging. Otherwise should be called */
543: /* with lock. */
544: static size_t number_of_blocks;
545: static size_t total_bytes;
546:
547: /* Number of set bits in a word. Not performance critical. */
548: static int set_bits(n)
549: word n;
550: {
551: register word m = n;
552: register int result = 0;
553:
554: while (m > 0) {
555: if (m & 1) result++;
556: m >>= 1;
557: }
558: return(result);
559: }
560:
561: /* Return the number of set mark bits in the given header */
562: int GC_n_set_marks(hhdr)
563: hdr * hhdr;
564: {
565: register int result = 0;
566: register int i;
567:
568: for (i = 0; i < MARK_BITS_SZ; i++) {
569: result += set_bits(hhdr -> hb_marks[i]);
570: }
571: return(result);
572: }
573:
574: /*ARGSUSED*/
575: void GC_print_block_descr(h, dummy)
576: struct hblk *h;
577: word dummy;
578: {
579: register hdr * hhdr = HDR(h);
580: register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
581:
582: GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),
583: (unsigned long)bytes,
584: (unsigned long)(GC_n_set_marks(hhdr)));
585: bytes += HDR_BYTES + HBLKSIZE-1;
586: bytes &= ~(HBLKSIZE-1);
587: total_bytes += bytes;
588: number_of_blocks++;
589: }
590:
591: void GC_print_block_list()
592: {
593: GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
594: number_of_blocks = 0;
595: total_bytes = 0;
596: GC_apply_to_all_blocks(GC_print_block_descr, (word)0);
597: GC_printf2("\nblocks = %lu, bytes = %lu\n",
598: (unsigned long)number_of_blocks,
599: (unsigned long)total_bytes);
600: }
601:
602: #endif /* NO_DEBUGGING */
603:
604: /*
605: * Do the same thing on the entire heap, after first clearing small object
606: * free lists (if we are not just looking for leaks).
607: */
608: void GC_start_reclaim(abort_if_found)
609: int abort_if_found; /* Abort if a GC_reclaimable object is found */
610: {
611: int kind;
612:
613: /* Clear reclaim- and free-lists */
614: for (kind = 0; kind < GC_n_kinds; kind++) {
615: register ptr_t *fop;
616: register ptr_t *lim;
617: register struct hblk ** rlp;
618: register struct hblk ** rlim;
619: register struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
620:
621: if (rlist == 0) continue; /* This kind not used. */
622: if (!abort_if_found) {
623: lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
624: for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
625: *fop = 0;
626: }
627: } /* otherwise free list objects are marked, */
628: /* and its safe to leave them */
629: rlim = rlist + MAXOBJSZ+1;
630: for( rlp = rlist; rlp < rlim; rlp++ ) {
631: *rlp = 0;
632: }
633: }
634:
635: # ifdef PRINTBLOCKS
636: GC_printf0("GC_reclaim: current block sizes:\n");
637: GC_print_block_list();
638: # endif
639:
640: /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
641: /* or enqueue the block for later processing. */
642: GC_apply_to_all_blocks(GC_reclaim_block, (word)abort_if_found);
643:
644: }
645:
646: /*
647: * Sweep blocks of the indicated object size and kind until either the
648: * appropriate free list is nonempty, or there are no more blocks to
649: * sweep.
650: */
651: void GC_continue_reclaim(sz, kind)
652: word sz; /* words */
653: int kind;
654: {
655: register hdr * hhdr;
656: register struct hblk * hbp;
657: register struct obj_kind * ok = &(GC_obj_kinds[kind]);
658: struct hblk ** rlh = ok -> ok_reclaim_list;
659: ptr_t *flh = &(ok -> ok_freelist[sz]);
660:
661: if (rlh == 0) return; /* No blocks of this kind. */
662: rlh += sz;
663: GC_timerstart();
664: while ((hbp = *rlh) != 0) {
665: hhdr = HDR(hbp);
666: *rlh = hhdr -> hb_next;
667: GC_reclaim_small_nonempty_block(hbp, FALSE);
668: if (*flh != 0) break;
669: }
670: GC_timerstop();
671: }
672:
673: /*
674: * Reclaim all small blocks waiting to be reclaimed.
675: * Abort and return FALSE when/if (*stop_func)() returns TRUE.
676: * If this returns TRUE, then it's safe to restart the world
677: * with incorrectly cleared mark bits.
678: * If ignore_old is TRUE, then reclain only blocks that have been
679: * recently reclaimed, and discard the rest.
680: * Stop_func may be 0.
681: */
682: GC_bool GC_reclaim_all(stop_func, ignore_old)
683: GC_stop_func stop_func;
684: GC_bool ignore_old;
685: {
686: register word sz;
687: register int kind;
688: register hdr * hhdr;
689: register struct hblk * hbp;
690: register struct obj_kind * ok;
691: struct hblk ** rlp;
692: struct hblk ** rlh;
693: # ifdef PRINTTIMES
694: CLOCK_TYPE start_time;
695: CLOCK_TYPE done_time;
696:
697: GET_TIME(start_time);
698: # endif
699:
700: GC_timerstart();
701: for (kind = 0; kind < GC_n_kinds; kind++) {
702: ok = &(GC_obj_kinds[kind]);
703: rlp = ok -> ok_reclaim_list;
704: if (rlp == 0) continue;
705: for (sz = 1; sz <= MAXOBJSZ; sz++) {
706: rlh = rlp + sz;
707: while ((hbp = *rlh) != 0) {
708: if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
709: return(FALSE);
710: }
711: hhdr = HDR(hbp);
712: *rlh = hhdr -> hb_next;
713: if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
714: /* It's likely we'll need it this time, too */
715: /* It's been touched recently, so this */
716: /* shouldn't trigger paging. */
717: GC_reclaim_small_nonempty_block(hbp, FALSE);
718: }
719: }
720: }
721: }
722: GC_timerstop();
723: # ifdef PRINTTIMES
724: GET_TIME(done_time);
725: GC_printf1("Disposing of reclaim lists took %lu msecs\n",
726: MS_TIME_DIFF(done_time,start_time));
727: # endif
728: return(TRUE);
729: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>