Annotation of OpenXM_contrib/gc/dbg_mlc.c, Revision 1.1
1.1 ! maekawa 1: /*
! 2: * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
! 3: * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
! 4: * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
! 5: *
! 6: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
! 7: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
! 8: *
! 9: * Permission is hereby granted to use or copy this program
! 10: * for any purpose, provided the above notices are retained on all copies.
! 11: * Permission to modify the code and to distribute modified code is granted,
! 12: * provided the above notices are retained, and a notice that the code was
! 13: * modified is included with the above copyright notice.
! 14: */
! 15: /* Boehm, October 9, 1995 1:16 pm PDT */
! 16: # include "gc_priv.h"
! 17:
! 18: void GC_default_print_heap_obj_proc();
! 19: GC_API void GC_register_finalizer_no_order
! 20: GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
! 21: GC_finalization_proc *ofn, GC_PTR *ocd));
! 22:
! 23: /* Do we want to and know how to save the call stack at the time of */
! 24: /* an allocation? How much space do we want to use in each object? */
! 25:
! 26: # define START_FLAG ((word)0xfedcedcb)
! 27: # define END_FLAG ((word)0xbcdecdef)
! 28: /* Stored both one past the end of user object, and one before */
! 29: /* the end of the object as seen by the allocator. */
! 30:
! 31:
! 32: /* Object header */
! 33: typedef struct {
! 34: char * oh_string; /* object descriptor string */
! 35: word oh_int; /* object descriptor integers */
! 36: # ifdef NEED_CALLINFO
! 37: struct callinfo oh_ci[NFRAMES];
! 38: # endif
! 39: word oh_sz; /* Original malloc arg. */
! 40: word oh_sf; /* start flag */
! 41: } oh;
! 42: /* The size of the above structure is assumed not to dealign things, */
! 43: /* and to be a multiple of the word length. */
! 44:
! 45: #define DEBUG_BYTES (sizeof (oh) + sizeof (word))
! 46: #undef ROUNDED_UP_WORDS
! 47: #define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
! 48:
! 49:
! 50: #ifdef SAVE_CALL_CHAIN
! 51: # define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci)
! 52: # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
! 53: #else
! 54: # ifdef GC_ADD_CALLER
! 55: # define ADD_CALL_CHAIN(base, ra) ((oh *)(base)) -> oh_ci[0].ci_pc = (ra)
! 56: # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci)
! 57: # else
! 58: # define ADD_CALL_CHAIN(base, ra)
! 59: # define PRINT_CALL_CHAIN(base)
! 60: # endif
! 61: #endif
! 62:
! 63: /* Check whether object with base pointer p has debugging info */
! 64: /* p is assumed to point to a legitimate object in our part */
! 65: /* of the heap. */
! 66: GC_bool GC_has_debug_info(p)
! 67: ptr_t p;
! 68: {
! 69: register oh * ohdr = (oh *)p;
! 70: register ptr_t body = (ptr_t)(ohdr + 1);
! 71: register word sz = GC_size((ptr_t) ohdr);
! 72:
! 73: if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
! 74: || sz < sizeof (oh)) {
! 75: return(FALSE);
! 76: }
! 77: if (ohdr -> oh_sz == sz) {
! 78: /* Object may have had debug info, but has been deallocated */
! 79: return(FALSE);
! 80: }
! 81: if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
! 82: if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
! 83: return(TRUE);
! 84: }
! 85: return(FALSE);
! 86: }
! 87:
! 88: /* Store debugging info into p. Return displaced pointer. */
! 89: /* Assumes we don't hold allocation lock. */
! 90: ptr_t GC_store_debug_info(p, sz, string, integer)
! 91: register ptr_t p; /* base pointer */
! 92: word sz; /* bytes */
! 93: char * string;
! 94: word integer;
! 95: {
! 96: register word * result = (word *)((oh *)p + 1);
! 97: DCL_LOCK_STATE;
! 98:
! 99: /* There is some argument that we should dissble signals here. */
! 100: /* But that's expensive. And this way things should only appear */
! 101: /* inconsistent while we're in the handler. */
! 102: LOCK();
! 103: ((oh *)p) -> oh_string = string;
! 104: ((oh *)p) -> oh_int = integer;
! 105: ((oh *)p) -> oh_sz = sz;
! 106: ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
! 107: ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
! 108: result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
! 109: UNLOCK();
! 110: return((ptr_t)result);
! 111: }
! 112:
! 113: /* Check the object with debugging info at p */
! 114: /* return NIL if it's OK. Else return clobbered */
! 115: /* address. */
! 116: ptr_t GC_check_annotated_obj(ohdr)
! 117: register oh * ohdr;
! 118: {
! 119: register ptr_t body = (ptr_t)(ohdr + 1);
! 120: register word gc_sz = GC_size((ptr_t)ohdr);
! 121: if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
! 122: return((ptr_t)(&(ohdr -> oh_sz)));
! 123: }
! 124: if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
! 125: return((ptr_t)(&(ohdr -> oh_sf)));
! 126: }
! 127: if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
! 128: return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
! 129: }
! 130: if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
! 131: != (END_FLAG ^ (word)body)) {
! 132: return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
! 133: }
! 134: return(0);
! 135: }
! 136:
! 137: void GC_print_obj(p)
! 138: ptr_t p;
! 139: {
! 140: register oh * ohdr = (oh *)GC_base(p);
! 141:
! 142: GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
! 143: GC_err_puts(ohdr -> oh_string);
! 144: GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
! 145: (unsigned long)(ohdr -> oh_sz));
! 146: PRINT_CALL_CHAIN(ohdr);
! 147: }
! 148:
! 149: void GC_debug_print_heap_obj_proc(p)
! 150: ptr_t p;
! 151: {
! 152: if (GC_has_debug_info(p)) {
! 153: GC_print_obj(p);
! 154: } else {
! 155: GC_default_print_heap_obj_proc(p);
! 156: }
! 157: }
! 158:
! 159: void GC_print_smashed_obj(p, clobbered_addr)
! 160: ptr_t p, clobbered_addr;
! 161: {
! 162: register oh * ohdr = (oh *)GC_base(p);
! 163:
! 164: GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
! 165: (unsigned long)p);
! 166: if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
! 167: || ohdr -> oh_string == 0) {
! 168: GC_err_printf1("<smashed>, appr. sz = %ld)\n",
! 169: (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
! 170: } else {
! 171: if (ohdr -> oh_string[0] == '\0') {
! 172: GC_err_puts("EMPTY(smashed?)");
! 173: } else {
! 174: GC_err_puts(ohdr -> oh_string);
! 175: }
! 176: GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
! 177: (unsigned long)(ohdr -> oh_sz));
! 178: PRINT_CALL_CHAIN(ohdr);
! 179: }
! 180: }
! 181:
! 182: void GC_check_heap_proc();
! 183:
! 184: void GC_start_debugging()
! 185: {
! 186: GC_check_heap = GC_check_heap_proc;
! 187: GC_print_heap_obj = GC_debug_print_heap_obj_proc;
! 188: GC_debugging_started = TRUE;
! 189: GC_register_displacement((word)sizeof(oh));
! 190: }
! 191:
! 192: # if defined(__STDC__) || defined(__cplusplus)
! 193: void GC_debug_register_displacement(GC_word offset)
! 194: # else
! 195: void GC_debug_register_displacement(offset)
! 196: GC_word offset;
! 197: # endif
! 198: {
! 199: GC_register_displacement(offset);
! 200: GC_register_displacement((word)sizeof(oh) + offset);
! 201: }
! 202:
! 203: # ifdef GC_ADD_CALLER
! 204: # define EXTRA_ARGS word ra, char * s, int i
! 205: # define OPT_RA ra,
! 206: # else
! 207: # define EXTRA_ARGS char * s, int i
! 208: # define OPT_RA
! 209: # endif
! 210:
! 211: # ifdef __STDC__
! 212: GC_PTR GC_debug_malloc(size_t lb, EXTRA_ARGS)
! 213: # else
! 214: GC_PTR GC_debug_malloc(lb, s, i)
! 215: size_t lb;
! 216: char * s;
! 217: int i;
! 218: # ifdef GC_ADD_CALLER
! 219: --> GC_ADD_CALLER not implemented for K&R C
! 220: # endif
! 221: # endif
! 222: {
! 223: GC_PTR result = GC_malloc(lb + DEBUG_BYTES);
! 224:
! 225: if (result == 0) {
! 226: GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
! 227: (unsigned long) lb);
! 228: GC_err_puts(s);
! 229: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 230: return(0);
! 231: }
! 232: if (!GC_debugging_started) {
! 233: GC_start_debugging();
! 234: }
! 235: ADD_CALL_CHAIN(result, ra);
! 236: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 237: }
! 238:
! 239: #ifdef STUBBORN_ALLOC
! 240: # ifdef __STDC__
! 241: GC_PTR GC_debug_malloc_stubborn(size_t lb, EXTRA_ARGS)
! 242: # else
! 243: GC_PTR GC_debug_malloc_stubborn(lb, s, i)
! 244: size_t lb;
! 245: char * s;
! 246: int i;
! 247: # endif
! 248: {
! 249: GC_PTR result = GC_malloc_stubborn(lb + DEBUG_BYTES);
! 250:
! 251: if (result == 0) {
! 252: GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
! 253: (unsigned long) lb);
! 254: GC_err_puts(s);
! 255: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 256: return(0);
! 257: }
! 258: if (!GC_debugging_started) {
! 259: GC_start_debugging();
! 260: }
! 261: ADD_CALL_CHAIN(result, ra);
! 262: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 263: }
! 264:
! 265: void GC_debug_change_stubborn(p)
! 266: GC_PTR p;
! 267: {
! 268: register GC_PTR q = GC_base(p);
! 269: register hdr * hhdr;
! 270:
! 271: if (q == 0) {
! 272: GC_err_printf1("Bad argument: 0x%lx to GC_debug_change_stubborn\n",
! 273: (unsigned long) p);
! 274: ABORT("GC_debug_change_stubborn: bad arg");
! 275: }
! 276: hhdr = HDR(q);
! 277: if (hhdr -> hb_obj_kind != STUBBORN) {
! 278: GC_err_printf1("GC_debug_change_stubborn arg not stubborn: 0x%lx\n",
! 279: (unsigned long) p);
! 280: ABORT("GC_debug_change_stubborn: arg not stubborn");
! 281: }
! 282: GC_change_stubborn(q);
! 283: }
! 284:
! 285: void GC_debug_end_stubborn_change(p)
! 286: GC_PTR p;
! 287: {
! 288: register GC_PTR q = GC_base(p);
! 289: register hdr * hhdr;
! 290:
! 291: if (q == 0) {
! 292: GC_err_printf1("Bad argument: 0x%lx to GC_debug_end_stubborn_change\n",
! 293: (unsigned long) p);
! 294: ABORT("GC_debug_end_stubborn_change: bad arg");
! 295: }
! 296: hhdr = HDR(q);
! 297: if (hhdr -> hb_obj_kind != STUBBORN) {
! 298: GC_err_printf1("debug_end_stubborn_change arg not stubborn: 0x%lx\n",
! 299: (unsigned long) p);
! 300: ABORT("GC_debug_end_stubborn_change: arg not stubborn");
! 301: }
! 302: GC_end_stubborn_change(q);
! 303: }
! 304:
! 305: #endif /* STUBBORN_ALLOC */
! 306:
! 307: # ifdef __STDC__
! 308: GC_PTR GC_debug_malloc_atomic(size_t lb, EXTRA_ARGS)
! 309: # else
! 310: GC_PTR GC_debug_malloc_atomic(lb, s, i)
! 311: size_t lb;
! 312: char * s;
! 313: int i;
! 314: # endif
! 315: {
! 316: GC_PTR result = GC_malloc_atomic(lb + DEBUG_BYTES);
! 317:
! 318: if (result == 0) {
! 319: GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
! 320: (unsigned long) lb);
! 321: GC_err_puts(s);
! 322: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 323: return(0);
! 324: }
! 325: if (!GC_debugging_started) {
! 326: GC_start_debugging();
! 327: }
! 328: ADD_CALL_CHAIN(result, ra);
! 329: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 330: }
! 331:
! 332: # ifdef __STDC__
! 333: GC_PTR GC_debug_malloc_uncollectable(size_t lb, EXTRA_ARGS)
! 334: # else
! 335: GC_PTR GC_debug_malloc_uncollectable(lb, s, i)
! 336: size_t lb;
! 337: char * s;
! 338: int i;
! 339: # endif
! 340: {
! 341: GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES);
! 342:
! 343: if (result == 0) {
! 344: GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
! 345: (unsigned long) lb);
! 346: GC_err_puts(s);
! 347: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 348: return(0);
! 349: }
! 350: if (!GC_debugging_started) {
! 351: GC_start_debugging();
! 352: }
! 353: ADD_CALL_CHAIN(result, ra);
! 354: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 355: }
! 356:
! 357: #ifdef ATOMIC_UNCOLLECTABLE
! 358: # ifdef __STDC__
! 359: GC_PTR GC_debug_malloc_atomic_uncollectable(size_t lb, EXTRA_ARGS)
! 360: # else
! 361: GC_PTR GC_debug_malloc_atomic_uncollectable(lb, s, i)
! 362: size_t lb;
! 363: char * s;
! 364: int i;
! 365: # endif
! 366: {
! 367: GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES);
! 368:
! 369: if (result == 0) {
! 370: GC_err_printf1(
! 371: "GC_debug_malloc_atomic_uncollectable(%ld) returning NIL (",
! 372: (unsigned long) lb);
! 373: GC_err_puts(s);
! 374: GC_err_printf1(":%ld)\n", (unsigned long)i);
! 375: return(0);
! 376: }
! 377: if (!GC_debugging_started) {
! 378: GC_start_debugging();
! 379: }
! 380: ADD_CALL_CHAIN(result, ra);
! 381: return (GC_store_debug_info(result, (word)lb, s, (word)i));
! 382: }
! 383: #endif /* ATOMIC_UNCOLLECTABLE */
! 384:
! 385: # ifdef __STDC__
! 386: void GC_debug_free(GC_PTR p)
! 387: # else
! 388: void GC_debug_free(p)
! 389: GC_PTR p;
! 390: # endif
! 391: {
! 392: register GC_PTR base = GC_base(p);
! 393: register ptr_t clobbered;
! 394:
! 395: if (base == 0) {
! 396: GC_err_printf1("Attempt to free invalid pointer %lx\n",
! 397: (unsigned long)p);
! 398: if (p != 0) ABORT("free(invalid pointer)");
! 399: }
! 400: if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
! 401: GC_err_printf1(
! 402: "GC_debug_free called on pointer %lx wo debugging info\n",
! 403: (unsigned long)p);
! 404: } else {
! 405: clobbered = GC_check_annotated_obj((oh *)base);
! 406: if (clobbered != 0) {
! 407: if (((oh *)base) -> oh_sz == GC_size(base)) {
! 408: GC_err_printf0(
! 409: "GC_debug_free: found previously deallocated (?) object at ");
! 410: } else {
! 411: GC_err_printf0("GC_debug_free: found smashed object at ");
! 412: }
! 413: GC_print_smashed_obj(p, clobbered);
! 414: }
! 415: /* Invalidate size */
! 416: ((oh *)base) -> oh_sz = GC_size(base);
! 417: }
! 418: # ifdef FIND_LEAK
! 419: GC_free(base);
! 420: # else
! 421: {
! 422: register hdr * hhdr = HDR(p);
! 423: GC_bool uncollectable = FALSE;
! 424:
! 425: if (hhdr -> hb_obj_kind == UNCOLLECTABLE) {
! 426: uncollectable = TRUE;
! 427: }
! 428: # ifdef ATOMIC_UNCOLLECTABLE
! 429: if (hhdr -> hb_obj_kind == AUNCOLLECTABLE) {
! 430: uncollectable = TRUE;
! 431: }
! 432: # endif
! 433: if (uncollectable) GC_free(base);
! 434: }
! 435: # endif
! 436: }
! 437:
! 438: # ifdef __STDC__
! 439: GC_PTR GC_debug_realloc(GC_PTR p, size_t lb, EXTRA_ARGS)
! 440: # else
! 441: GC_PTR GC_debug_realloc(p, lb, s, i)
! 442: GC_PTR p;
! 443: size_t lb;
! 444: char *s;
! 445: int i;
! 446: # endif
! 447: {
! 448: register GC_PTR base = GC_base(p);
! 449: register ptr_t clobbered;
! 450: register GC_PTR result;
! 451: register size_t copy_sz = lb;
! 452: register size_t old_sz;
! 453: register hdr * hhdr;
! 454:
! 455: if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
! 456: if (base == 0) {
! 457: GC_err_printf1(
! 458: "Attempt to reallocate invalid pointer %lx\n", (unsigned long)p);
! 459: ABORT("realloc(invalid pointer)");
! 460: }
! 461: if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
! 462: GC_err_printf1(
! 463: "GC_debug_realloc called on pointer %lx wo debugging info\n",
! 464: (unsigned long)p);
! 465: return(GC_realloc(p, lb));
! 466: }
! 467: hhdr = HDR(base);
! 468: switch (hhdr -> hb_obj_kind) {
! 469: # ifdef STUBBORN_ALLOC
! 470: case STUBBORN:
! 471: result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
! 472: break;
! 473: # endif
! 474: case NORMAL:
! 475: result = GC_debug_malloc(lb, OPT_RA s, i);
! 476: break;
! 477: case PTRFREE:
! 478: result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
! 479: break;
! 480: case UNCOLLECTABLE:
! 481: result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
! 482: break;
! 483: # ifdef ATOMIC_UNCOLLECTABLE
! 484: case AUNCOLLECTABLE:
! 485: result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
! 486: break;
! 487: # endif
! 488: default:
! 489: GC_err_printf0("GC_debug_realloc: encountered bad kind\n");
! 490: ABORT("bad kind");
! 491: }
! 492: clobbered = GC_check_annotated_obj((oh *)base);
! 493: if (clobbered != 0) {
! 494: GC_err_printf0("GC_debug_realloc: found smashed object at ");
! 495: GC_print_smashed_obj(p, clobbered);
! 496: }
! 497: old_sz = ((oh *)base) -> oh_sz;
! 498: if (old_sz < copy_sz) copy_sz = old_sz;
! 499: if (result == 0) return(0);
! 500: BCOPY(p, result, copy_sz);
! 501: GC_debug_free(p);
! 502: return(result);
! 503: }
! 504:
! 505: /* Check all marked objects in the given block for validity */
! 506: /*ARGSUSED*/
! 507: void GC_check_heap_block(hbp, dummy)
! 508: register struct hblk *hbp; /* ptr to current heap block */
! 509: word dummy;
! 510: {
! 511: register struct hblkhdr * hhdr = HDR(hbp);
! 512: register word sz = hhdr -> hb_sz;
! 513: register int word_no;
! 514: register word *p, *plim;
! 515:
! 516: p = (word *)(hbp->hb_body);
! 517: word_no = HDR_WORDS;
! 518: if (sz > MAXOBJSZ) {
! 519: plim = p;
! 520: } else {
! 521: plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz));
! 522: }
! 523: /* go through all words in block */
! 524: while( p <= plim ) {
! 525: if( mark_bit_from_hdr(hhdr, word_no)
! 526: && GC_has_debug_info((ptr_t)p)) {
! 527: ptr_t clobbered = GC_check_annotated_obj((oh *)p);
! 528:
! 529: if (clobbered != 0) {
! 530: GC_err_printf0(
! 531: "GC_check_heap_block: found smashed object at ");
! 532: GC_print_smashed_obj((ptr_t)p, clobbered);
! 533: }
! 534: }
! 535: word_no += sz;
! 536: p += sz;
! 537: }
! 538: }
! 539:
! 540:
! 541: /* This assumes that all accessible objects are marked, and that */
! 542: /* I hold the allocation lock. Normally called by collector. */
! 543: void GC_check_heap_proc()
! 544: {
! 545: # ifndef SMALL_CONFIG
! 546: if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
! 547: ABORT("Alignment problem: object header has inappropriate size\n");
! 548: }
! 549: # endif
! 550: GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
! 551: }
! 552:
! 553: struct closure {
! 554: GC_finalization_proc cl_fn;
! 555: GC_PTR cl_data;
! 556: };
! 557:
! 558: # ifdef __STDC__
! 559: void * GC_make_closure(GC_finalization_proc fn, void * data)
! 560: # else
! 561: GC_PTR GC_make_closure(fn, data)
! 562: GC_finalization_proc fn;
! 563: GC_PTR data;
! 564: # endif
! 565: {
! 566: struct closure * result =
! 567: (struct closure *) GC_malloc(sizeof (struct closure));
! 568:
! 569: result -> cl_fn = fn;
! 570: result -> cl_data = data;
! 571: return((GC_PTR)result);
! 572: }
! 573:
! 574: # ifdef __STDC__
! 575: void GC_debug_invoke_finalizer(void * obj, void * data)
! 576: # else
! 577: void GC_debug_invoke_finalizer(obj, data)
! 578: char * obj;
! 579: char * data;
! 580: # endif
! 581: {
! 582: register struct closure * cl = (struct closure *) data;
! 583:
! 584: (*(cl -> cl_fn))((GC_PTR)((char *)obj + sizeof(oh)), cl -> cl_data);
! 585: }
! 586:
! 587:
! 588: # ifdef __STDC__
! 589: void GC_debug_register_finalizer(GC_PTR obj, GC_finalization_proc fn,
! 590: GC_PTR cd, GC_finalization_proc *ofn,
! 591: GC_PTR *ocd)
! 592: # else
! 593: void GC_debug_register_finalizer(obj, fn, cd, ofn, ocd)
! 594: GC_PTR obj;
! 595: GC_finalization_proc fn;
! 596: GC_PTR cd;
! 597: GC_finalization_proc *ofn;
! 598: GC_PTR *ocd;
! 599: # endif
! 600: {
! 601: ptr_t base = GC_base(obj);
! 602: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 603: GC_err_printf1(
! 604: "GC_register_finalizer called with non-base-pointer 0x%lx\n",
! 605: obj);
! 606: }
! 607: GC_register_finalizer(base, GC_debug_invoke_finalizer,
! 608: GC_make_closure(fn,cd), ofn, ocd);
! 609: }
! 610:
! 611: # ifdef __STDC__
! 612: void GC_debug_register_finalizer_no_order
! 613: (GC_PTR obj, GC_finalization_proc fn,
! 614: GC_PTR cd, GC_finalization_proc *ofn,
! 615: GC_PTR *ocd)
! 616: # else
! 617: void GC_debug_register_finalizer_no_order
! 618: (obj, fn, cd, ofn, ocd)
! 619: GC_PTR obj;
! 620: GC_finalization_proc fn;
! 621: GC_PTR cd;
! 622: GC_finalization_proc *ofn;
! 623: GC_PTR *ocd;
! 624: # endif
! 625: {
! 626: ptr_t base = GC_base(obj);
! 627: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 628: GC_err_printf1(
! 629: "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
! 630: obj);
! 631: }
! 632: GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
! 633: GC_make_closure(fn,cd), ofn, ocd);
! 634: }
! 635:
! 636: # ifdef __STDC__
! 637: void GC_debug_register_finalizer_ignore_self
! 638: (GC_PTR obj, GC_finalization_proc fn,
! 639: GC_PTR cd, GC_finalization_proc *ofn,
! 640: GC_PTR *ocd)
! 641: # else
! 642: void GC_debug_register_finalizer_ignore_self
! 643: (obj, fn, cd, ofn, ocd)
! 644: GC_PTR obj;
! 645: GC_finalization_proc fn;
! 646: GC_PTR cd;
! 647: GC_finalization_proc *ofn;
! 648: GC_PTR *ocd;
! 649: # endif
! 650: {
! 651: ptr_t base = GC_base(obj);
! 652: if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
! 653: GC_err_printf1(
! 654: "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
! 655: obj);
! 656: }
! 657: GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
! 658: GC_make_closure(fn,cd), ofn, ocd);
! 659: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>