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>