Annotation of OpenXM_contrib2/asir2000/gc/finalize.c, Revision 1.1
1.1 ! noro 1: /*
! 2: * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
! 3: * Copyright (c) 1991-1996 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 1, 1996 1:19 pm PST */
! 15: # define I_HIDE_POINTERS
! 16: # include "gc_priv.h"
! 17: # include "gc_mark.h"
! 18:
! 19: /* Type of mark procedure used for marking from finalizable object. */
! 20: /* This procedure normally does not mark the object, only its */
! 21: /* descendents. */
! 22: typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
! 23:
! 24: # define HASH3(addr,size,log_size) \
! 25: ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+(log_size)))) \
! 26: & ((size) - 1))
! 27: #define HASH2(addr,log_size) HASH3(addr, 1 << log_size, log_size)
! 28:
! 29: struct hash_chain_entry {
! 30: word hidden_key;
! 31: struct hash_chain_entry * next;
! 32: };
! 33:
! 34: unsigned GC_finalization_failures = 0;
! 35: /* Number of finalization requests that failed for lack of memory. */
! 36:
! 37: static struct disappearing_link {
! 38: struct hash_chain_entry prolog;
! 39: # define dl_hidden_link prolog.hidden_key
! 40: /* Field to be cleared. */
! 41: # define dl_next(x) (struct disappearing_link *)((x) -> prolog.next)
! 42: # define dl_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
! 43:
! 44: word dl_hidden_obj; /* Pointer to object base */
! 45: } **dl_head = 0;
! 46:
! 47: static signed_word log_dl_table_size = -1;
! 48: /* Binary log of */
! 49: /* current size of array pointed to by dl_head. */
! 50: /* -1 ==> size is 0. */
! 51:
! 52: word GC_dl_entries = 0; /* Number of entries currently in disappearing */
! 53: /* link table. */
! 54:
! 55: static struct finalizable_object {
! 56: struct hash_chain_entry prolog;
! 57: # define fo_hidden_base prolog.hidden_key
! 58: /* Pointer to object base. */
! 59: /* No longer hidden once object */
! 60: /* is on finalize_now queue. */
! 61: # define fo_next(x) (struct finalizable_object *)((x) -> prolog.next)
! 62: # define fo_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
! 63: GC_finalization_proc fo_fn; /* Finalizer. */
! 64: ptr_t fo_client_data;
! 65: word fo_object_size; /* In bytes. */
! 66: finalization_mark_proc * fo_mark_proc; /* Mark-through procedure */
! 67: } **fo_head = 0;
! 68:
! 69: struct finalizable_object * GC_finalize_now = 0;
! 70: /* LIst of objects that should be finalized now. */
! 71:
! 72: static signed_word log_fo_table_size = -1;
! 73:
! 74: word GC_fo_entries = 0;
! 75:
! 76: # ifdef SRC_M3
! 77: void GC_push_finalizer_structures()
! 78: {
! 79: GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word));
! 80: GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word));
! 81: }
! 82: # endif
! 83:
! 84: /* Double the size of a hash table. *size_ptr is the log of its current */
! 85: /* size. May be a noop. */
! 86: /* *table is a pointer to an array of hash headers. If we succeed, we */
! 87: /* update both *table and *log_size_ptr. */
! 88: /* Lock is held. Signals are disabled. */
! 89: void GC_grow_table(table, log_size_ptr)
! 90: struct hash_chain_entry ***table;
! 91: signed_word * log_size_ptr;
! 92: {
! 93: register word i;
! 94: register struct hash_chain_entry *p;
! 95: int log_old_size = *log_size_ptr;
! 96: register int log_new_size = log_old_size + 1;
! 97: word old_size = ((log_old_size == -1)? 0: (1 << log_old_size));
! 98: register word new_size = 1 << log_new_size;
! 99: struct hash_chain_entry **new_table = (struct hash_chain_entry **)
! 100: GC_generic_malloc_inner_ignore_off_page(
! 101: (size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL);
! 102:
! 103: if (new_table == 0) {
! 104: if (table == 0) {
! 105: ABORT("Insufficient space for initial table allocation");
! 106: } else {
! 107: return;
! 108: }
! 109: }
! 110: for (i = 0; i < old_size; i++) {
! 111: p = (*table)[i];
! 112: while (p != 0) {
! 113: register ptr_t real_key = (ptr_t)REVEAL_POINTER(p -> hidden_key);
! 114: register struct hash_chain_entry *next = p -> next;
! 115: register int new_hash = HASH3(real_key, new_size, log_new_size);
! 116:
! 117: p -> next = new_table[new_hash];
! 118: new_table[new_hash] = p;
! 119: p = next;
! 120: }
! 121: }
! 122: *log_size_ptr = log_new_size;
! 123: *table = new_table;
! 124: }
! 125:
! 126: # if defined(__STDC__) || defined(__cplusplus)
! 127: int GC_register_disappearing_link(GC_PTR * link)
! 128: # else
! 129: int GC_register_disappearing_link(link)
! 130: GC_PTR * link;
! 131: # endif
! 132: {
! 133: ptr_t base;
! 134:
! 135: base = (ptr_t)GC_base((GC_PTR)link);
! 136: if (base == 0)
! 137: ABORT("Bad arg to GC_register_disappearing_link");
! 138: return(GC_general_register_disappearing_link(link, base));
! 139: }
! 140:
! 141: # if defined(__STDC__) || defined(__cplusplus)
! 142: int GC_general_register_disappearing_link(GC_PTR * link,
! 143: GC_PTR obj)
! 144: # else
! 145: int GC_general_register_disappearing_link(link, obj)
! 146: GC_PTR * link;
! 147: GC_PTR obj;
! 148: # endif
! 149:
! 150: {
! 151: struct disappearing_link *curr_dl;
! 152: int index;
! 153: struct disappearing_link * new_dl;
! 154: DCL_LOCK_STATE;
! 155:
! 156: if ((word)link & (ALIGNMENT-1))
! 157: ABORT("Bad arg to GC_general_register_disappearing_link");
! 158: # ifdef THREADS
! 159: DISABLE_SIGNALS();
! 160: LOCK();
! 161: # endif
! 162: if (log_dl_table_size == -1
! 163: || GC_dl_entries > ((word)1 << log_dl_table_size)) {
! 164: # ifndef THREADS
! 165: DISABLE_SIGNALS();
! 166: # endif
! 167: GC_grow_table((struct hash_chain_entry ***)(&dl_head),
! 168: &log_dl_table_size);
! 169: # ifdef PRINTSTATS
! 170: GC_printf1("Grew dl table to %lu entries\n",
! 171: (unsigned long)(1 << log_dl_table_size));
! 172: # endif
! 173: # ifndef THREADS
! 174: ENABLE_SIGNALS();
! 175: # endif
! 176: }
! 177: index = HASH2(link, log_dl_table_size);
! 178: curr_dl = dl_head[index];
! 179: for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
! 180: if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
! 181: curr_dl -> dl_hidden_obj = HIDE_POINTER(obj);
! 182: # ifdef THREADS
! 183: UNLOCK();
! 184: ENABLE_SIGNALS();
! 185: # endif
! 186: return(1);
! 187: }
! 188: }
! 189: # ifdef THREADS
! 190: new_dl = (struct disappearing_link *)
! 191: GC_generic_malloc_inner(sizeof(struct disappearing_link),NORMAL);
! 192: # else
! 193: new_dl = (struct disappearing_link *)
! 194: GC_malloc(sizeof(struct disappearing_link));
! 195: # endif
! 196: if (new_dl != 0) {
! 197: new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
! 198: new_dl -> dl_hidden_link = HIDE_POINTER(link);
! 199: dl_set_next(new_dl, dl_head[index]);
! 200: dl_head[index] = new_dl;
! 201: GC_dl_entries++;
! 202: } else {
! 203: GC_finalization_failures++;
! 204: }
! 205: # ifdef THREADS
! 206: UNLOCK();
! 207: ENABLE_SIGNALS();
! 208: # endif
! 209: return(0);
! 210: }
! 211:
! 212: # if defined(__STDC__) || defined(__cplusplus)
! 213: int GC_unregister_disappearing_link(GC_PTR * link)
! 214: # else
! 215: int GC_unregister_disappearing_link(link)
! 216: GC_PTR * link;
! 217: # endif
! 218: {
! 219: struct disappearing_link *curr_dl, *prev_dl;
! 220: int index;
! 221: DCL_LOCK_STATE;
! 222:
! 223: DISABLE_SIGNALS();
! 224: LOCK();
! 225: index = HASH2(link, log_dl_table_size);
! 226: if (((unsigned long)link & (ALIGNMENT-1))) goto out;
! 227: prev_dl = 0; curr_dl = dl_head[index];
! 228: while (curr_dl != 0) {
! 229: if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
! 230: if (prev_dl == 0) {
! 231: dl_head[index] = dl_next(curr_dl);
! 232: } else {
! 233: dl_set_next(prev_dl, dl_next(curr_dl));
! 234: }
! 235: GC_dl_entries--;
! 236: UNLOCK();
! 237: ENABLE_SIGNALS();
! 238: GC_free((GC_PTR)curr_dl);
! 239: return(1);
! 240: }
! 241: prev_dl = curr_dl;
! 242: curr_dl = dl_next(curr_dl);
! 243: }
! 244: out:
! 245: UNLOCK();
! 246: ENABLE_SIGNALS();
! 247: return(0);
! 248: }
! 249:
! 250: /* Possible finalization_marker procedures. Note that mark stack */
! 251: /* overflow is handled by the caller, and is not a disaster. */
! 252: void GC_normal_finalize_mark_proc(p)
! 253: ptr_t p;
! 254: {
! 255: hdr * hhdr = HDR(p);
! 256:
! 257: PUSH_OBJ((word *)p, hhdr, GC_mark_stack_top,
! 258: &(GC_mark_stack[GC_mark_stack_size]));
! 259: }
! 260:
! 261: /* This only pays very partial attention to the mark descriptor. */
! 262: /* It does the right thing for normal and atomic objects, and treats */
! 263: /* most others as normal. */
! 264: void GC_ignore_self_finalize_mark_proc(p)
! 265: ptr_t p;
! 266: {
! 267: hdr * hhdr = HDR(p);
! 268: word descr = hhdr -> hb_descr;
! 269: ptr_t q, r;
! 270: ptr_t scan_limit;
! 271: ptr_t target_limit = p + WORDS_TO_BYTES(hhdr -> hb_sz) - 1;
! 272:
! 273: if ((descr & DS_TAGS) == DS_LENGTH) {
! 274: scan_limit = p + descr - sizeof(word);
! 275: } else {
! 276: scan_limit = target_limit + 1 - sizeof(word);
! 277: }
! 278: for (q = p; q <= scan_limit; q += ALIGNMENT) {
! 279: r = *(ptr_t *)q;
! 280: if (r < p || r > target_limit) {
! 281: GC_PUSH_ONE_HEAP((word)r, q);
! 282: }
! 283: }
! 284: }
! 285:
! 286: /*ARGSUSED*/
! 287: void GC_null_finalize_mark_proc(p)
! 288: ptr_t p;
! 289: {
! 290: }
! 291:
! 292:
! 293:
! 294: /* Register a finalization function. See gc.h for details. */
! 295: /* in the nonthreads case, we try to avoid disabling signals, */
! 296: /* since it can be expensive. Threads packages typically */
! 297: /* make it cheaper. */
! 298: void GC_register_finalizer_inner(obj, fn, cd, ofn, ocd, mp)
! 299: GC_PTR obj;
! 300: GC_finalization_proc fn;
! 301: GC_PTR cd;
! 302: GC_finalization_proc * ofn;
! 303: GC_PTR * ocd;
! 304: finalization_mark_proc * mp;
! 305: {
! 306: ptr_t base;
! 307: struct finalizable_object * curr_fo, * prev_fo;
! 308: int index;
! 309: struct finalizable_object *new_fo;
! 310: DCL_LOCK_STATE;
! 311:
! 312: # ifdef THREADS
! 313: DISABLE_SIGNALS();
! 314: LOCK();
! 315: # endif
! 316: if (log_fo_table_size == -1
! 317: || GC_fo_entries > ((word)1 << log_fo_table_size)) {
! 318: # ifndef THREADS
! 319: DISABLE_SIGNALS();
! 320: # endif
! 321: GC_grow_table((struct hash_chain_entry ***)(&fo_head),
! 322: &log_fo_table_size);
! 323: # ifdef PRINTSTATS
! 324: GC_printf1("Grew fo table to %lu entries\n",
! 325: (unsigned long)(1 << log_fo_table_size));
! 326: # endif
! 327: # ifndef THREADS
! 328: ENABLE_SIGNALS();
! 329: # endif
! 330: }
! 331: /* in the THREADS case signals are disabled and we hold allocation */
! 332: /* lock; otherwise neither is true. Proceed carefully. */
! 333: base = (ptr_t)obj;
! 334: index = HASH2(base, log_fo_table_size);
! 335: prev_fo = 0; curr_fo = fo_head[index];
! 336: while (curr_fo != 0) {
! 337: if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
! 338: /* Interruption by a signal in the middle of this */
! 339: /* should be safe. The client may see only *ocd */
! 340: /* updated, but we'll declare that to be his */
! 341: /* problem. */
! 342: if (ocd) *ocd = (GC_PTR) curr_fo -> fo_client_data;
! 343: if (ofn) *ofn = curr_fo -> fo_fn;
! 344: /* Delete the structure for base. */
! 345: if (prev_fo == 0) {
! 346: fo_head[index] = fo_next(curr_fo);
! 347: } else {
! 348: fo_set_next(prev_fo, fo_next(curr_fo));
! 349: }
! 350: if (fn == 0) {
! 351: GC_fo_entries--;
! 352: /* May not happen if we get a signal. But a high */
! 353: /* estimate will only make the table larger than */
! 354: /* necessary. */
! 355: # ifndef THREADS
! 356: GC_free((GC_PTR)curr_fo);
! 357: # endif
! 358: } else {
! 359: curr_fo -> fo_fn = fn;
! 360: curr_fo -> fo_client_data = (ptr_t)cd;
! 361: curr_fo -> fo_mark_proc = mp;
! 362: /* Reinsert it. We deleted it first to maintain */
! 363: /* consistency in the event of a signal. */
! 364: if (prev_fo == 0) {
! 365: fo_head[index] = curr_fo;
! 366: } else {
! 367: fo_set_next(prev_fo, curr_fo);
! 368: }
! 369: }
! 370: # ifdef THREADS
! 371: UNLOCK();
! 372: ENABLE_SIGNALS();
! 373: # endif
! 374: return;
! 375: }
! 376: prev_fo = curr_fo;
! 377: curr_fo = fo_next(curr_fo);
! 378: }
! 379: if (ofn) *ofn = 0;
! 380: if (ocd) *ocd = 0;
! 381: if (fn == 0) {
! 382: # ifdef THREADS
! 383: UNLOCK();
! 384: ENABLE_SIGNALS();
! 385: # endif
! 386: return;
! 387: }
! 388: # ifdef THREADS
! 389: new_fo = (struct finalizable_object *)
! 390: GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL);
! 391: # else
! 392: new_fo = (struct finalizable_object *)
! 393: GC_malloc(sizeof(struct finalizable_object));
! 394: # endif
! 395: if (new_fo != 0) {
! 396: new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
! 397: new_fo -> fo_fn = fn;
! 398: new_fo -> fo_client_data = (ptr_t)cd;
! 399: new_fo -> fo_object_size = GC_size(base);
! 400: new_fo -> fo_mark_proc = mp;
! 401: fo_set_next(new_fo, fo_head[index]);
! 402: GC_fo_entries++;
! 403: fo_head[index] = new_fo;
! 404: } else {
! 405: GC_finalization_failures++;
! 406: }
! 407: # ifdef THREADS
! 408: UNLOCK();
! 409: ENABLE_SIGNALS();
! 410: # endif
! 411: }
! 412:
! 413: # if defined(__STDC__)
! 414: void GC_register_finalizer(void * obj,
! 415: GC_finalization_proc fn, void * cd,
! 416: GC_finalization_proc *ofn, void ** ocd)
! 417: # else
! 418: void GC_register_finalizer(obj, fn, cd, ofn, ocd)
! 419: GC_PTR obj;
! 420: GC_finalization_proc fn;
! 421: GC_PTR cd;
! 422: GC_finalization_proc * ofn;
! 423: GC_PTR * ocd;
! 424: # endif
! 425: {
! 426: GC_register_finalizer_inner(obj, fn, cd, ofn,
! 427: ocd, GC_normal_finalize_mark_proc);
! 428: }
! 429:
! 430: # if defined(__STDC__)
! 431: void GC_register_finalizer_ignore_self(void * obj,
! 432: GC_finalization_proc fn, void * cd,
! 433: GC_finalization_proc *ofn, void ** ocd)
! 434: # else
! 435: void GC_register_finalizer_ignore_self(obj, fn, cd, ofn, ocd)
! 436: GC_PTR obj;
! 437: GC_finalization_proc fn;
! 438: GC_PTR cd;
! 439: GC_finalization_proc * ofn;
! 440: GC_PTR * ocd;
! 441: # endif
! 442: {
! 443: GC_register_finalizer_inner(obj, fn, cd, ofn,
! 444: ocd, GC_ignore_self_finalize_mark_proc);
! 445: }
! 446:
! 447: # if defined(__STDC__)
! 448: void GC_register_finalizer_no_order(void * obj,
! 449: GC_finalization_proc fn, void * cd,
! 450: GC_finalization_proc *ofn, void ** ocd)
! 451: # else
! 452: void GC_register_finalizer_no_order(obj, fn, cd, ofn, ocd)
! 453: GC_PTR obj;
! 454: GC_finalization_proc fn;
! 455: GC_PTR cd;
! 456: GC_finalization_proc * ofn;
! 457: GC_PTR * ocd;
! 458: # endif
! 459: {
! 460: GC_register_finalizer_inner(obj, fn, cd, ofn,
! 461: ocd, GC_null_finalize_mark_proc);
! 462: }
! 463:
! 464: /* Called with world stopped. Cause disappearing links to disappear, */
! 465: /* and invoke finalizers. */
! 466: void GC_finalize()
! 467: {
! 468: struct disappearing_link * curr_dl, * prev_dl, * next_dl;
! 469: struct finalizable_object * curr_fo, * prev_fo, * next_fo;
! 470: ptr_t real_ptr, real_link;
! 471: register int i;
! 472: int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
! 473: int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
! 474:
! 475: /* Make disappearing links disappear */
! 476: for (i = 0; i < dl_size; i++) {
! 477: curr_dl = dl_head[i];
! 478: prev_dl = 0;
! 479: while (curr_dl != 0) {
! 480: real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
! 481: real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
! 482: if (!GC_is_marked(real_ptr)) {
! 483: *(word *)real_link = 0;
! 484: next_dl = dl_next(curr_dl);
! 485: if (prev_dl == 0) {
! 486: dl_head[i] = next_dl;
! 487: } else {
! 488: dl_set_next(prev_dl, next_dl);
! 489: }
! 490: GC_clear_mark_bit((ptr_t)curr_dl);
! 491: GC_dl_entries--;
! 492: curr_dl = next_dl;
! 493: } else {
! 494: prev_dl = curr_dl;
! 495: curr_dl = dl_next(curr_dl);
! 496: }
! 497: }
! 498: }
! 499: /* Mark all objects reachable via chains of 1 or more pointers */
! 500: /* from finalizable objects. */
! 501: # ifdef PRINTSTATS
! 502: if (GC_mark_state != MS_NONE) ABORT("Bad mark state");
! 503: # endif
! 504: for (i = 0; i < fo_size; i++) {
! 505: for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
! 506: real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
! 507: if (!GC_is_marked(real_ptr)) {
! 508: GC_MARKED_FOR_FINALIZATION(real_ptr);
! 509: GC_MARK_FO(real_ptr, curr_fo -> fo_mark_proc);
! 510: if (GC_is_marked(real_ptr)) {
! 511: WARN("Finalization cycle involving %lx\n", real_ptr);
! 512: }
! 513: }
! 514: }
! 515: }
! 516: /* Enqueue for finalization all objects that are still */
! 517: /* unreachable. */
! 518: GC_words_finalized = 0;
! 519: for (i = 0; i < fo_size; i++) {
! 520: curr_fo = fo_head[i];
! 521: prev_fo = 0;
! 522: while (curr_fo != 0) {
! 523: real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
! 524: if (!GC_is_marked(real_ptr)) {
! 525: # ifndef JAVA_FINALIZATION
! 526: GC_set_mark_bit(real_ptr);
! 527: # endif
! 528: /* Delete from hash table */
! 529: next_fo = fo_next(curr_fo);
! 530: if (prev_fo == 0) {
! 531: fo_head[i] = next_fo;
! 532: } else {
! 533: fo_set_next(prev_fo, next_fo);
! 534: }
! 535: GC_fo_entries--;
! 536: /* Add to list of objects awaiting finalization. */
! 537: fo_set_next(curr_fo, GC_finalize_now);
! 538: GC_finalize_now = curr_fo;
! 539: /* unhide object pointer so any future collections will */
! 540: /* see it. */
! 541: curr_fo -> fo_hidden_base =
! 542: (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
! 543: GC_words_finalized +=
! 544: ALIGNED_WORDS(curr_fo -> fo_object_size)
! 545: + ALIGNED_WORDS(sizeof(struct finalizable_object));
! 546: # ifdef PRINTSTATS
! 547: if (!GC_is_marked((ptr_t)curr_fo)) {
! 548: ABORT("GC_finalize: found accessible unmarked object\n");
! 549: }
! 550: # endif
! 551: curr_fo = next_fo;
! 552: } else {
! 553: prev_fo = curr_fo;
! 554: curr_fo = fo_next(curr_fo);
! 555: }
! 556: }
! 557: }
! 558:
! 559: # ifdef JAVA_FINALIZATION
! 560: /* make sure we mark everything reachable from objects finalized
! 561: using the no_order mark_proc */
! 562: for (curr_fo = GC_finalize_now;
! 563: curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
! 564: real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
! 565: if (!GC_is_marked(real_ptr)) {
! 566: if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
! 567: GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
! 568: }
! 569: GC_set_mark_bit(real_ptr);
! 570: }
! 571: }
! 572: # endif
! 573:
! 574: /* Remove dangling disappearing links. */
! 575: for (i = 0; i < dl_size; i++) {
! 576: curr_dl = dl_head[i];
! 577: prev_dl = 0;
! 578: while (curr_dl != 0) {
! 579: real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link));
! 580: if (real_link != 0 && !GC_is_marked(real_link)) {
! 581: next_dl = dl_next(curr_dl);
! 582: if (prev_dl == 0) {
! 583: dl_head[i] = next_dl;
! 584: } else {
! 585: dl_set_next(prev_dl, next_dl);
! 586: }
! 587: GC_clear_mark_bit((ptr_t)curr_dl);
! 588: GC_dl_entries--;
! 589: curr_dl = next_dl;
! 590: } else {
! 591: prev_dl = curr_dl;
! 592: curr_dl = dl_next(curr_dl);
! 593: }
! 594: }
! 595: }
! 596: }
! 597:
! 598: #ifdef JAVA_FINALIZATION
! 599:
! 600: /* Enqueue all remaining finalizers to be run - Assumes lock is
! 601: * held, and signals are disabled */
! 602: void GC_enqueue_all_finalizers()
! 603: {
! 604: struct finalizable_object * curr_fo, * prev_fo, * next_fo;
! 605: ptr_t real_ptr, real_link;
! 606: register int i;
! 607: int fo_size;
! 608:
! 609: fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
! 610: GC_words_finalized = 0;
! 611: for (i = 0; i < fo_size; i++) {
! 612: curr_fo = fo_head[i];
! 613: prev_fo = 0;
! 614: while (curr_fo != 0) {
! 615: real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
! 616: GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
! 617: GC_set_mark_bit(real_ptr);
! 618:
! 619: /* Delete from hash table */
! 620: next_fo = fo_next(curr_fo);
! 621: if (prev_fo == 0) {
! 622: fo_head[i] = next_fo;
! 623: } else {
! 624: fo_set_next(prev_fo, next_fo);
! 625: }
! 626: GC_fo_entries--;
! 627:
! 628: /* Add to list of objects awaiting finalization. */
! 629: fo_set_next(curr_fo, GC_finalize_now);
! 630: GC_finalize_now = curr_fo;
! 631:
! 632: /* unhide object pointer so any future collections will */
! 633: /* see it. */
! 634: curr_fo -> fo_hidden_base =
! 635: (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
! 636:
! 637: GC_words_finalized +=
! 638: ALIGNED_WORDS(curr_fo -> fo_object_size)
! 639: + ALIGNED_WORDS(sizeof(struct finalizable_object));
! 640: curr_fo = next_fo;
! 641: }
! 642: }
! 643:
! 644: return;
! 645: }
! 646:
! 647: /* Invoke all remaining finalizers that haven't yet been run.
! 648: * This is needed for strict compliance with the Java standard,
! 649: * which can make the runtime guarantee that all finalizers are run.
! 650: * Unfortunately, the Java standard implies we have to keep running
! 651: * finalizers until there are no more left, a potential infinite loop.
! 652: * YUCK.
! 653: * This routine is externally callable, so is called without
! 654: * the allocation lock.
! 655: */
! 656: void GC_finalize_all()
! 657: {
! 658: DCL_LOCK_STATE;
! 659:
! 660: DISABLE_SIGNALS();
! 661: LOCK();
! 662: while (GC_fo_entries > 0) {
! 663: GC_enqueue_all_finalizers();
! 664: UNLOCK();
! 665: ENABLE_SIGNALS();
! 666: GC_INVOKE_FINALIZERS();
! 667: DISABLE_SIGNALS();
! 668: LOCK();
! 669: }
! 670: UNLOCK();
! 671: ENABLE_SIGNALS();
! 672: }
! 673: #endif
! 674:
! 675: /* Invoke finalizers for all objects that are ready to be finalized. */
! 676: /* Should be called without allocation lock. */
! 677: int GC_invoke_finalizers()
! 678: {
! 679: register struct finalizable_object * curr_fo;
! 680: register int count = 0;
! 681: DCL_LOCK_STATE;
! 682:
! 683: while (GC_finalize_now != 0) {
! 684: # ifdef THREADS
! 685: DISABLE_SIGNALS();
! 686: LOCK();
! 687: # endif
! 688: curr_fo = GC_finalize_now;
! 689: # ifdef THREADS
! 690: if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
! 691: UNLOCK();
! 692: ENABLE_SIGNALS();
! 693: if (curr_fo == 0) break;
! 694: # else
! 695: GC_finalize_now = fo_next(curr_fo);
! 696: # endif
! 697: fo_set_next(curr_fo, 0);
! 698: (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
! 699: curr_fo -> fo_client_data);
! 700: curr_fo -> fo_client_data = 0;
! 701: ++count;
! 702: # ifdef UNDEFINED
! 703: /* This is probably a bad idea. It throws off accounting if */
! 704: /* nearly all objects are finalizable. O.w. it shouldn't */
! 705: /* matter. */
! 706: GC_free((GC_PTR)curr_fo);
! 707: # endif
! 708: }
! 709: return count;
! 710: }
! 711:
! 712: # ifdef __STDC__
! 713: GC_PTR GC_call_with_alloc_lock(GC_fn_type fn,
! 714: GC_PTR client_data)
! 715: # else
! 716: GC_PTR GC_call_with_alloc_lock(fn, client_data)
! 717: GC_fn_type fn;
! 718: GC_PTR client_data;
! 719: # endif
! 720: {
! 721: GC_PTR result;
! 722: DCL_LOCK_STATE;
! 723:
! 724: # ifdef THREADS
! 725: DISABLE_SIGNALS();
! 726: LOCK();
! 727: SET_LOCK_HOLDER();
! 728: # endif
! 729: result = (*fn)(client_data);
! 730: # ifdef THREADS
! 731: UNSET_LOCK_HOLDER();
! 732: UNLOCK();
! 733: ENABLE_SIGNALS();
! 734: # endif
! 735: return(result);
! 736: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>