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