Annotation of OpenXM_contrib/gc/ptr_chck.c, Revision 1.1
1.1 ! maekawa 1: /*
! 2: * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
! 3: *
! 4: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
! 5: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
! 6: *
! 7: * Permission is hereby granted to use or copy this program
! 8: * for any purpose, provided the above notices are retained on all copies.
! 9: * Permission to modify the code and to distribute modified code is granted,
! 10: * provided the above notices are retained, and a notice that the code was
! 11: * modified is included with the above copyright notice.
! 12: */
! 13: /* Boehm, September 19, 1995 1:26 pm PDT */
! 14:
! 15: #include "gc_priv.h"
! 16: #include "gc_mark.h"
! 17:
! 18: #ifdef __STDC__
! 19: void GC_default_same_obj_print_proc(GC_PTR p, GC_PTR q)
! 20: #else
! 21: void GC_default_same_obj_print_proc (p, q)
! 22: GC_PTR p, q;
! 23: #endif
! 24: {
! 25: GC_err_printf2("0x%lx and 0x%lx are not in the same object\n",
! 26: (unsigned long)p, (unsigned long)q);
! 27: ABORT("GC_same_obj test failed");
! 28: }
! 29:
! 30: void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
! 31: = GC_default_same_obj_print_proc;
! 32:
! 33: /* Check that p and q point to the same object. Call */
! 34: /* *GC_same_obj_print_proc if they don't. */
! 35: /* Returns the first argument. (Return value may be hard */
! 36: /* to use,due to typing issues. But if we had a suitable */
! 37: /* preprocessor ...) */
! 38: /* Succeeds if neither p nor q points to the heap. */
! 39: /* We assume this is performance critical. (It shouldn't */
! 40: /* be called by production code, but this can easily make */
! 41: /* debugging intolerably slow.) */
! 42: #ifdef __STDC__
! 43: GC_PTR GC_same_obj(register void *p, register void *q)
! 44: #else
! 45: GC_PTR GC_same_obj(p, q)
! 46: register char *p, *q;
! 47: #endif
! 48: {
! 49: register struct hblk *h;
! 50: register hdr *hhdr;
! 51: register ptr_t base, limit;
! 52: register word sz;
! 53:
! 54: if (!GC_is_initialized) GC_init();
! 55: hhdr = HDR((word)p);
! 56: if (hhdr == 0) {
! 57: if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
! 58: && HDR((word)q) != 0) {
! 59: goto fail;
! 60: }
! 61: return(p);
! 62: }
! 63: /* If it's a pointer to the middle of a large object, move it */
! 64: /* to the beginning. */
! 65: if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
! 66: h = HBLKPTR(p) - (word)hhdr;
! 67: hhdr = HDR(h);
! 68: while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
! 69: h = FORWARDED_ADDR(h, hhdr);
! 70: hhdr = HDR(h);
! 71: }
! 72: limit = (ptr_t)((word *)h + HDR_WORDS + hhdr -> hb_sz);
! 73: if ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
! 74: goto fail;
! 75: }
! 76: return(p);
! 77: }
! 78: sz = WORDS_TO_BYTES(hhdr -> hb_sz);
! 79: if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
! 80: base = (ptr_t)HBLKPTR(p);
! 81: limit = base + sz;
! 82: if ((ptr_t)p >= limit) {
! 83: goto fail;
! 84: }
! 85: } else {
! 86: # ifdef ALL_INTERIOR_POINTERS
! 87: register map_entry_type map_entry;
! 88: register int pdispl;
! 89:
! 90: pdispl = HBLKDISPL(p);
! 91: map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
! 92: if (map_entry == OBJ_INVALID) {
! 93: goto fail;
! 94: } else {
! 95: base = (char *)((word)p & ~(WORDS_TO_BYTES(1) - 1));
! 96: base -= WORDS_TO_BYTES(map_entry);
! 97: }
! 98: # else
! 99: register int offset = HBLKDISPL(p) - HDR_BYTES;
! 100: register word correction = offset % sz;
! 101:
! 102: if (HBLKPTR(p) != HBLKPTR(q)) {
! 103: /* The following computation otherwise fails in this case */
! 104: goto fail;
! 105: }
! 106: base = (ptr_t)p - correction;
! 107: # endif
! 108: limit = base + sz;
! 109: }
! 110: /* [base, limit) delimits the object containing p, if any. */
! 111: /* If p is not inside a valid object, then either q is */
! 112: /* also outside any valid object, or it is outside */
! 113: /* [base, limit). */
! 114: if ((ptr_t)q >= limit || (ptr_t)q < base) {
! 115: goto fail;
! 116: }
! 117: return(p);
! 118: fail:
! 119: (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
! 120: return(p);
! 121: }
! 122:
! 123: #ifdef __STDC__
! 124: void GC_default_is_valid_displacement_print_proc (GC_PTR p)
! 125: #else
! 126: void GC_default_is_valid_displacement_print_proc (p)
! 127: GC_PTR p;
! 128: #endif
! 129: {
! 130: GC_err_printf1("0x%lx does not point to valid object displacement\n",
! 131: (unsigned long)p);
! 132: ABORT("GC_is_valid_displacement test failed");
! 133: }
! 134:
! 135: void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) =
! 136: GC_default_is_valid_displacement_print_proc;
! 137:
! 138: /* Check that if p is a pointer to a heap page, then it points to */
! 139: /* a valid displacement within a heap object. */
! 140: /* Uninteresting with ALL_INTERIOR_POINTERS. */
! 141: /* Always returns its argument. */
! 142: /* Note that we don't lock, since nothing relevant about the header */
! 143: /* should change while we have a valid object pointer to the block. */
! 144: #ifdef __STDC__
! 145: void * GC_is_valid_displacement(void *p)
! 146: #else
! 147: char *GC_is_valid_displacement(p)
! 148: char *p;
! 149: #endif
! 150: {
! 151: register hdr *hhdr;
! 152: register word pdispl;
! 153: register struct hblk *h;
! 154: register map_entry_type map_entry;
! 155: register word sz;
! 156:
! 157: if (!GC_is_initialized) GC_init();
! 158: hhdr = HDR((word)p);
! 159: if (hhdr == 0) return(p);
! 160: h = HBLKPTR(p);
! 161: # ifdef ALL_INTERIOR_POINTERS
! 162: while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
! 163: h = FORWARDED_ADDR(h, hhdr);
! 164: hhdr = HDR(h);
! 165: }
! 166: # endif
! 167: if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
! 168: goto fail;
! 169: }
! 170: sz = WORDS_TO_BYTES(hhdr -> hb_sz);
! 171: pdispl = HBLKDISPL(p);
! 172: map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
! 173: if (map_entry == OBJ_INVALID
! 174: || sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) {
! 175: goto fail;
! 176: }
! 177: return(p);
! 178: fail:
! 179: (*GC_is_valid_displacement_print_proc)((ptr_t)p);
! 180: return(p);
! 181: }
! 182:
! 183: #ifdef __STDC__
! 184: void GC_default_is_visible_print_proc(GC_PTR p)
! 185: #else
! 186: void GC_default_is_visible_print_proc(p)
! 187: GC_PTR p;
! 188: #endif
! 189: {
! 190: GC_err_printf1("0x%lx is not a GC visible pointer location\n",
! 191: (unsigned long)p);
! 192: ABORT("GC_is_visible test failed");
! 193: }
! 194:
! 195: void (*GC_is_visible_print_proc) GC_PROTO((GC_PTR p)) =
! 196: GC_default_is_visible_print_proc;
! 197:
! 198: /* Could p be a stack address? */
! 199: GC_bool GC_on_stack(p)
! 200: ptr_t p;
! 201: {
! 202: # ifdef THREADS
! 203: return(TRUE);
! 204: # else
! 205: int dummy;
! 206: # ifdef STACK_GROWS_DOWN
! 207: if ((ptr_t)p >= (ptr_t)(&dummy) && (ptr_t)p < GC_stackbottom ) {
! 208: return(TRUE);
! 209: }
! 210: # else
! 211: if ((ptr_t)p <= (ptr_t)(&dummy) && (ptr_t)p > GC_stackbottom ) {
! 212: return(TRUE);
! 213: }
! 214: # endif
! 215: return(FALSE);
! 216: # endif
! 217: }
! 218:
! 219: /* Check that p is visible */
! 220: /* to the collector as a possibly pointer containing location. */
! 221: /* If it isn't invoke *GC_is_visible_print_proc. */
! 222: /* Returns the argument in all cases. May erroneously succeed */
! 223: /* in hard cases. (This is intended for debugging use with */
! 224: /* untyped allocations. The idea is that it should be possible, though */
! 225: /* slow, to add such a call to all indirect pointer stores.) */
! 226: /* Currently useless for multithreaded worlds. */
! 227: #ifdef __STDC__
! 228: void * GC_is_visible(void *p)
! 229: #else
! 230: char *GC_is_visible(p)
! 231: char *p;
! 232: #endif
! 233: {
! 234: register hdr *hhdr;
! 235:
! 236: if ((word)p & (ALIGNMENT - 1)) goto fail;
! 237: if (!GC_is_initialized) GC_init();
! 238: # ifdef THREADS
! 239: hhdr = HDR((word)p);
! 240: if (hhdr != 0 && GC_base(p) == 0) {
! 241: goto fail;
! 242: } else {
! 243: /* May be inside thread stack. We can't do much. */
! 244: return(p);
! 245: }
! 246: # else
! 247: /* Check stack first: */
! 248: if (GC_on_stack(p)) return(p);
! 249: hhdr = HDR((word)p);
! 250: if (hhdr == 0) {
! 251: GC_bool result;
! 252:
! 253: if (GC_is_static_root(p)) return(p);
! 254: /* Else do it again correctly: */
! 255: # if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
! 256: && !defined(SRC_M3)
! 257: DISABLE_SIGNALS();
! 258: GC_register_dynamic_libraries();
! 259: result = GC_is_static_root(p);
! 260: ENABLE_SIGNALS();
! 261: if (result) return(p);
! 262: # endif
! 263: goto fail;
! 264: } else {
! 265: /* p points to the heap. */
! 266: word descr;
! 267: ptr_t base = GC_base(p); /* Should be manually inlined? */
! 268:
! 269: if (base == 0) goto fail;
! 270: if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
! 271: descr = hhdr -> hb_descr;
! 272: retry:
! 273: switch(descr & DS_TAGS) {
! 274: case DS_LENGTH:
! 275: if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
! 276: break;
! 277: case DS_BITMAP:
! 278: if ((ptr_t)p - (ptr_t)base
! 279: >= WORDS_TO_BYTES(BITMAP_BITS)
! 280: || ((word)p & (sizeof(word) - 1))) goto fail;
! 281: if (!((1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
! 282: & descr)) goto fail;
! 283: break;
! 284: case DS_PROC:
! 285: /* We could try to decipher this partially. */
! 286: /* For now we just punt. */
! 287: break;
! 288: case DS_PER_OBJECT:
! 289: descr = *(word *)((ptr_t)base + (descr & ~DS_TAGS));
! 290: goto retry;
! 291: }
! 292: return(p);
! 293: }
! 294: # endif
! 295: fail:
! 296: (*GC_is_visible_print_proc)((ptr_t)p);
! 297: return(p);
! 298: }
! 299:
! 300:
! 301: GC_PTR GC_pre_incr (p, how_much)
! 302: GC_PTR *p;
! 303: size_t how_much;
! 304: {
! 305: GC_PTR initial = *p;
! 306: GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
! 307:
! 308: # ifndef ALL_INTERIOR_POINTERS
! 309: (void) GC_is_valid_displacement(result);
! 310: # endif
! 311: return (*p = result);
! 312: }
! 313:
! 314: GC_PTR GC_post_incr (p, how_much)
! 315: GC_PTR *p;
! 316: size_t how_much;
! 317: {
! 318: GC_PTR initial = *p;
! 319: GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
! 320:
! 321: # ifndef ALL_INTERIOR_POINTERS
! 322: (void) GC_is_valid_displacement(result);
! 323: # endif
! 324: *p = result;
! 325: return(initial);
! 326: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>