Back to index

lightning-sunbird  0.9+nobinonly
reclaim.c
Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to use or copy this program
00009  * for any purpose,  provided the above notices are retained on all copies.
00010  * Permission to modify the code and to distribute modified code is granted,
00011  * provided the above notices are retained, and a notice that the code was
00012  * modified is included with the above copyright notice.
00013  */
00014 /* Boehm, February 15, 1996 2:41 pm PST */
00015 
00016 #include <stdio.h>
00017 #include "gc_priv.h"
00018 
00019 signed_word GC_mem_found = 0;
00020                      /* Number of words of memory reclaimed     */
00021 
00022 # ifdef FIND_LEAK
00023 static void report_leak(p, sz)
00024 ptr_t p;
00025 word sz;
00026 {
00027     if (GC_debugging_started && GC_has_debug_info(p)) {
00028         /* only print if object has some debugging info attached. */
00029         if (HDR(p) -> hb_obj_kind == PTRFREE) {
00030             GC_err_printf0("Leaked atomic object at:\n");
00031         } else {
00032             GC_err_printf0("Leaked composite object at:\n");
00033         }
00034         GC_print_obj(p);
00035     } else {
00036 #ifdef MACOS
00037         /* no debug info, so at least try for a type name. */
00038         /* extern const char* getTypeName(void* ptr);
00039         GC_err_printf3("0x%08lX <%s> (%ld)\n", p, getTypeName(p),
00040                        (unsigned long)WORDS_TO_BYTES(sz)); */
00041 #else
00042         GC_err_printf2("0x%lx (appr. size = %ld)\n",
00043                            (unsigned long)p,
00044                            (unsigned long)WORDS_TO_BYTES(sz));
00045 #endif
00046     }
00047 }
00048 
00049 #   define FOUND_FREE(hblk, word_no) \
00050       if (abort_if_found) { \
00051          report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \
00052                    HDR(hblk) -> hb_sz); \
00053       }
00054 # else
00055 #   define FOUND_FREE(hblk, word_no)
00056 # endif
00057 
00058 /*
00059  * reclaim phase
00060  *
00061  */
00062 
00063 
00064 /*
00065  * Test whether a block is completely empty, i.e. contains no marked
00066  * objects.  This does not require the block to be in physical
00067  * memory.
00068  */
00069  
00070 GC_bool GC_block_empty(hhdr)
00071 register hdr * hhdr;
00072 {
00073     register word *p = (word *)(&(hhdr -> hb_marks[0]));
00074     register word * plim =
00075                      (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ]));
00076     while (p < plim) {
00077        if (*p++) return(FALSE);
00078     }
00079     return(TRUE);
00080 }
00081 
00082 # ifdef GATHERSTATS
00083 #   define INCR_WORDS(sz) n_words_found += (sz)
00084 # else
00085 #   define INCR_WORDS(sz)
00086 # endif
00087 /*
00088  * Restore unmarked small objects in h of size sz to the object
00089  * free list.  Returns the new list.
00090  * Clears unmarked objects.
00091  */
00092 /*ARGSUSED*/
00093 ptr_t GC_reclaim_clear(hbp, hhdr, sz, list, abort_if_found)
00094 register struct hblk *hbp;  /* ptr to current heap block              */
00095 register hdr * hhdr;
00096 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00097 register ptr_t list;
00098 register word sz;
00099 {
00100     register int word_no;
00101     register word *p, *q, *plim;
00102 #   ifdef GATHERSTATS
00103         register int n_words_found = 0;
00104 #   endif        
00105     
00106     p = (word *)(hbp->hb_body);
00107     word_no = HDR_WORDS;
00108     plim = (word *)((((word)hbp) + HBLKSIZE)
00109                  - WORDS_TO_BYTES(sz));
00110 
00111     /* go through all words in block */
00112     while( p <= plim )  {
00113       if( mark_bit_from_hdr(hhdr, word_no) ) {
00114        p += sz;
00115       } else {
00116        FOUND_FREE(hbp, word_no);
00117        INCR_WORDS(sz);
00118 #if !defined(FIND_LEAK) || 1
00119        if (GC_root_size) {
00120          /* object is available - put on list */
00121          obj_link(p) = list;
00122          list = ((ptr_t)p);
00123          /* Clear object, advance p to next object in the process */
00124          q = p + sz;
00125          p++; /* Skip link field */
00126          while (p < q) {
00127            *p++ = 0;
00128          }
00129        } else {
00130          /* roots gone, just advance. */
00131          p += sz;
00132        }
00133 #else
00134        /* let leaks accumulate. */
00135        p += sz;
00136 #endif
00137       }
00138       word_no += sz;
00139     }
00140 #   ifdef GATHERSTATS
00141     GC_mem_found += n_words_found;
00142 #   endif
00143     return(list);
00144 }
00145 
00146 #ifndef SMALL_CONFIG
00147 
00148 /*
00149  * A special case for 2 word composite objects (e.g. cons cells):
00150  */
00151 /*ARGSUSED*/
00152 ptr_t GC_reclaim_clear2(hbp, hhdr, list, abort_if_found)
00153 register struct hblk *hbp;  /* ptr to current heap block              */
00154 hdr * hhdr;
00155 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00156 register ptr_t list;
00157 {
00158     register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00159     register word *p, *plim;
00160 #   ifdef GATHERSTATS
00161         register int n_words_found = 0;
00162 #   endif
00163     register word mark_word;
00164     register int i;
00165 #   define DO_OBJ(start_displ) \
00166        if (!(mark_word & ((word)1 << start_displ))) { \
00167            FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00168            if (GC_root_size) { p[start_displ] = (word)list; \
00169            list = (ptr_t)(p+start_displ); \
00170            p[start_displ+1] = 0; \
00171            INCR_WORDS(2); } \
00172        }
00173     
00174     p = (word *)(hbp->hb_body);
00175     plim = (word *)(((word)hbp) + HBLKSIZE);
00176 
00177     /* go through all words in block */
00178        while( p < plim )  {
00179            mark_word = *mark_word_addr++;
00180            for (i = 0; i < WORDSZ; i += 8) {
00181               DO_OBJ(0);
00182               DO_OBJ(2);
00183               DO_OBJ(4);
00184               DO_OBJ(6);
00185               p += 8;
00186               mark_word >>= 8;
00187            }
00188        }              
00189 #   ifdef GATHERSTATS
00190        GC_mem_found += n_words_found;
00191 #   endif
00192     return(list);
00193 #   undef DO_OBJ
00194 }
00195 
00196 /*
00197  * Another special case for 4 word composite objects:
00198  */
00199 /*ARGSUSED*/
00200 ptr_t GC_reclaim_clear4(hbp, hhdr, list, abort_if_found)
00201 register struct hblk *hbp;  /* ptr to current heap block              */
00202 hdr * hhdr;
00203 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00204 register ptr_t list;
00205 {
00206     register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00207     register word *p, *plim;
00208 #   ifdef GATHERSTATS
00209         register int n_words_found = 0;
00210 #   endif
00211     register word mark_word;
00212 #   define DO_OBJ(start_displ) \
00213        if (!(mark_word & ((word)1 << start_displ))) { \
00214            FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00215            if (GC_root_size) { \
00216            p[start_displ] = (word)list; \
00217            list = (ptr_t)(p+start_displ); \
00218            p[start_displ+1] = 0; \
00219            p[start_displ+2] = 0; \
00220            p[start_displ+3] = 0; \
00221            INCR_WORDS(4); \
00222            } \
00223        }
00224     
00225     p = (word *)(hbp->hb_body);
00226     plim = (word *)(((word)hbp) + HBLKSIZE);
00227 
00228     /* go through all words in block */
00229        while( p < plim )  {
00230            mark_word = *mark_word_addr++;
00231            DO_OBJ(0);
00232            DO_OBJ(4);
00233            DO_OBJ(8);
00234            DO_OBJ(12);
00235            DO_OBJ(16);
00236            DO_OBJ(20);
00237            DO_OBJ(24);
00238            DO_OBJ(28);
00239 #          if CPP_WORDSZ == 64
00240              DO_OBJ(32);
00241              DO_OBJ(36);
00242              DO_OBJ(40);
00243              DO_OBJ(44);
00244              DO_OBJ(48);
00245              DO_OBJ(52);
00246              DO_OBJ(56);
00247              DO_OBJ(60);
00248 #          endif
00249            p += WORDSZ;
00250        }              
00251 #   ifdef GATHERSTATS
00252        GC_mem_found += n_words_found;
00253 #   endif
00254     return(list);
00255 #   undef DO_OBJ
00256 }
00257 
00258 #endif /* !SMALL_CONFIG */
00259 
00260 /* The same thing, but don't clear objects: */
00261 /*ARGSUSED*/
00262 ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list, abort_if_found)
00263 register struct hblk *hbp;  /* ptr to current heap block              */
00264 register hdr * hhdr;
00265 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00266 register ptr_t list;
00267 register word sz;
00268 {
00269     register int word_no;
00270     register word *p, *plim;
00271 #   ifdef GATHERSTATS
00272         register int n_words_found = 0;
00273 #   endif
00274     
00275     p = (word *)(hbp->hb_body);
00276     word_no = HDR_WORDS;
00277     plim = (word *)((((word)hbp) + HBLKSIZE)
00278                  - WORDS_TO_BYTES(sz));
00279 
00280     /* go through all words in block */
00281        while( p <= plim )  {
00282            if( !mark_bit_from_hdr(hhdr, word_no) ) {
00283             FOUND_FREE(hbp, word_no);
00284             INCR_WORDS(sz);
00285             if (GC_root_size) {
00286                 /* object is available - put on list */
00287                 obj_link(p) = list;
00288                 list = ((ptr_t)p);
00289             }
00290            }
00291            p += sz;
00292            word_no += sz;
00293        }
00294 #   ifdef GATHERSTATS
00295        GC_mem_found += n_words_found;
00296 #   endif
00297     return(list);
00298 }
00299 
00300 #ifndef SMALL_CONFIG
00301 /*
00302  * Another special case for 2 word atomic objects:
00303  */
00304 /*ARGSUSED*/
00305 ptr_t GC_reclaim_uninit2(hbp, hhdr, list, abort_if_found)
00306 register struct hblk *hbp;  /* ptr to current heap block              */
00307 hdr * hhdr;
00308 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00309 register ptr_t list;
00310 {
00311     register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00312     register word *p, *plim;
00313 #   ifdef GATHERSTATS
00314         register int n_words_found = 0;
00315 #   endif
00316     register word mark_word;
00317     register int i;
00318 #   define DO_OBJ(start_displ) \
00319        if (!(mark_word & ((word)1 << start_displ))) { \
00320            FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00321            if (GC_root_size) { \
00322            p[start_displ] = (word)list; \
00323            list = (ptr_t)(p+start_displ); \
00324            INCR_WORDS(2); \
00325            } \
00326        }
00327     
00328     p = (word *)(hbp->hb_body);
00329     plim = (word *)(((word)hbp) + HBLKSIZE);
00330 
00331     /* go through all words in block */
00332        while( p < plim )  {
00333            mark_word = *mark_word_addr++;
00334            for (i = 0; i < WORDSZ; i += 8) {
00335               DO_OBJ(0);
00336               DO_OBJ(2);
00337               DO_OBJ(4);
00338               DO_OBJ(6);
00339               p += 8;
00340               mark_word >>= 8;
00341            }
00342        }              
00343 #   ifdef GATHERSTATS
00344        GC_mem_found += n_words_found;
00345 #   endif
00346     return(list);
00347 #   undef DO_OBJ
00348 }
00349 
00350 /*
00351  * Another special case for 4 word atomic objects:
00352  */
00353 /*ARGSUSED*/
00354 ptr_t GC_reclaim_uninit4(hbp, hhdr, list, abort_if_found)
00355 register struct hblk *hbp;  /* ptr to current heap block              */
00356 hdr * hhdr;
00357 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00358 register ptr_t list;
00359 {
00360     register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00361     register word *p, *plim;
00362 #   ifdef GATHERSTATS
00363         register int n_words_found = 0;
00364 #   endif
00365     register word mark_word;
00366 #   define DO_OBJ(start_displ) \
00367        if (!(mark_word & ((word)1 << start_displ))) { \
00368            FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00369            if (GC_root_size) { \
00370            p[start_displ] = (word)list; \
00371            list = (ptr_t)(p+start_displ); \
00372            INCR_WORDS(4); \
00373            } \
00374        }
00375     
00376     p = (word *)(hbp->hb_body);
00377     plim = (word *)(((word)hbp) + HBLKSIZE);
00378 
00379     /* go through all words in block */
00380        while( p < plim )  {
00381            mark_word = *mark_word_addr++;
00382            DO_OBJ(0);
00383            DO_OBJ(4);
00384            DO_OBJ(8);
00385            DO_OBJ(12);
00386            DO_OBJ(16);
00387            DO_OBJ(20);
00388            DO_OBJ(24);
00389            DO_OBJ(28);
00390 #          if CPP_WORDSZ == 64
00391              DO_OBJ(32);
00392              DO_OBJ(36);
00393              DO_OBJ(40);
00394              DO_OBJ(44);
00395              DO_OBJ(48);
00396              DO_OBJ(52);
00397              DO_OBJ(56);
00398              DO_OBJ(60);
00399 #          endif
00400            p += WORDSZ;
00401        }              
00402 #   ifdef GATHERSTATS
00403        GC_mem_found += n_words_found;
00404 #   endif
00405     return(list);
00406 #   undef DO_OBJ
00407 }
00408 
00409 /* Finally the one word case, which never requires any clearing: */
00410 /*ARGSUSED*/
00411 ptr_t GC_reclaim1(hbp, hhdr, list, abort_if_found)
00412 register struct hblk *hbp;  /* ptr to current heap block              */
00413 hdr * hhdr;
00414 GC_bool abort_if_found;            /* Abort if a reclaimable object is found */
00415 register ptr_t list;
00416 {
00417     register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]);
00418     register word *p, *plim;
00419 #   ifdef GATHERSTATS
00420         register int n_words_found = 0;
00421 #   endif
00422     register word mark_word;
00423     register int i;
00424 #   define DO_OBJ(start_displ) \
00425        if (!(mark_word & ((word)1 << start_displ))) { \
00426            FOUND_FREE(hbp, p - (word *)hbp + start_displ); \
00427            if (GC_root_size) { \
00428            p[start_displ] = (word)list; \
00429            list = (ptr_t)(p+start_displ); \
00430            INCR_WORDS(1); \
00431            } \
00432        }
00433     
00434     p = (word *)(hbp->hb_body);
00435     plim = (word *)(((word)hbp) + HBLKSIZE);
00436 
00437     /* go through all words in block */
00438        while( p < plim )  {
00439            mark_word = *mark_word_addr++;
00440            for (i = 0; i < WORDSZ; i += 4) {
00441               DO_OBJ(0);
00442               DO_OBJ(1);
00443               DO_OBJ(2);
00444               DO_OBJ(3);
00445               p += 4;
00446               mark_word >>= 4;
00447            }
00448        }              
00449 #   ifdef GATHERSTATS
00450        GC_mem_found += n_words_found;
00451 #   endif
00452     return(list);
00453 #   undef DO_OBJ
00454 }
00455 
00456 #endif /* !SMALL_CONFIG */
00457 
00458 /*
00459  * Restore unmarked small objects in the block pointed to by hbp
00460  * to the appropriate object free list.
00461  * If entirely empty blocks are to be completely deallocated, then
00462  * caller should perform that check.
00463  */
00464 void GC_reclaim_small_nonempty_block(hbp, abort_if_found)
00465 register struct hblk *hbp;  /* ptr to current heap block              */
00466 int abort_if_found;         /* Abort if a reclaimable object is found */
00467 {
00468     hdr * hhdr;
00469     register word sz;              /* size of objects in current block       */
00470     register struct obj_kind * ok;
00471     register ptr_t * flh;
00472     register int kind;
00473     
00474     hhdr = HDR(hbp);
00475     sz = hhdr -> hb_sz;
00476     hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
00477     kind = hhdr -> hb_obj_kind;
00478     ok = &GC_obj_kinds[kind];
00479     flh = &(ok -> ok_freelist[sz]);
00480     GC_write_hint(hbp);
00481 
00482     if (ok -> ok_init) {
00483       switch(sz) {
00484 #      ifndef SMALL_CONFIG
00485         case 1:
00486             *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
00487             break;
00488         case 2:
00489             *flh = GC_reclaim_clear2(hbp, hhdr, *flh, abort_if_found);
00490             break;
00491         case 4:
00492             *flh = GC_reclaim_clear4(hbp, hhdr, *flh, abort_if_found);
00493             break;
00494 #      endif
00495         default:
00496             *flh = GC_reclaim_clear(hbp, hhdr, sz, *flh, abort_if_found);
00497             break;
00498       }
00499     } else {
00500       switch(sz) {
00501 #      ifndef SMALL_CONFIG
00502         case 1:
00503             *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
00504             break;
00505         case 2:
00506             *flh = GC_reclaim_uninit2(hbp, hhdr, *flh, abort_if_found);
00507             break;
00508         case 4:
00509             *flh = GC_reclaim_uninit4(hbp, hhdr, *flh, abort_if_found);
00510             break;
00511 #      endif
00512         default:
00513             *flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh, abort_if_found);
00514             break;
00515       }
00516     } 
00517     if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(hhdr);
00518 }
00519 
00520 /*
00521  * Restore an unmarked large object or an entirely empty blocks of small objects
00522  * to the heap block free list.
00523  * Otherwise enqueue the block for later processing
00524  * by GC_reclaim_small_nonempty_block.
00525  * If abort_if_found is TRUE, then process any block immediately.
00526  */
00527 void GC_reclaim_block(hbp, abort_if_found)
00528 register struct hblk *hbp;  /* ptr to current heap block              */
00529 word abort_if_found;        /* Abort if a reclaimable object is found */
00530 {
00531     register hdr * hhdr;
00532     register word sz;              /* size of objects in current block       */
00533     register struct obj_kind * ok;
00534     struct hblk ** rlh;
00535 
00536     hhdr = HDR(hbp);
00537     sz = hhdr -> hb_sz;
00538     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
00539 
00540     if( sz > MAXOBJSZ ) {  /* 1 big object */
00541         if( !mark_bit_from_hdr(hhdr, HDR_WORDS) ) {
00542            FOUND_FREE(hbp, HDR_WORDS);
00543            if (GC_root_size) {
00544 #          ifdef GATHERSTATS
00545                GC_mem_found += sz;
00546 #          endif
00547            GC_freehblk(hbp);
00548            }
00549        }
00550     } else {
00551         GC_bool empty = GC_block_empty(hhdr);
00552         if (abort_if_found) {
00553          GC_reclaim_small_nonempty_block(hbp, (int)abort_if_found);
00554         } else if (empty) {
00555 #        ifdef GATHERSTATS
00556             GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
00557 #        endif
00558           GC_freehblk(hbp);
00559         } else {
00560           /* group of smaller objects, enqueue the real work */
00561           rlh = &(ok -> ok_reclaim_list[sz]);
00562           hhdr -> hb_next = *rlh;
00563           *rlh = hbp;
00564         }
00565     }
00566 }
00567 
00568 #if !defined(NO_DEBUGGING)
00569 /* Routines to gather and print heap block info  */
00570 /* intended for debugging.  Otherwise should be called  */
00571 /* with lock.                                    */
00572 static size_t number_of_blocks;
00573 static size_t total_bytes;
00574 
00575 /* Number of set bits in a word.  Not performance critical.    */
00576 static int set_bits(n)
00577 word n;
00578 {
00579     register word m = n;
00580     register int result = 0;
00581     
00582     while (m > 0) {
00583        if (m & 1) result++;
00584        m >>= 1;
00585     }
00586     return(result);
00587 }
00588 
00589 /* Return the number of set mark bits in the given header      */
00590 int GC_n_set_marks(hhdr)
00591 hdr * hhdr;
00592 {
00593     register int result = 0;
00594     register int i;
00595     
00596     for (i = 0; i < MARK_BITS_SZ; i++) {
00597         result += set_bits(hhdr -> hb_marks[i]);
00598     }
00599     return(result);
00600 }
00601 
00602 /*ARGSUSED*/
00603 void GC_print_block_descr(h, dummy)
00604 struct hblk *h;
00605 word dummy;
00606 {
00607     register hdr * hhdr = HDR(h);
00608     register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
00609     
00610     GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),
00611                              (unsigned long)bytes,
00612                              (unsigned long)(GC_n_set_marks(hhdr)));
00613     bytes += HDR_BYTES + HBLKSIZE-1;
00614     bytes &= ~(HBLKSIZE-1);
00615     total_bytes += bytes;
00616     number_of_blocks++;
00617 }
00618 
00619 void GC_print_block_list()
00620 {
00621     GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
00622     number_of_blocks = 0;
00623     total_bytes = 0;
00624     GC_apply_to_all_blocks(GC_print_block_descr, (word)0);
00625     GC_printf2("\nblocks = %lu, bytes = %lu\n",
00626               (unsigned long)number_of_blocks,
00627               (unsigned long)total_bytes);
00628 }
00629 
00630 #endif /* NO_DEBUGGING */
00631 
00632 /*
00633  * Do the same thing on the entire heap, after first clearing small object
00634  * free lists (if we are not just looking for leaks).
00635  */
00636 void GC_start_reclaim(abort_if_found)
00637 int abort_if_found;         /* Abort if a GC_reclaimable object is found */
00638 {
00639     int kind;
00640     
00641     /* Clear reclaim- and free-lists */
00642       for (kind = 0; kind < GC_n_kinds; kind++) {
00643         register ptr_t *fop;
00644         register ptr_t *lim;
00645         register struct hblk ** rlp;
00646         register struct hblk ** rlim;
00647         register struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
00648         
00649         if (rlist == 0) continue;  /* This kind not used.      */
00650         if (!abort_if_found) {
00651             lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
00652            for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
00653              *fop = 0;
00654            }
00655        } /* otherwise free list objects are marked,     */
00656          /* and its safe to leave them                  */
00657        rlim = rlist + MAXOBJSZ+1;
00658        for( rlp = rlist; rlp < rlim; rlp++ ) {
00659            *rlp = 0;
00660        }
00661       }
00662     
00663 #   ifdef PRINTBLOCKS
00664         GC_printf0("GC_reclaim: current block sizes:\n");
00665         GC_print_block_list();
00666 #   endif
00667 
00668   /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
00669   /* or enqueue the block for later processing.                          */
00670     GC_apply_to_all_blocks(GC_reclaim_block, (word)abort_if_found);
00671     
00672 }
00673 
00674 /*
00675  * Sweep blocks of the indicated object size and kind until either the
00676  * appropriate free list is nonempty, or there are no more blocks to
00677  * sweep.
00678  */
00679 void GC_continue_reclaim(sz, kind)
00680 word sz;      /* words */
00681 int kind;
00682 {
00683     register hdr * hhdr;
00684     register struct hblk * hbp;
00685     register struct obj_kind * ok = &(GC_obj_kinds[kind]);
00686     struct hblk ** rlh = ok -> ok_reclaim_list;
00687     ptr_t *flh = &(ok -> ok_freelist[sz]);
00688     
00689     if (rlh == 0) return;   /* No blocks of this kind.  */
00690     rlh += sz;
00691     while ((hbp = *rlh) != 0) {
00692         hhdr = HDR(hbp);
00693         *rlh = hhdr -> hb_next;
00694         GC_reclaim_small_nonempty_block(hbp, FALSE);
00695         if (*flh != 0) break;
00696     }
00697 }
00698 
00699 /*
00700  * Reclaim all small blocks waiting to be reclaimed.
00701  * Abort and return FALSE when/if (*stop_func)() returns TRUE.
00702  * If this returns TRUE, then it's safe to restart the world
00703  * with incorrectly cleared mark bits.
00704  * If ignore_old is TRUE, then reclain only blocks that have been 
00705  * recently reclaimed, and discard the rest.
00706  * Stop_func may be 0.
00707  */
00708 GC_bool GC_reclaim_all(stop_func, ignore_old)
00709 GC_stop_func stop_func;
00710 GC_bool ignore_old;
00711 {
00712     register word sz;
00713     register int kind;
00714     register hdr * hhdr;
00715     register struct hblk * hbp;
00716     register struct obj_kind * ok;
00717     struct hblk ** rlp;
00718     struct hblk ** rlh;
00719 #   ifdef PRINTTIMES
00720        CLOCK_TYPE start_time;
00721        CLOCK_TYPE done_time;
00722        
00723        GET_TIME(start_time);
00724 #   endif
00725     
00726     for (kind = 0; kind < GC_n_kinds; kind++) {
00727        ok = &(GC_obj_kinds[kind]);
00728        rlp = ok -> ok_reclaim_list;
00729        if (rlp == 0) continue;
00730        for (sz = 1; sz <= MAXOBJSZ; sz++) {
00731            rlh = rlp + sz;
00732            while ((hbp = *rlh) != 0) {
00733                if (stop_func != (GC_stop_func)0 && (*stop_func)()) {
00734                    return(FALSE);
00735                }
00736               hhdr = HDR(hbp);
00737               *rlh = hhdr -> hb_next;
00738               if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
00739                   /* It's likely we'll need it this time, too  */
00740                   /* It's been touched recently, so this       */
00741                   /* shouldn't trigger paging.          */
00742                   GC_reclaim_small_nonempty_block(hbp, FALSE);
00743               }
00744             }
00745         }
00746     }
00747 #   ifdef PRINTTIMES
00748        GET_TIME(done_time);
00749        GC_printf1("Disposing of reclaim lists took %lu msecs\n",
00750                   MS_TIME_DIFF(done_time,start_time));
00751 #   endif
00752     return(TRUE);
00753 }