[BACK]Return to reclaim.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc

Annotation of OpenXM_contrib/gc/reclaim.c, Revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>