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