2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
4 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
5 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
7 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
10 * Permission is hereby granted to use or copy this program
11 * for any purpose, provided the above notices are retained on all copies.
12 * Permission to modify the code and to distribute modified code is granted,
13 * provided the above notices are retained, and a notice that the code was
14 * modified is included with the above copyright notice.
20 #include "private/gc_priv.h"
22 signed_word GC_mem_found = 0;
23 /* Number of words of memory reclaimed */
25 #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
26 word GC_fl_builder_count = 0;
27 /* Number of threads currently building free lists without */
28 /* holding GC lock. It is not safe to collect if this is */
30 #endif /* PARALLEL_MARK */
32 /* We defer printing of leaked objects until we're done with the GC */
33 /* cycle, since the routine for printing objects needs to run outside */
34 /* the collector, e.g. without the allocation lock. */
36 ptr_t GC_leaked[MAX_LEAKED];
37 unsigned GC_n_leaked = 0;
39 GC_bool GC_have_errors = FALSE;
41 void GC_add_leaked(leaked)
44 if (GC_n_leaked < MAX_LEAKED) {
45 GC_have_errors = TRUE;
46 GC_leaked[GC_n_leaked++] = leaked;
47 /* Make sure it's not reclaimed this cycle */
48 GC_set_mark_bit(leaked);
52 static GC_bool printing_errors = FALSE;
53 /* Print all objects on the list after printing any smashed objs. */
54 /* Clear both lists. */
55 void GC_print_all_errors ()
60 if (printing_errors) {
64 printing_errors = TRUE;
66 if (GC_debugging_started) GC_print_all_smashed();
67 for (i = 0; i < GC_n_leaked; ++i) {
68 ptr_t p = GC_leaked[i];
69 if (HDR(p) -> hb_obj_kind == PTRFREE) {
70 GC_err_printf0("Leaked atomic object at ");
72 GC_err_printf0("Leaked composite object at ");
80 printing_errors = FALSE;
84 # define FOUND_FREE(hblk, word_no) \
86 GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
96 * Test whether a block is completely empty, i.e. contains no marked
97 * objects. This does not require the block to be in physical
101 GC_bool GC_block_empty(hhdr)
104 /* We treat hb_marks as an array of words here, even if it is */
105 /* actually an array of bytes. Since we only check for zero, there */
106 /* are no endian-ness issues. */
107 register word *p = (word *)(&(hhdr -> hb_marks[0]));
108 register word * plim =
109 (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
111 if (*p++) return(FALSE);
116 /* The following functions sometimes return a DONT_KNOW value. */
120 # define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW
121 # define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW
122 # define GC_block_nearly_full(hhdr) DONT_KNOW
125 #if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES)
127 # define GC_block_nearly_full1(hhdr, pat1) GC_block_nearly_full(hhdr)
128 # define GC_block_nearly_full3(hhdr, pat1, pat2) GC_block_nearly_full(hhdr)
131 GC_bool GC_block_nearly_full(hhdr)
134 /* We again treat hb_marks as an array of words, even though it */
135 /* isn't. We first sum up all the words, resulting in a word */
136 /* containing 4 or 8 separate partial sums. */
137 /* We then sum the bytes in the word of partial sums. */
138 /* This is still endian independant. This fails if the partial */
139 /* sums can overflow. */
140 # if (BYTES_TO_WORDS(MARK_BITS_SZ)) >= 256
141 --> potential overflow; fix the code
143 register word *p = (word *)(&(hhdr -> hb_marks[0]));
144 register word * plim =
145 (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
153 while (sum_vector > 0) {
154 sum += sum_vector & 0xff;
157 return (sum > BYTES_TO_WORDS(7*HBLKSIZE/8)/(hhdr -> hb_sz));
159 #endif /* USE_MARK_BYTES */
161 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
164 * Test whether nearly all of the mark words consist of the same
167 #define FULL_THRESHOLD (MARK_BITS_SZ/16)
169 GC_bool GC_block_nearly_full1(hhdr, pat1)
175 GC_ASSERT((MARK_BITS_SZ & 1) == 0);
176 for (i = 0; i < MARK_BITS_SZ; ++i) {
177 if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
178 if (++misses > FULL_THRESHOLD) return FALSE;
185 * Test whether the same repeating 3 word pattern occurs in nearly
186 * all the mark bit slots.
187 * This is used as a heuristic, so we're a bit sloppy and ignore
188 * the last one or two words.
190 GC_bool GC_block_nearly_full3(hhdr, pat1, pat2, pat3)
192 word pat1, pat2, pat3;
197 if (MARK_BITS_SZ < 4) {
200 for (i = 0; i < MARK_BITS_SZ - 2; i += 3) {
201 if ((hhdr -> hb_marks[i] | ~pat1) != ONES) {
202 if (++misses > FULL_THRESHOLD) return FALSE;
204 if ((hhdr -> hb_marks[i+1] | ~pat2) != ONES) {
205 if (++misses > FULL_THRESHOLD) return FALSE;
207 if ((hhdr -> hb_marks[i+2] | ~pat3) != ONES) {
208 if (++misses > FULL_THRESHOLD) return FALSE;
214 /* Check whether a small object block is nearly full by looking at only */
216 /* We manually precomputed the mark bit patterns that need to be */
217 /* checked for, and we give up on the ones that are unlikely to occur, */
218 /* or have period > 3. */
219 /* This would be a lot easier with a mark bit per object instead of per */
220 /* word, but that would rewuire computing object numbers in the mark */
221 /* loop, which would require different data structures ... */
222 GC_bool GC_block_nearly_full(hhdr)
225 int sz = hhdr -> hb_sz;
227 # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
228 return DONT_KNOW; /* Shouldn't be used in any standard config. */
230 # if CPP_WORDSZ == 32
233 return GC_block_nearly_full1(hhdr, 0xffffffffl);
235 return GC_block_nearly_full1(hhdr, 0x55555555l);
237 return GC_block_nearly_full1(hhdr, 0x11111111l);
239 return GC_block_nearly_full3(hhdr, 0x41041041l,
243 return GC_block_nearly_full1(hhdr, 0x01010101l);
245 return GC_block_nearly_full3(hhdr, 0x01001001l,
249 return GC_block_nearly_full1(hhdr, 0x00010001l);
251 return GC_block_nearly_full1(hhdr, 0x00000001l);
256 # if CPP_WORDSZ == 64
259 return GC_block_nearly_full1(hhdr, 0xffffffffffffffffl);
261 return GC_block_nearly_full1(hhdr, 0x5555555555555555l);
263 return GC_block_nearly_full1(hhdr, 0x1111111111111111l);
265 return GC_block_nearly_full3(hhdr, 0x1041041041041041l,
267 0x0410410410410410l);
269 return GC_block_nearly_full1(hhdr, 0x0101010101010101l);
271 return GC_block_nearly_full3(hhdr, 0x1001001001001001l,
273 0x0010010010010010l);
275 return GC_block_nearly_full1(hhdr, 0x0001000100010001l);
277 return GC_block_nearly_full1(hhdr, 0x0000000100000001l);
283 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
285 /* We keep track of reclaimed memory if we are either asked to, or */
286 /* we are using the parallel marker. In the latter case, we assume */
287 /* that most allocation goes through GC_malloc_many for scalability. */
288 /* GC_malloc_many needs the count anyway. */
289 # if defined(GATHERSTATS) || defined(PARALLEL_MARK)
290 # define INCR_WORDS(sz) n_words_found += (sz)
291 # define COUNT_PARAM , count
292 # define COUNT_ARG , count
293 # define COUNT_DECL signed_word * count;
294 # define NWORDS_DECL signed_word n_words_found = 0;
295 # define COUNT_UPDATE *count += n_words_found;
296 # define MEM_FOUND_ADDR , &GC_mem_found
298 # define INCR_WORDS(sz)
303 # define COUNT_UPDATE
304 # define MEM_FOUND_ADDR
307 * Restore unmarked small objects in h of size sz to the object
308 * free list. Returns the new list.
309 * Clears unmarked objects.
312 ptr_t GC_reclaim_clear(hbp, hhdr, sz, list COUNT_PARAM)
313 register struct hblk *hbp; /* ptr to current heap block */
319 register int word_no;
320 register word *p, *q, *plim;
323 GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
324 p = (word *)(hbp->hb_body);
326 plim = (word *)((((word)hbp) + HBLKSIZE)
327 - WORDS_TO_BYTES(sz));
329 /* go through all words in block */
331 if( mark_bit_from_hdr(hhdr, word_no) ) {
335 /* object is available - put on list */
338 /* Clear object, advance p to next object in the process */
340 # ifdef USE_MARK_BYTES
342 && !((word)p & (2 * sizeof(word) - 1)));
350 p++; /* Skip link field */
362 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
365 * A special case for 2 word composite objects (e.g. cons cells):
368 ptr_t GC_reclaim_clear2(hbp, hhdr, list COUNT_PARAM)
369 register struct hblk *hbp; /* ptr to current heap block */
374 register word * mark_word_addr = &(hhdr->hb_marks[0]);
375 register word *p, *plim;
376 register word mark_word;
379 # define DO_OBJ(start_displ) \
380 if (!(mark_word & ((word)1 << start_displ))) { \
381 p[start_displ] = (word)list; \
382 list = (ptr_t)(p+start_displ); \
383 p[start_displ+1] = 0; \
387 p = (word *)(hbp->hb_body);
388 plim = (word *)(((word)hbp) + HBLKSIZE);
390 /* go through all words in block */
392 mark_word = *mark_word_addr++;
393 for (i = 0; i < WORDSZ; i += 8) {
408 * Another special case for 4 word composite objects:
411 ptr_t GC_reclaim_clear4(hbp, hhdr, list COUNT_PARAM)
412 register struct hblk *hbp; /* ptr to current heap block */
417 register word * mark_word_addr = &(hhdr->hb_marks[0]);
418 register word *p, *plim;
419 register word mark_word;
421 # define DO_OBJ(start_displ) \
422 if (!(mark_word & ((word)1 << start_displ))) { \
423 p[start_displ] = (word)list; \
424 list = (ptr_t)(p+start_displ); \
425 p[start_displ+1] = 0; \
426 CLEAR_DOUBLE(p + start_displ + 2); \
430 p = (word *)(hbp->hb_body);
431 plim = (word *)(((word)hbp) + HBLKSIZE);
433 /* go through all words in block */
435 mark_word = *mark_word_addr++;
444 # if CPP_WORDSZ == 64
461 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
463 /* The same thing, but don't clear objects: */
465 ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_PARAM)
466 register struct hblk *hbp; /* ptr to current heap block */
472 register int word_no = 0;
473 register word *p, *plim;
476 p = (word *)(hbp->hb_body);
477 plim = (word *)((((word)hbp) + HBLKSIZE)
478 - WORDS_TO_BYTES(sz));
480 /* go through all words in block */
482 if( !mark_bit_from_hdr(hhdr, word_no) ) {
484 /* object is available - put on list */
495 /* Don't really reclaim objects, just check for unmarked ones: */
497 void GC_reclaim_check(hbp, hhdr, sz)
498 register struct hblk *hbp; /* ptr to current heap block */
502 register int word_no = 0;
503 register word *p, *plim;
505 register int n_words_found = 0;
508 p = (word *)(hbp->hb_body);
509 plim = (word *)((((word)hbp) + HBLKSIZE)
510 - WORDS_TO_BYTES(sz));
512 /* go through all words in block */
514 if( !mark_bit_from_hdr(hhdr, word_no) ) {
515 FOUND_FREE(hbp, word_no);
522 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
524 * Another special case for 2 word atomic objects:
527 ptr_t GC_reclaim_uninit2(hbp, hhdr, list COUNT_PARAM)
528 register struct hblk *hbp; /* ptr to current heap block */
533 register word * mark_word_addr = &(hhdr->hb_marks[0]);
534 register word *p, *plim;
535 register word mark_word;
538 # define DO_OBJ(start_displ) \
539 if (!(mark_word & ((word)1 << start_displ))) { \
540 p[start_displ] = (word)list; \
541 list = (ptr_t)(p+start_displ); \
545 p = (word *)(hbp->hb_body);
546 plim = (word *)(((word)hbp) + HBLKSIZE);
548 /* go through all words in block */
550 mark_word = *mark_word_addr++;
551 for (i = 0; i < WORDSZ; i += 8) {
566 * Another special case for 4 word atomic objects:
569 ptr_t GC_reclaim_uninit4(hbp, hhdr, list COUNT_PARAM)
570 register struct hblk *hbp; /* ptr to current heap block */
575 register word * mark_word_addr = &(hhdr->hb_marks[0]);
576 register word *p, *plim;
577 register word mark_word;
579 # define DO_OBJ(start_displ) \
580 if (!(mark_word & ((word)1 << start_displ))) { \
581 p[start_displ] = (word)list; \
582 list = (ptr_t)(p+start_displ); \
586 p = (word *)(hbp->hb_body);
587 plim = (word *)(((word)hbp) + HBLKSIZE);
589 /* go through all words in block */
591 mark_word = *mark_word_addr++;
600 # if CPP_WORDSZ == 64
617 /* Finally the one word case, which never requires any clearing: */
619 ptr_t GC_reclaim1(hbp, hhdr, list COUNT_PARAM)
620 register struct hblk *hbp; /* ptr to current heap block */
625 register word * mark_word_addr = &(hhdr->hb_marks[0]);
626 register word *p, *plim;
627 register word mark_word;
630 # define DO_OBJ(start_displ) \
631 if (!(mark_word & ((word)1 << start_displ))) { \
632 p[start_displ] = (word)list; \
633 list = (ptr_t)(p+start_displ); \
637 p = (word *)(hbp->hb_body);
638 plim = (word *)(((word)hbp) + HBLKSIZE);
640 /* go through all words in block */
642 mark_word = *mark_word_addr++;
643 for (i = 0; i < WORDSZ; i += 4) {
657 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
660 * Generic procedure to rebuild a free list in hbp.
661 * Also called directly from GC_malloc_many.
663 ptr_t GC_reclaim_generic(hbp, hhdr, sz, init, list COUNT_PARAM)
664 struct hblk *hbp; /* ptr to current heap block */
673 GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
674 GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
677 # if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
679 /* We now issue the hint even if GC_nearly_full returned */
681 result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
684 result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG);
687 result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG);
689 # endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
691 result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG);
695 GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
697 # if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
699 result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
702 result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG);
705 result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG);
707 # endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
709 result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG);
713 if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr);
718 * Restore unmarked small objects in the block pointed to by hbp
719 * to the appropriate object free list.
720 * If entirely empty blocks are to be completely deallocated, then
721 * caller should perform that check.
723 void GC_reclaim_small_nonempty_block(hbp, report_if_found COUNT_PARAM)
724 register struct hblk *hbp; /* ptr to current heap block */
725 int report_if_found; /* Abort if a reclaimable object is found */
728 hdr *hhdr = HDR(hbp);
729 word sz = hhdr -> hb_sz;
730 int kind = hhdr -> hb_obj_kind;
731 struct obj_kind * ok = &GC_obj_kinds[kind];
732 ptr_t * flh = &(ok -> ok_freelist[sz]);
734 hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
736 if (report_if_found) {
737 GC_reclaim_check(hbp, hhdr, sz);
739 *flh = GC_reclaim_generic(hbp, hhdr, sz,
740 (ok -> ok_init || GC_debugging_started),
741 *flh MEM_FOUND_ADDR);
746 * Restore an unmarked large object or an entirely empty blocks of small objects
747 * to the heap block free list.
748 * Otherwise enqueue the block for later processing
749 * by GC_reclaim_small_nonempty_block.
750 * If report_if_found is TRUE, then process any block immediately, and
751 * simply report free objects; do not actually reclaim them.
753 # if defined(__STDC__) || defined(__cplusplus)
754 void GC_reclaim_block(register struct hblk *hbp, word report_if_found)
756 void GC_reclaim_block(hbp, report_if_found)
757 register struct hblk *hbp; /* ptr to current heap block */
758 word report_if_found; /* Abort if a reclaimable object is found */
762 register word sz; /* size of objects in current block */
763 register struct obj_kind * ok;
768 ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
770 if( sz > MAXOBJSZ ) { /* 1 big object */
771 if( !mark_bit_from_hdr(hhdr, 0) ) {
772 if (report_if_found) {
775 word blocks = OBJ_SZ_TO_BLOCKS(sz);
777 GC_large_allocd_bytes -= blocks * HBLKSIZE;
786 GC_bool empty = GC_block_empty(hhdr);
787 if (report_if_found) {
788 GC_reclaim_small_nonempty_block(hbp, (int)report_if_found
792 GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
795 } else if (TRUE != GC_block_nearly_full(hhdr)){
796 /* group of smaller objects, enqueue the real work */
797 rlh = &(ok -> ok_reclaim_list[sz]);
798 hhdr -> hb_next = *rlh;
800 } /* else not worth salvaging. */
801 /* We used to do the nearly_full check later, but we */
802 /* already have the right cache context here. Also */
803 /* doing it here avoids some silly lock contention in */
804 /* GC_malloc_many. */
808 #if !defined(NO_DEBUGGING)
809 /* Routines to gather and print heap block info */
810 /* intended for debugging. Otherwise should be called */
815 size_t number_of_blocks;
819 #ifdef USE_MARK_BYTES
821 /* Return the number of set mark bits in the given header */
822 int GC_n_set_marks(hhdr)
825 register int result = 0;
828 for (i = 0; i < MARK_BITS_SZ; i++) {
829 result += hhdr -> hb_marks[i];
836 /* Number of set bits in a word. Not performance critical. */
837 static int set_bits(n)
841 register int result = 0;
850 /* Return the number of set mark bits in the given header */
851 int GC_n_set_marks(hhdr)
854 register int result = 0;
857 for (i = 0; i < MARK_BITS_SZ; i++) {
858 result += set_bits(hhdr -> hb_marks[i]);
863 #endif /* !USE_MARK_BYTES */
866 # if defined(__STDC__) || defined(__cplusplus)
867 void GC_print_block_descr(struct hblk *h, word dummy)
869 void GC_print_block_descr(h, dummy)
874 register hdr * hhdr = HDR(h);
875 register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
876 struct Print_stats *ps;
878 GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),
879 (unsigned long)bytes,
880 (unsigned long)(GC_n_set_marks(hhdr)));
882 bytes &= ~(HBLKSIZE-1);
884 ps = (struct Print_stats *)dummy;
885 ps->total_bytes += bytes;
886 ps->number_of_blocks++;
889 void GC_print_block_list()
891 struct Print_stats pstats;
893 GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
894 pstats.number_of_blocks = 0;
895 pstats.total_bytes = 0;
896 GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
897 GC_printf2("\nblocks = %lu, bytes = %lu\n",
898 (unsigned long)pstats.number_of_blocks,
899 (unsigned long)pstats.total_bytes);
902 #endif /* NO_DEBUGGING */
905 * Clear all obj_link pointers in the list of free objects *flp.
907 * This must be done before dropping a list of free gcj-style objects,
908 * since may otherwise end up with dangling "descriptor" pointers.
909 * It may help for other pointer-containing objects.
911 void GC_clear_fl_links(flp)
918 flp = &(obj_link(next));
924 * Perform GC_reclaim_block on the entire heap, after first clearing
925 * small object free lists (if we are not just looking for leaks).
927 void GC_start_reclaim(report_if_found)
928 int report_if_found; /* Abort if a GC_reclaimable object is found */
932 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
933 GC_ASSERT(0 == GC_fl_builder_count);
935 /* Clear reclaim- and free-lists */
936 for (kind = 0; kind < GC_n_kinds; kind++) {
941 struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
942 GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0);
944 if (rlist == 0) continue; /* This kind not used. */
945 if (!report_if_found) {
946 lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
947 for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
949 if (should_clobber) {
950 GC_clear_fl_links(fop);
956 } /* otherwise free list objects are marked, */
957 /* and its safe to leave them */
958 rlim = rlist + MAXOBJSZ+1;
959 for( rlp = rlist; rlp < rlim; rlp++ ) {
965 GC_printf0("GC_reclaim: current block sizes:\n");
966 GC_print_block_list();
969 /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
970 /* or enqueue the block for later processing. */
971 GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
974 /* This is a very stupid thing to do. We make it possible anyway, */
975 /* so that you can convince yourself that it really is very stupid. */
976 GC_reclaim_all((GC_stop_func)0, FALSE);
978 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
979 GC_ASSERT(0 == GC_fl_builder_count);
985 * Sweep blocks of the indicated object size and kind until either the
986 * appropriate free list is nonempty, or there are no more blocks to
989 void GC_continue_reclaim(sz, kind)
994 register struct hblk * hbp;
995 register struct obj_kind * ok = &(GC_obj_kinds[kind]);
996 struct hblk ** rlh = ok -> ok_reclaim_list;
997 ptr_t *flh = &(ok -> ok_freelist[sz]);
999 if (rlh == 0) return; /* No blocks of this kind. */
1001 while ((hbp = *rlh) != 0) {
1003 *rlh = hhdr -> hb_next;
1004 GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
1005 if (*flh != 0) break;
1010 * Reclaim all small blocks waiting to be reclaimed.
1011 * Abort and return FALSE when/if (*stop_func)() returns TRUE.
1012 * If this returns TRUE, then it's safe to restart the world
1013 * with incorrectly cleared mark bits.
1014 * If ignore_old is TRUE, then reclaim only blocks that have been
1015 * recently reclaimed, and discard the rest.
1016 * Stop_func may be 0.
1018 GC_bool GC_reclaim_all(stop_func, ignore_old)
1019 GC_stop_func stop_func;
1024 register hdr * hhdr;
1025 register struct hblk * hbp;
1026 register struct obj_kind * ok;
1030 CLOCK_TYPE start_time;
1031 CLOCK_TYPE done_time;
1033 GET_TIME(start_time);
1036 for (kind = 0; kind < GC_n_kinds; kind++) {
1037 ok = &(GC_obj_kinds[kind]);
1038 rlp = ok -> ok_reclaim_list;
1039 if (rlp == 0) continue;
1040 for (sz = 1; sz <= MAXOBJSZ; sz++) {
1042 while ((hbp = *rlh) != 0) {
1043 if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
1047 *rlh = hhdr -> hb_next;
1048 if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
1049 /* It's likely we'll need it this time, too */
1050 /* It's been touched recently, so this */
1051 /* shouldn't trigger paging. */
1052 GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR);
1058 GET_TIME(done_time);
1059 GC_printf1("Disposing of reclaim lists took %lu msecs\n",
1060 MS_TIME_DIFF(done_time,start_time));