home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sa104os2.zip / SATHR104.ZIP / SATHER / SYSTEM / GC / RECLAIM.C < prev    next >
C/C++ Source or Header  |  1994-06-13  |  19KB  |  711 lines

  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, June 13, 1994 6:22 pm PDT */
  15.  
  16. #include <stdio.h>
  17. #include "gc_priv.h"
  18.  
  19. signed_word GC_mem_found = 0;
  20.             /* Number of longwords of memory GC_reclaimed     */
  21.  
  22. # ifdef FIND_LEAK
  23. static 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((long)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. 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. 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. 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. 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. 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. 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. 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. 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.     
  445.     hhdr = HDR(hbp);
  446.     sz = hhdr -> hb_sz;
  447.     hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no;
  448.     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
  449.     flh = &(ok -> ok_freelist[sz]);
  450.     GC_write_hint(hbp);
  451.  
  452.     if (ok -> ok_init) {
  453.       switch(sz) {
  454. #      ifndef SMALL_CONFIG
  455.         case 1:
  456.             *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
  457.             break;
  458.         case 2:
  459.             *flh = GC_reclaim_clear2(hbp, hhdr, *flh, abort_if_found);
  460.             break;
  461.         case 4:
  462.             *flh = GC_reclaim_clear4(hbp, hhdr, *flh, abort_if_found);
  463.             break;
  464. #      endif
  465.         default:
  466.             *flh = GC_reclaim_clear(hbp, hhdr, sz, *flh, abort_if_found);
  467.             break;
  468.       }
  469.     } else {
  470.       switch(sz) {
  471. #      ifndef SMALL_CONFIG
  472.         case 1:
  473.             *flh = GC_reclaim1(hbp, hhdr, *flh, abort_if_found);
  474.             break;
  475.         case 2:
  476.             *flh = GC_reclaim_uninit2(hbp, hhdr, *flh, abort_if_found);
  477.             break;
  478.         case 4:
  479.             *flh = GC_reclaim_uninit4(hbp, hhdr, *flh, abort_if_found);
  480.             break;
  481. #      endif
  482.         default:
  483.             *flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh, abort_if_found);
  484.             break;
  485.       }
  486.     } 
  487. }
  488.  
  489. /*
  490.  * Restore an unmarked large object or an entirely empty blocks of small objects
  491.  * to the heap block free list.
  492.  * Otherwise enqueue the block for later processing
  493.  * by GC_reclaim_small_nonempty_block.
  494.  * If abort_if_found is TRUE, then process any block immediately.
  495.  */
  496. void GC_reclaim_block(hbp, abort_if_found)
  497. register struct hblk *hbp;    /* ptr to current heap block        */
  498. word abort_if_found;        /* Abort if a reclaimable object is found */
  499. {
  500.     register hdr * hhdr;
  501.     register word sz;        /* size of objects in current block    */
  502.     register struct obj_kind * ok;
  503.     struct hblk ** rlh;
  504.  
  505.     hhdr = HDR(hbp);
  506.     sz = hhdr -> hb_sz;
  507.     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
  508.  
  509.     if( sz > MAXOBJSZ ) {  /* 1 big object */
  510.         if( !mark_bit_from_hdr(hhdr, HDR_WORDS) ) {
  511.         FOUND_FREE(hbp, HDR_WORDS);
  512. #        ifdef GATHERSTATS
  513.             GC_mem_found += sz;
  514. #        endif
  515.         GC_freehblk(hbp);
  516.     }
  517.     } else {
  518.         bool empty = GC_block_empty(hhdr);
  519.         if (abort_if_found) {
  520.           GC_reclaim_small_nonempty_block(hbp, (int)abort_if_found);
  521.         } else if (empty) {
  522. #      ifdef GATHERSTATS
  523.             GC_mem_found += BYTES_TO_WORDS(HBLKSIZE);
  524. #      endif
  525.           GC_freehblk(hbp);
  526.         } else {
  527.           /* group of smaller objects, enqueue the real work */
  528.           rlh = &(ok -> ok_reclaim_list[sz]);
  529.           hhdr -> hb_next = *rlh;
  530.           *rlh = hbp;
  531.         }
  532.     }
  533. }
  534.  
  535. /* Routines to gather and print heap block info     */
  536. /* intended for debugging.  Otherwise should be called    */
  537. /* with lock.                        */
  538. static number_of_blocks;
  539. static total_bytes;
  540.  
  541. /* Number of set bits in a word.  Not performance critical.    */
  542. static int set_bits(n)
  543. word n;
  544. {
  545.     register word m = n;
  546.     register int result = 0;
  547.     
  548.     while (m > 0) {
  549.         if (m & 1) result++;
  550.         m >>= 1;
  551.     }
  552.     return(result);
  553. }
  554.  
  555. /* Return the number of set mark bits in the given header    */
  556. int GC_n_set_marks(hhdr)
  557. hdr * hhdr;
  558. {
  559.     register int result = 0;
  560.     register int i;
  561.     
  562.     for (i = 0; i < MARK_BITS_SZ; i++) {
  563.         result += set_bits(hhdr -> hb_marks[i]);
  564.     }
  565.     return(result);
  566. }
  567.  
  568. /*ARGSUSED*/
  569. void GC_print_block_descr(h, dummy)
  570. struct hblk *h;
  571. word dummy;
  572. {
  573.     register hdr * hhdr = HDR(h);
  574.     register bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
  575.     
  576.     GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind),
  577.                         (unsigned long)bytes,
  578.                         (unsigned long)(GC_n_set_marks(hhdr)));
  579.     bytes += HDR_BYTES + HBLKSIZE-1;
  580.     bytes &= ~(HBLKSIZE-1);
  581.     total_bytes += bytes;
  582.     number_of_blocks++;
  583. }
  584.  
  585. void GC_print_block_list()
  586. {
  587.     GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
  588.     number_of_blocks = 0;
  589.     total_bytes = 0;
  590.     GC_apply_to_all_blocks(GC_print_block_descr, (word)0);
  591.     GC_printf2("\nblocks = %lu, bytes = %lu\n",
  592.                (unsigned long)number_of_blocks,
  593.                (unsigned long)total_bytes);
  594. }
  595.  
  596. /*
  597.  * Do the same thing on the entire heap, after first clearing small object
  598.  * free lists (if we are not just looking for leaks).
  599.  */
  600. void GC_start_reclaim(abort_if_found)
  601. int abort_if_found;        /* Abort if a GC_reclaimable object is found */
  602. {
  603.     int kind;
  604.     
  605.     /* Clear reclaim- and free-lists */
  606.       for (kind = 0; kind < GC_n_kinds; kind++) {
  607.         register ptr_t *fop;
  608.         register ptr_t *lim;
  609.         register struct hblk ** rlp;
  610.         register struct hblk ** rlim;
  611.         register struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list;
  612.         
  613.         if (rlist == 0) continue;    /* This kind not used.    */
  614.         if (!abort_if_found) {
  615.             lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJSZ+1]);
  616.         for( fop = GC_obj_kinds[kind].ok_freelist; fop < lim; fop++ ) {
  617.           *fop = 0;
  618.         }
  619.     } /* otherwise free list objects are marked,     */
  620.       /* and its safe to leave them            */
  621.     rlim = rlist + MAXOBJSZ+1;
  622.     for( rlp = rlist; rlp < rlim; rlp++ ) {
  623.         *rlp = 0;
  624.     }
  625.       }
  626.     
  627. #   ifdef PRINTBLOCKS
  628.         GC_printf0("GC_reclaim: current block sizes:\n");
  629.         GC_print_block_list();
  630. #   endif
  631.  
  632.   /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
  633.   /* or enqueue the block for later processing.                   */
  634.     GC_apply_to_all_blocks(GC_reclaim_block, (word)abort_if_found);
  635.     
  636. }
  637.  
  638. /*
  639.  * Sweep blocks of the indicated object size and kind until either the
  640.  * appropriate free list is nonempty, or there are no more blocks to
  641.  * sweep.
  642.  */
  643. void GC_continue_reclaim(sz, kind)
  644. word sz;    /* words */
  645. int kind;
  646. {
  647.     register hdr * hhdr;
  648.     register struct hblk * hbp;
  649.     register struct obj_kind * ok = &(GC_obj_kinds[kind]);
  650.     struct hblk ** rlh = ok -> ok_reclaim_list;
  651.     ptr_t *flh = &(ok -> ok_freelist[sz]);
  652.     
  653.     if (rlh == 0) return;    /* No blocks of this kind.    */
  654.     rlh += sz;
  655.     while ((hbp = *rlh) != 0) {
  656.         hhdr = HDR(hbp);
  657.         *rlh = hhdr -> hb_next;
  658.         GC_reclaim_small_nonempty_block(hbp, FALSE);
  659.         if (*flh != 0) break;
  660.     }
  661. }
  662.  
  663. /*
  664.  * Reclaim all blocks that have been recently reclaimed.
  665.  * Clear lists of blocks waiting to be reclaimed.
  666.  * Must be done before clearing mark bits with the world running,
  667.  * since otherwise a subsequent reclamation of block would see
  668.  * the wrong mark bits.
  669.  * SHOULD PROBABLY BE INCREMENTAL
  670.  */
  671. void GC_reclaim_or_delete_all()
  672. {
  673.     register word sz;
  674.     register int kind;
  675.     register hdr * hhdr;
  676.     register struct hblk * hbp;
  677.     register struct obj_kind * ok;
  678.     struct hblk ** rlp;
  679.     struct hblk ** rlh;
  680. #   ifdef PRINTTIMES
  681.     CLOCK_TYPE start_time;
  682.     CLOCK_TYPE done_time;
  683.     
  684.     GET_TIME(start_time);
  685. #   endif
  686.     
  687.     for (kind = 0; kind < GC_n_kinds; kind++) {
  688.         ok = &(GC_obj_kinds[kind]);
  689.         rlp = ok -> ok_reclaim_list;
  690.         if (rlp == 0) continue;
  691.         for (sz = 1; sz <= MAXOBJSZ; sz++) {
  692.             rlh = rlp + sz;
  693.             while ((hbp = *rlh) != 0) {
  694.             hhdr = HDR(hbp);
  695.             *rlh = hhdr -> hb_next;
  696.             if (hhdr -> hb_last_reclaimed == GC_gc_no - 1) {
  697.                 /* It's likely we'll need it this time, too    */
  698.                 /* It's been touched recently, so this    */
  699.                 /* shouldn't trigger paging.        */
  700.                 GC_reclaim_small_nonempty_block(hbp, FALSE);
  701.             }
  702.             }
  703.         }
  704.     }
  705. #   ifdef PRINTTIMES
  706.     GET_TIME(done_time);
  707.     GC_printf1("Disposing of reclaim lists took %lu msecs\n",
  708.                MS_TIME_DIFF(done_time,start_time));
  709. #   endif
  710. }
  711.