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.
18 #include "private/gc_priv.h"
20 signed_word GC_mem_found
= 0;
21 /* Number of words of memory reclaimed */
23 #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
24 word GC_fl_builder_count
= 0;
25 /* Number of threads currently building free lists without */
26 /* holding GC lock. It is not safe to collect if this is */
28 #endif /* PARALLEL_MARK */
30 /* We defer printing of leaked objects until we're done with the GC */
31 /* cycle, since the routine for printing objects needs to run outside */
32 /* the collector, e.g. without the allocation lock. */
34 ptr_t GC_leaked
[MAX_LEAKED
];
35 unsigned GC_n_leaked
= 0;
37 GC_bool GC_have_errors
= FALSE
;
39 void GC_add_leaked(leaked
)
42 if (GC_n_leaked
< MAX_LEAKED
) {
43 GC_have_errors
= TRUE
;
44 GC_leaked
[GC_n_leaked
++] = leaked
;
45 /* Make sure it's not reclaimed this cycle */
46 GC_set_mark_bit(leaked
);
50 static GC_bool printing_errors
= FALSE
;
51 /* Print all objects on the list after printing any smashed objs. */
52 /* Clear both lists. */
53 void GC_print_all_errors ()
58 if (printing_errors
) {
62 printing_errors
= TRUE
;
64 if (GC_debugging_started
) GC_print_all_smashed();
65 for (i
= 0; i
< GC_n_leaked
; ++i
) {
66 ptr_t p
= GC_leaked
[i
];
67 if (HDR(p
) -> hb_obj_kind
== PTRFREE
) {
68 GC_err_printf0("Leaked atomic object at ");
70 GC_err_printf0("Leaked composite object at ");
78 printing_errors
= FALSE
;
82 # define FOUND_FREE(hblk, word_no) \
84 GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \
94 * Test whether a block is completely empty, i.e. contains no marked
95 * objects. This does not require the block to be in physical
99 GC_bool
GC_block_empty(hhdr
)
102 /* We treat hb_marks as an array of words here, even if it is */
103 /* actually an array of bytes. Since we only check for zero, there */
104 /* are no endian-ness issues. */
105 register word
*p
= (word
*)(&(hhdr
-> hb_marks
[0]));
106 register word
* plim
=
107 (word
*)(&(hhdr
-> hb_marks
[MARK_BITS_SZ
]));
109 if (*p
++) return(FALSE
);
114 /* The following functions sometimes return a DONT_KNOW value. */
118 # define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW
119 # define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW
120 # define GC_block_nearly_full(hhdr) DONT_KNOW
123 #if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES)
125 # define GC_block_nearly_full1(hhdr, pat1) GC_block_nearly_full(hhdr)
126 # define GC_block_nearly_full3(hhdr, pat1, pat2) GC_block_nearly_full(hhdr)
129 GC_bool
GC_block_nearly_full(hhdr
)
132 /* We again treat hb_marks as an array of words, even though it */
133 /* isn't. We first sum up all the words, resulting in a word */
134 /* containing 4 or 8 separate partial sums. */
135 /* We then sum the bytes in the word of partial sums. */
136 /* This is still endian independant. This fails if the partial */
137 /* sums can overflow. */
138 # if (BYTES_TO_WORDS(MARK_BITS_SZ)) >= 256
139 --> potential overflow
; fix the code
141 register word
*p
= (word
*)(&(hhdr
-> hb_marks
[0]));
142 register word
* plim
=
143 (word
*)(&(hhdr
-> hb_marks
[MARK_BITS_SZ
]));
151 while (sum_vector
> 0) {
152 sum
+= sum_vector
& 0xff;
155 return (sum
> BYTES_TO_WORDS(7*HBLKSIZE
/8)/(hhdr
-> hb_sz
));
157 #endif /* USE_MARK_BYTES */
159 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
162 * Test whether nearly all of the mark words consist of the same
165 #define FULL_THRESHOLD (MARK_BITS_SZ/16)
167 GC_bool
GC_block_nearly_full1(hhdr
, pat1
)
173 GC_ASSERT((MARK_BITS_SZ
& 1) == 0);
174 for (i
= 0; i
< MARK_BITS_SZ
; ++i
) {
175 if ((hhdr
-> hb_marks
[i
] | ~pat1
) != ONES
) {
176 if (++misses
> FULL_THRESHOLD
) return FALSE
;
183 * Test whether the same repeating 3 word pattern occurs in nearly
184 * all the mark bit slots.
185 * This is used as a heuristic, so we're a bit sloppy and ignore
186 * the last one or two words.
188 GC_bool
GC_block_nearly_full3(hhdr
, pat1
, pat2
, pat3
)
190 word pat1
, pat2
, pat3
;
195 if (MARK_BITS_SZ
< 4) {
198 for (i
= 0; i
< MARK_BITS_SZ
- 2; i
+= 3) {
199 if ((hhdr
-> hb_marks
[i
] | ~pat1
) != ONES
) {
200 if (++misses
> FULL_THRESHOLD
) return FALSE
;
202 if ((hhdr
-> hb_marks
[i
+1] | ~pat2
) != ONES
) {
203 if (++misses
> FULL_THRESHOLD
) return FALSE
;
205 if ((hhdr
-> hb_marks
[i
+2] | ~pat3
) != ONES
) {
206 if (++misses
> FULL_THRESHOLD
) return FALSE
;
212 /* Check whether a small object block is nearly full by looking at only */
214 /* We manually precomputed the mark bit patterns that need to be */
215 /* checked for, and we give up on the ones that are unlikely to occur, */
216 /* or have period > 3. */
217 /* This would be a lot easier with a mark bit per object instead of per */
218 /* word, but that would rewuire computing object numbers in the mark */
219 /* loop, which would require different data structures ... */
220 GC_bool
GC_block_nearly_full(hhdr
)
223 int sz
= hhdr
-> hb_sz
;
225 # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
226 return DONT_KNOW
; /* Shouldn't be used in any standard config. */
228 # if CPP_WORDSZ == 32
231 return GC_block_nearly_full1(hhdr
, 0xffffffffl
);
233 return GC_block_nearly_full1(hhdr
, 0x55555555l
);
235 return GC_block_nearly_full1(hhdr
, 0x11111111l
);
237 return GC_block_nearly_full3(hhdr
, 0x41041041l
,
241 return GC_block_nearly_full1(hhdr
, 0x01010101l
);
243 return GC_block_nearly_full3(hhdr
, 0x01001001l
,
247 return GC_block_nearly_full1(hhdr
, 0x00010001l
);
249 return GC_block_nearly_full1(hhdr
, 0x00000001l
);
254 # if CPP_WORDSZ == 64
257 return GC_block_nearly_full1(hhdr
, 0xffffffffffffffffl
);
259 return GC_block_nearly_full1(hhdr
, 0x5555555555555555l
);
261 return GC_block_nearly_full1(hhdr
, 0x1111111111111111l
);
263 return GC_block_nearly_full3(hhdr
, 0x1041041041041041l
,
265 0x0410410410410410l
);
267 return GC_block_nearly_full1(hhdr
, 0x0101010101010101l
);
269 return GC_block_nearly_full3(hhdr
, 0x1001001001001001l
,
271 0x0010010010010010l
);
273 return GC_block_nearly_full1(hhdr
, 0x0001000100010001l
);
275 return GC_block_nearly_full1(hhdr
, 0x0000000100000001l
);
281 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
283 /* We keep track of reclaimed memory if we are either asked to, or */
284 /* we are using the parallel marker. In the latter case, we assume */
285 /* that most allocation goes through GC_malloc_many for scalability. */
286 /* GC_malloc_many needs the count anyway. */
287 # if defined(GATHERSTATS) || defined(PARALLEL_MARK)
288 # define INCR_WORDS(sz) n_words_found += (sz)
289 # define COUNT_PARAM , count
290 # define COUNT_ARG , count
291 # define COUNT_DECL signed_word * count;
292 # define NWORDS_DECL signed_word n_words_found = 0;
293 # define COUNT_UPDATE *count += n_words_found;
294 # define MEM_FOUND_ADDR , &GC_mem_found
296 # define INCR_WORDS(sz)
301 # define COUNT_UPDATE
302 # define MEM_FOUND_ADDR
305 * Restore unmarked small objects in h of size sz to the object
306 * free list. Returns the new list.
307 * Clears unmarked objects.
310 ptr_t
GC_reclaim_clear(hbp
, hhdr
, sz
, list COUNT_PARAM
)
311 register struct hblk
*hbp
; /* ptr to current heap block */
317 register int word_no
;
318 register word
*p
, *q
, *plim
;
321 GC_ASSERT(hhdr
== GC_find_header((ptr_t
)hbp
));
322 p
= (word
*)(hbp
->hb_body
);
324 plim
= (word
*)((((word
)hbp
) + HBLKSIZE
)
325 - WORDS_TO_BYTES(sz
));
327 /* go through all words in block */
329 if( mark_bit_from_hdr(hhdr
, word_no
) ) {
333 /* object is available - put on list */
336 /* Clear object, advance p to next object in the process */
338 # ifdef USE_MARK_BYTES
340 && !((word
)p
& (2 * sizeof(word
) - 1)));
348 p
++; /* Skip link field */
360 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
363 * A special case for 2 word composite objects (e.g. cons cells):
366 ptr_t
GC_reclaim_clear2(hbp
, hhdr
, list COUNT_PARAM
)
367 register struct hblk
*hbp
; /* ptr to current heap block */
372 register word
* mark_word_addr
= &(hhdr
->hb_marks
[0]);
373 register word
*p
, *plim
;
374 register word mark_word
;
377 # define DO_OBJ(start_displ) \
378 if (!(mark_word & ((word)1 << start_displ))) { \
379 p[start_displ] = (word)list; \
380 list = (ptr_t)(p+start_displ); \
381 p[start_displ+1] = 0; \
385 p
= (word
*)(hbp
->hb_body
);
386 plim
= (word
*)(((word
)hbp
) + HBLKSIZE
);
388 /* go through all words in block */
390 mark_word
= *mark_word_addr
++;
391 for (i
= 0; i
< WORDSZ
; i
+= 8) {
406 * Another special case for 4 word composite objects:
409 ptr_t
GC_reclaim_clear4(hbp
, hhdr
, list COUNT_PARAM
)
410 register struct hblk
*hbp
; /* ptr to current heap block */
415 register word
* mark_word_addr
= &(hhdr
->hb_marks
[0]);
416 register word
*p
, *plim
;
417 register word mark_word
;
419 # define DO_OBJ(start_displ) \
420 if (!(mark_word & ((word)1 << start_displ))) { \
421 p[start_displ] = (word)list; \
422 list = (ptr_t)(p+start_displ); \
423 p[start_displ+1] = 0; \
424 CLEAR_DOUBLE(p + start_displ + 2); \
428 p
= (word
*)(hbp
->hb_body
);
429 plim
= (word
*)(((word
)hbp
) + HBLKSIZE
);
431 /* go through all words in block */
433 mark_word
= *mark_word_addr
++;
442 # if CPP_WORDSZ == 64
459 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
461 /* The same thing, but don't clear objects: */
463 ptr_t
GC_reclaim_uninit(hbp
, hhdr
, sz
, list COUNT_PARAM
)
464 register struct hblk
*hbp
; /* ptr to current heap block */
470 register int word_no
= 0;
471 register word
*p
, *plim
;
474 p
= (word
*)(hbp
->hb_body
);
475 plim
= (word
*)((((word
)hbp
) + HBLKSIZE
)
476 - WORDS_TO_BYTES(sz
));
478 /* go through all words in block */
480 if( !mark_bit_from_hdr(hhdr
, word_no
) ) {
482 /* object is available - put on list */
493 /* Don't really reclaim objects, just check for unmarked ones: */
495 void GC_reclaim_check(hbp
, hhdr
, sz
)
496 register struct hblk
*hbp
; /* ptr to current heap block */
500 register int word_no
= 0;
501 register word
*p
, *plim
;
503 register int n_words_found
= 0;
506 p
= (word
*)(hbp
->hb_body
);
507 plim
= (word
*)((((word
)hbp
) + HBLKSIZE
)
508 - WORDS_TO_BYTES(sz
));
510 /* go through all words in block */
512 if( !mark_bit_from_hdr(hhdr
, word_no
) ) {
513 FOUND_FREE(hbp
, word_no
);
520 #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
522 * Another special case for 2 word atomic objects:
525 ptr_t
GC_reclaim_uninit2(hbp
, hhdr
, list COUNT_PARAM
)
526 register struct hblk
*hbp
; /* ptr to current heap block */
531 register word
* mark_word_addr
= &(hhdr
->hb_marks
[0]);
532 register word
*p
, *plim
;
533 register word mark_word
;
536 # define DO_OBJ(start_displ) \
537 if (!(mark_word & ((word)1 << start_displ))) { \
538 p[start_displ] = (word)list; \
539 list = (ptr_t)(p+start_displ); \
543 p
= (word
*)(hbp
->hb_body
);
544 plim
= (word
*)(((word
)hbp
) + HBLKSIZE
);
546 /* go through all words in block */
548 mark_word
= *mark_word_addr
++;
549 for (i
= 0; i
< WORDSZ
; i
+= 8) {
564 * Another special case for 4 word atomic objects:
567 ptr_t
GC_reclaim_uninit4(hbp
, hhdr
, list COUNT_PARAM
)
568 register struct hblk
*hbp
; /* ptr to current heap block */
573 register word
* mark_word_addr
= &(hhdr
->hb_marks
[0]);
574 register word
*p
, *plim
;
575 register word mark_word
;
577 # define DO_OBJ(start_displ) \
578 if (!(mark_word & ((word)1 << start_displ))) { \
579 p[start_displ] = (word)list; \
580 list = (ptr_t)(p+start_displ); \
584 p
= (word
*)(hbp
->hb_body
);
585 plim
= (word
*)(((word
)hbp
) + HBLKSIZE
);
587 /* go through all words in block */
589 mark_word
= *mark_word_addr
++;
598 # if CPP_WORDSZ == 64
615 /* Finally the one word case, which never requires any clearing: */
617 ptr_t
GC_reclaim1(hbp
, hhdr
, list COUNT_PARAM
)
618 register struct hblk
*hbp
; /* ptr to current heap block */
623 register word
* mark_word_addr
= &(hhdr
->hb_marks
[0]);
624 register word
*p
, *plim
;
625 register word mark_word
;
628 # define DO_OBJ(start_displ) \
629 if (!(mark_word & ((word)1 << start_displ))) { \
630 p[start_displ] = (word)list; \
631 list = (ptr_t)(p+start_displ); \
635 p
= (word
*)(hbp
->hb_body
);
636 plim
= (word
*)(((word
)hbp
) + HBLKSIZE
);
638 /* go through all words in block */
640 mark_word
= *mark_word_addr
++;
641 for (i
= 0; i
< WORDSZ
; i
+= 4) {
655 #endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
658 * Generic procedure to rebuild a free list in hbp.
659 * Also called directly from GC_malloc_many.
661 ptr_t
GC_reclaim_generic(hbp
, hhdr
, sz
, init
, list COUNT_PARAM
)
662 struct hblk
*hbp
; /* ptr to current heap block */
671 GC_ASSERT(GC_find_header((ptr_t
)hbp
) == hhdr
);
672 GC_remove_protection(hbp
, 1, (hhdr
)->hb_descr
== 0 /* Pointer-free? */);
675 # if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
677 /* We now issue the hint even if GC_nearly_full returned */
679 result
= GC_reclaim1(hbp
, hhdr
, list COUNT_ARG
);
682 result
= GC_reclaim_clear2(hbp
, hhdr
, list COUNT_ARG
);
685 result
= GC_reclaim_clear4(hbp
, hhdr
, list COUNT_ARG
);
687 # endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
689 result
= GC_reclaim_clear(hbp
, hhdr
, sz
, list COUNT_ARG
);
693 GC_ASSERT((hhdr
)->hb_descr
== 0 /* Pointer-free block */);
695 # if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
697 result
= GC_reclaim1(hbp
, hhdr
, list COUNT_ARG
);
700 result
= GC_reclaim_uninit2(hbp
, hhdr
, list COUNT_ARG
);
703 result
= GC_reclaim_uninit4(hbp
, hhdr
, list COUNT_ARG
);
705 # endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
707 result
= GC_reclaim_uninit(hbp
, hhdr
, sz
, list COUNT_ARG
);
711 if (IS_UNCOLLECTABLE(hhdr
-> hb_obj_kind
)) GC_set_hdr_marks(hhdr
);
716 * Restore unmarked small objects in the block pointed to by hbp
717 * to the appropriate object free list.
718 * If entirely empty blocks are to be completely deallocated, then
719 * caller should perform that check.
721 void GC_reclaim_small_nonempty_block(hbp
, report_if_found COUNT_PARAM
)
722 register struct hblk
*hbp
; /* ptr to current heap block */
723 int report_if_found
; /* Abort if a reclaimable object is found */
726 hdr
*hhdr
= HDR(hbp
);
727 word sz
= hhdr
-> hb_sz
;
728 int kind
= hhdr
-> hb_obj_kind
;
729 struct obj_kind
* ok
= &GC_obj_kinds
[kind
];
730 ptr_t
* flh
= &(ok
-> ok_freelist
[sz
]);
732 hhdr
-> hb_last_reclaimed
= (unsigned short) GC_gc_no
;
734 if (report_if_found
) {
735 GC_reclaim_check(hbp
, hhdr
, sz
);
737 *flh
= GC_reclaim_generic(hbp
, hhdr
, sz
,
738 (ok
-> ok_init
|| GC_debugging_started
),
739 *flh MEM_FOUND_ADDR
);
744 * Restore an unmarked large object or an entirely empty blocks of small objects
745 * to the heap block free list.
746 * Otherwise enqueue the block for later processing
747 * by GC_reclaim_small_nonempty_block.
748 * If report_if_found is TRUE, then process any block immediately, and
749 * simply report free objects; do not actually reclaim them.
751 # if defined(__STDC__) || defined(__cplusplus)
752 void GC_reclaim_block(register struct hblk
*hbp
, word report_if_found
)
754 void GC_reclaim_block(hbp
, report_if_found
)
755 register struct hblk
*hbp
; /* ptr to current heap block */
756 word report_if_found
; /* Abort if a reclaimable object is found */
760 register word sz
; /* size of objects in current block */
761 register struct obj_kind
* ok
;
766 ok
= &GC_obj_kinds
[hhdr
-> hb_obj_kind
];
768 if( sz
> MAXOBJSZ
) { /* 1 big object */
769 if( !mark_bit_from_hdr(hhdr
, 0) ) {
770 if (report_if_found
) {
773 word blocks
= OBJ_SZ_TO_BLOCKS(sz
);
775 GC_large_allocd_bytes
-= blocks
* HBLKSIZE
;
784 GC_bool empty
= GC_block_empty(hhdr
);
785 if (report_if_found
) {
786 GC_reclaim_small_nonempty_block(hbp
, (int)report_if_found
790 GC_mem_found
+= BYTES_TO_WORDS(HBLKSIZE
);
793 } else if (TRUE
!= GC_block_nearly_full(hhdr
)){
794 /* group of smaller objects, enqueue the real work */
795 rlh
= &(ok
-> ok_reclaim_list
[sz
]);
796 hhdr
-> hb_next
= *rlh
;
798 } /* else not worth salvaging. */
799 /* We used to do the nearly_full check later, but we */
800 /* already have the right cache context here. Also */
801 /* doing it here avoids some silly lock contention in */
802 /* GC_malloc_many. */
806 #if !defined(NO_DEBUGGING)
807 /* Routines to gather and print heap block info */
808 /* intended for debugging. Otherwise should be called */
813 size_t number_of_blocks
;
817 #ifdef USE_MARK_BYTES
819 /* Return the number of set mark bits in the given header */
820 int GC_n_set_marks(hhdr
)
823 register int result
= 0;
826 for (i
= 0; i
< MARK_BITS_SZ
; i
++) {
827 result
+= hhdr
-> hb_marks
[i
];
834 /* Number of set bits in a word. Not performance critical. */
835 static int set_bits(n
)
839 register int result
= 0;
848 /* Return the number of set mark bits in the given header */
849 int GC_n_set_marks(hhdr
)
852 register int result
= 0;
855 for (i
= 0; i
< MARK_BITS_SZ
; i
++) {
856 result
+= set_bits(hhdr
-> hb_marks
[i
]);
861 #endif /* !USE_MARK_BYTES */
864 # if defined(__STDC__) || defined(__cplusplus)
865 void GC_print_block_descr(struct hblk
*h
, word dummy
)
867 void GC_print_block_descr(h
, dummy
)
872 register hdr
* hhdr
= HDR(h
);
873 register size_t bytes
= WORDS_TO_BYTES(hhdr
-> hb_sz
);
874 struct Print_stats
*ps
;
876 GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr
-> hb_obj_kind
),
877 (unsigned long)bytes
,
878 (unsigned long)(GC_n_set_marks(hhdr
)));
880 bytes
&= ~(HBLKSIZE
-1);
882 ps
= (struct Print_stats
*)dummy
;
883 ps
->total_bytes
+= bytes
;
884 ps
->number_of_blocks
++;
887 void GC_print_block_list()
889 struct Print_stats pstats
;
891 GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN
);
892 pstats
.number_of_blocks
= 0;
893 pstats
.total_bytes
= 0;
894 GC_apply_to_all_blocks(GC_print_block_descr
, (word
)&pstats
);
895 GC_printf2("\nblocks = %lu, bytes = %lu\n",
896 (unsigned long)pstats
.number_of_blocks
,
897 (unsigned long)pstats
.total_bytes
);
900 #endif /* NO_DEBUGGING */
903 * Clear all obj_link pointers in the list of free objects *flp.
905 * This must be done before dropping a list of free gcj-style objects,
906 * since may otherwise end up with dangling "descriptor" pointers.
907 * It may help for other pointer-containing objects.
909 void GC_clear_fl_links(flp
)
916 flp
= &(obj_link(next
));
922 * Perform GC_reclaim_block on the entire heap, after first clearing
923 * small object free lists (if we are not just looking for leaks).
925 void GC_start_reclaim(report_if_found
)
926 int report_if_found
; /* Abort if a GC_reclaimable object is found */
930 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
931 GC_ASSERT(0 == GC_fl_builder_count
);
933 /* Clear reclaim- and free-lists */
934 for (kind
= 0; kind
< GC_n_kinds
; kind
++) {
939 struct hblk
** rlist
= GC_obj_kinds
[kind
].ok_reclaim_list
;
940 GC_bool should_clobber
= (GC_obj_kinds
[kind
].ok_descriptor
!= 0);
942 if (rlist
== 0) continue; /* This kind not used. */
943 if (!report_if_found
) {
944 lim
= &(GC_obj_kinds
[kind
].ok_freelist
[MAXOBJSZ
+1]);
945 for( fop
= GC_obj_kinds
[kind
].ok_freelist
; fop
< lim
; fop
++ ) {
947 if (should_clobber
) {
948 GC_clear_fl_links(fop
);
954 } /* otherwise free list objects are marked, */
955 /* and its safe to leave them */
956 rlim
= rlist
+ MAXOBJSZ
+1;
957 for( rlp
= rlist
; rlp
< rlim
; rlp
++ ) {
963 GC_printf0("GC_reclaim: current block sizes:\n");
964 GC_print_block_list();
967 /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
968 /* or enqueue the block for later processing. */
969 GC_apply_to_all_blocks(GC_reclaim_block
, (word
)report_if_found
);
972 /* This is a very stupid thing to do. We make it possible anyway, */
973 /* so that you can convince yourself that it really is very stupid. */
974 GC_reclaim_all((GC_stop_func
)0, FALSE
);
976 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
977 GC_ASSERT(0 == GC_fl_builder_count
);
983 * Sweep blocks of the indicated object size and kind until either the
984 * appropriate free list is nonempty, or there are no more blocks to
987 void GC_continue_reclaim(sz
, kind
)
992 register struct hblk
* hbp
;
993 register struct obj_kind
* ok
= &(GC_obj_kinds
[kind
]);
994 struct hblk
** rlh
= ok
-> ok_reclaim_list
;
995 ptr_t
*flh
= &(ok
-> ok_freelist
[sz
]);
997 if (rlh
== 0) return; /* No blocks of this kind. */
999 while ((hbp
= *rlh
) != 0) {
1001 *rlh
= hhdr
-> hb_next
;
1002 GC_reclaim_small_nonempty_block(hbp
, FALSE MEM_FOUND_ADDR
);
1003 if (*flh
!= 0) break;
1008 * Reclaim all small blocks waiting to be reclaimed.
1009 * Abort and return FALSE when/if (*stop_func)() returns TRUE.
1010 * If this returns TRUE, then it's safe to restart the world
1011 * with incorrectly cleared mark bits.
1012 * If ignore_old is TRUE, then reclaim only blocks that have been
1013 * recently reclaimed, and discard the rest.
1014 * Stop_func may be 0.
1016 GC_bool
GC_reclaim_all(stop_func
, ignore_old
)
1017 GC_stop_func stop_func
;
1022 register hdr
* hhdr
;
1023 register struct hblk
* hbp
;
1024 register struct obj_kind
* ok
;
1028 CLOCK_TYPE start_time
;
1029 CLOCK_TYPE done_time
;
1031 GET_TIME(start_time
);
1034 for (kind
= 0; kind
< GC_n_kinds
; kind
++) {
1035 ok
= &(GC_obj_kinds
[kind
]);
1036 rlp
= ok
-> ok_reclaim_list
;
1037 if (rlp
== 0) continue;
1038 for (sz
= 1; sz
<= MAXOBJSZ
; sz
++) {
1040 while ((hbp
= *rlh
) != 0) {
1041 if (stop_func
!= (GC_stop_func
)0 && (*stop_func
)()) {
1045 *rlh
= hhdr
-> hb_next
;
1046 if (!ignore_old
|| hhdr
-> hb_last_reclaimed
== GC_gc_no
- 1) {
1047 /* It's likely we'll need it this time, too */
1048 /* It's been touched recently, so this */
1049 /* shouldn't trigger paging. */
1050 GC_reclaim_small_nonempty_block(hbp
, FALSE MEM_FOUND_ADDR
);
1056 GET_TIME(done_time
);
1057 GC_printf1("Disposing of reclaim lists took %lu msecs\n",
1058 MS_TIME_DIFF(done_time
,start_time
));