Annotation of OpenXM_contrib2/asir2000/gc/malloc.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 7, 1996 4:32 pm PST */
! 15:
! 16: #include <stdio.h>
! 17: #include "gc_priv.h"
! 18:
! 19: extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
! 20: void GC_extend_size_map(); /* in misc.c. */
! 21:
! 22: /* Allocate reclaim list for kind: */
! 23: /* Return TRUE on success */
! 24: GC_bool GC_alloc_reclaim_list(kind)
! 25: register struct obj_kind * kind;
! 26: {
! 27: struct hblk ** result = (struct hblk **)
! 28: GC_scratch_alloc((MAXOBJSZ+1) * sizeof(struct hblk *));
! 29: if (result == 0) return(FALSE);
! 30: BZERO(result, (MAXOBJSZ+1)*sizeof(struct hblk *));
! 31: kind -> ok_reclaim_list = result;
! 32: return(TRUE);
! 33: }
! 34:
! 35: /* allocate lb bytes for an object of kind. */
! 36: /* Should not be used to directly to allocate */
! 37: /* objects such as STUBBORN objects that */
! 38: /* require special handling on allocation. */
! 39: /* First a version that assumes we already */
! 40: /* hold lock: */
! 41: ptr_t GC_generic_malloc_inner(lb, k)
! 42: register word lb;
! 43: register int k;
! 44: {
! 45: register word lw;
! 46: register ptr_t op;
! 47: register ptr_t *opp;
! 48:
! 49: if( SMALL_OBJ(lb) ) {
! 50: register struct obj_kind * kind = GC_obj_kinds + k;
! 51: # ifdef MERGE_SIZES
! 52: lw = GC_size_map[lb];
! 53: # else
! 54: lw = ALIGNED_WORDS(lb);
! 55: if (lw == 0) lw = 1;
! 56: # endif
! 57: opp = &(kind -> ok_freelist[lw]);
! 58: if( (op = *opp) == 0 ) {
! 59: # ifdef MERGE_SIZES
! 60: if (GC_size_map[lb] == 0) {
! 61: if (!GC_is_initialized) GC_init_inner();
! 62: if (GC_size_map[lb] == 0) GC_extend_size_map(lb);
! 63: return(GC_generic_malloc_inner(lb, k));
! 64: }
! 65: # else
! 66: if (!GC_is_initialized) {
! 67: GC_init_inner();
! 68: return(GC_generic_malloc_inner(lb, k));
! 69: }
! 70: # endif
! 71: if (kind -> ok_reclaim_list == 0) {
! 72: if (!GC_alloc_reclaim_list(kind)) goto out;
! 73: }
! 74: op = GC_allocobj(lw, k);
! 75: if (op == 0) goto out;
! 76: }
! 77: /* Here everything is in a consistent state. */
! 78: /* We assume the following assignment is */
! 79: /* atomic. If we get aborted */
! 80: /* after the assignment, we lose an object, */
! 81: /* but that's benign. */
! 82: /* Volatile declarations may need to be added */
! 83: /* to prevent the compiler from breaking things.*/
! 84: *opp = obj_link(op);
! 85: obj_link(op) = 0;
! 86: } else {
! 87: register struct hblk * h;
! 88: register word n_blocks = divHBLKSZ(ADD_SLOP(lb)
! 89: + HDR_BYTES + HBLKSIZE-1);
! 90:
! 91: if (!GC_is_initialized) GC_init_inner();
! 92: /* Do our share of marking work */
! 93: if(GC_incremental && !GC_dont_gc)
! 94: GC_collect_a_little_inner((int)n_blocks);
! 95: lw = ROUNDED_UP_WORDS(lb);
! 96: h = GC_allochblk(lw, k, 0);
! 97: # ifdef USE_MUNMAP
! 98: if (0 == h) {
! 99: GC_merge_unmapped();
! 100: h = GC_allochblk(lw, k, 0);
! 101: }
! 102: # endif
! 103: while (0 == h && GC_collect_or_expand(n_blocks, FALSE)) {
! 104: h = GC_allochblk(lw, k, 0);
! 105: }
! 106: if (h == 0) {
! 107: op = 0;
! 108: } else {
! 109: op = (ptr_t) (h -> hb_body);
! 110: GC_words_wasted += BYTES_TO_WORDS(n_blocks * HBLKSIZE) - lw;
! 111: }
! 112: }
! 113: GC_words_allocd += lw;
! 114:
! 115: out:
! 116: return((ptr_t)op);
! 117: }
! 118:
! 119: ptr_t GC_generic_malloc(lb, k)
! 120: register word lb;
! 121: register int k;
! 122: {
! 123: ptr_t result;
! 124: DCL_LOCK_STATE;
! 125:
! 126: GC_INVOKE_FINALIZERS();
! 127: DISABLE_SIGNALS();
! 128: LOCK();
! 129: result = GC_generic_malloc_inner(lb, k);
! 130: UNLOCK();
! 131: ENABLE_SIGNALS();
! 132: if (0 == result) {
! 133: return((*GC_oom_fn)(lb));
! 134: } else {
! 135: return(result);
! 136: }
! 137: }
! 138:
! 139:
! 140: #define GENERAL_MALLOC(lb,k) \
! 141: (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
! 142: /* We make the GC_clear_stack_call a tail call, hoping to get more of */
! 143: /* the stack. */
! 144:
! 145: /* Allocate lb bytes of atomic (pointerfree) data */
! 146: # ifdef __STDC__
! 147: GC_PTR GC_malloc_atomic(size_t lb)
! 148: # else
! 149: GC_PTR GC_malloc_atomic(lb)
! 150: size_t lb;
! 151: # endif
! 152: {
! 153: register ptr_t op;
! 154: register ptr_t * opp;
! 155: register word lw;
! 156: DCL_LOCK_STATE;
! 157:
! 158: if( SMALL_OBJ(lb) ) {
! 159: # ifdef MERGE_SIZES
! 160: lw = GC_size_map[lb];
! 161: # else
! 162: lw = ALIGNED_WORDS(lb);
! 163: # endif
! 164: opp = &(GC_aobjfreelist[lw]);
! 165: FASTLOCK();
! 166: if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
! 167: FASTUNLOCK();
! 168: return(GENERAL_MALLOC((word)lb, PTRFREE));
! 169: }
! 170: /* See above comment on signals. */
! 171: *opp = obj_link(op);
! 172: GC_words_allocd += lw;
! 173: FASTUNLOCK();
! 174: return((GC_PTR) op);
! 175: } else {
! 176: return(GENERAL_MALLOC((word)lb, PTRFREE));
! 177: }
! 178: }
! 179:
! 180: /* Allocate lb bytes of composite (pointerful) data */
! 181: # ifdef __STDC__
! 182: GC_PTR GC_malloc(size_t lb)
! 183: # else
! 184: GC_PTR GC_malloc(lb)
! 185: size_t lb;
! 186: # endif
! 187: {
! 188: register ptr_t op;
! 189: register ptr_t *opp;
! 190: register word lw;
! 191: DCL_LOCK_STATE;
! 192:
! 193: if( SMALL_OBJ(lb) ) {
! 194: # ifdef MERGE_SIZES
! 195: lw = GC_size_map[lb];
! 196: # else
! 197: lw = ALIGNED_WORDS(lb);
! 198: # endif
! 199: opp = &(GC_objfreelist[lw]);
! 200: FASTLOCK();
! 201: if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
! 202: FASTUNLOCK();
! 203: return(GENERAL_MALLOC((word)lb, NORMAL));
! 204: }
! 205: /* See above comment on signals. */
! 206: *opp = obj_link(op);
! 207: obj_link(op) = 0;
! 208: GC_words_allocd += lw;
! 209: FASTUNLOCK();
! 210: return((GC_PTR) op);
! 211: } else {
! 212: return(GENERAL_MALLOC((word)lb, NORMAL));
! 213: }
! 214: }
! 215:
! 216: # ifdef REDIRECT_MALLOC
! 217: # ifdef __STDC__
! 218: GC_PTR malloc(size_t lb)
! 219: # else
! 220: GC_PTR malloc(lb)
! 221: size_t lb;
! 222: # endif
! 223: {
! 224: /* It might help to manually inline the GC_malloc call here. */
! 225: /* But any decent compiler should reduce the extra procedure call */
! 226: /* to at most a jump instruction in this case. */
! 227: # if defined(I386) && defined(SOLARIS_THREADS)
! 228: /*
! 229: * Thread initialisation can call malloc before
! 230: * we're ready for it.
! 231: * It's not clear that this is enough to help matters.
! 232: * The thread implementation may well call malloc at other
! 233: * inopportune times.
! 234: */
! 235: if (!GC_is_initialized) return sbrk(lb);
! 236: # endif /* I386 && SOLARIS_THREADS */
! 237: return(REDIRECT_MALLOC(lb));
! 238: }
! 239:
! 240: # ifdef __STDC__
! 241: GC_PTR calloc(size_t n, size_t lb)
! 242: # else
! 243: GC_PTR calloc(n, lb)
! 244: size_t n, lb;
! 245: # endif
! 246: {
! 247: return(REDIRECT_MALLOC(n*lb));
! 248: }
! 249: # endif /* REDIRECT_MALLOC */
! 250:
! 251: GC_PTR GC_generic_or_special_malloc(lb,knd)
! 252: word lb;
! 253: int knd;
! 254: {
! 255: switch(knd) {
! 256: # ifdef STUBBORN_ALLOC
! 257: case STUBBORN:
! 258: return(GC_malloc_stubborn((size_t)lb));
! 259: # endif
! 260: case PTRFREE:
! 261: return(GC_malloc_atomic((size_t)lb));
! 262: case NORMAL:
! 263: return(GC_malloc((size_t)lb));
! 264: case UNCOLLECTABLE:
! 265: return(GC_malloc_uncollectable((size_t)lb));
! 266: # ifdef ATOMIC_UNCOLLECTABLE
! 267: case AUNCOLLECTABLE:
! 268: return(GC_malloc_atomic_uncollectable((size_t)lb));
! 269: # endif /* ATOMIC_UNCOLLECTABLE */
! 270: default:
! 271: return(GC_generic_malloc(lb,knd));
! 272: }
! 273: }
! 274:
! 275:
! 276: /* Change the size of the block pointed to by p to contain at least */
! 277: /* lb bytes. The object may be (and quite likely will be) moved. */
! 278: /* The kind (e.g. atomic) is the same as that of the old. */
! 279: /* Shrinking of large blocks is not implemented well. */
! 280: # ifdef __STDC__
! 281: GC_PTR GC_realloc(GC_PTR p, size_t lb)
! 282: # else
! 283: GC_PTR GC_realloc(p,lb)
! 284: GC_PTR p;
! 285: size_t lb;
! 286: # endif
! 287: {
! 288: register struct hblk * h;
! 289: register hdr * hhdr;
! 290: register word sz; /* Current size in bytes */
! 291: register word orig_sz; /* Original sz in bytes */
! 292: int obj_kind;
! 293:
! 294: if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */
! 295: h = HBLKPTR(p);
! 296: hhdr = HDR(h);
! 297: sz = hhdr -> hb_sz;
! 298: obj_kind = hhdr -> hb_obj_kind;
! 299: sz = WORDS_TO_BYTES(sz);
! 300: orig_sz = sz;
! 301:
! 302: if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
! 303: /* Round it up to the next whole heap block */
! 304: register word descr;
! 305:
! 306: sz = (sz+HDR_BYTES+HBLKSIZE-1)
! 307: & (~HBLKMASK);
! 308: sz -= HDR_BYTES;
! 309: hhdr -> hb_sz = BYTES_TO_WORDS(sz);
! 310: descr = GC_obj_kinds[obj_kind].ok_descriptor;
! 311: if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz;
! 312: hhdr -> hb_descr = descr;
! 313: if (IS_UNCOLLECTABLE(obj_kind)) GC_non_gc_bytes += (sz - orig_sz);
! 314: /* Extra area is already cleared by allochblk. */
! 315: }
! 316: if (ADD_SLOP(lb) <= sz) {
! 317: if (lb >= (sz >> 1)) {
! 318: # ifdef STUBBORN_ALLOC
! 319: if (obj_kind == STUBBORN) GC_change_stubborn(p);
! 320: # endif
! 321: if (orig_sz > lb) {
! 322: /* Clear unneeded part of object to avoid bogus pointer */
! 323: /* tracing. */
! 324: /* Safe for stubborn objects. */
! 325: BZERO(((ptr_t)p) + lb, orig_sz - lb);
! 326: }
! 327: return(p);
! 328: } else {
! 329: /* shrink */
! 330: GC_PTR result =
! 331: GC_generic_or_special_malloc((word)lb, obj_kind);
! 332:
! 333: if (result == 0) return(0);
! 334: /* Could also return original object. But this */
! 335: /* gives the client warning of imminent disaster. */
! 336: BCOPY(p, result, lb);
! 337: # ifndef IGNORE_FREE
! 338: GC_free(p);
! 339: # endif
! 340: return(result);
! 341: }
! 342: } else {
! 343: /* grow */
! 344: GC_PTR result =
! 345: GC_generic_or_special_malloc((word)lb, obj_kind);
! 346:
! 347: if (result == 0) return(0);
! 348: BCOPY(p, result, sz);
! 349: # ifndef IGNORE_FREE
! 350: GC_free(p);
! 351: # endif
! 352: return(result);
! 353: }
! 354: }
! 355:
! 356: # ifdef REDIRECT_MALLOC
! 357: # ifdef __STDC__
! 358: GC_PTR realloc(GC_PTR p, size_t lb)
! 359: # else
! 360: GC_PTR realloc(p,lb)
! 361: GC_PTR p;
! 362: size_t lb;
! 363: # endif
! 364: {
! 365: return(GC_realloc(p, lb));
! 366: }
! 367: # endif /* REDIRECT_MALLOC */
! 368:
! 369: /* Explicitly deallocate an object p. */
! 370: # ifdef __STDC__
! 371: void GC_free(GC_PTR p)
! 372: # else
! 373: void GC_free(p)
! 374: GC_PTR p;
! 375: # endif
! 376: {
! 377: register struct hblk *h;
! 378: register hdr *hhdr;
! 379: register signed_word sz;
! 380: register ptr_t * flh;
! 381: register int knd;
! 382: register struct obj_kind * ok;
! 383: DCL_LOCK_STATE;
! 384:
! 385: if (p == 0) return;
! 386: /* Required by ANSI. It's not my fault ... */
! 387: h = HBLKPTR(p);
! 388: hhdr = HDR(h);
! 389: # if defined(REDIRECT_MALLOC) && \
! 390: (defined(SOLARIS_THREADS) || defined(LINUX_THREADS))
! 391: /* We have to redirect malloc calls during initialization. */
! 392: /* Don't try to deallocate that memory. */
! 393: if (0 == hhdr) return;
! 394: # endif
! 395: knd = hhdr -> hb_obj_kind;
! 396: sz = hhdr -> hb_sz;
! 397: ok = &GC_obj_kinds[knd];
! 398: if (sz <= MAXOBJSZ) {
! 399: # ifdef THREADS
! 400: DISABLE_SIGNALS();
! 401: LOCK();
! 402: # endif
! 403: GC_mem_freed += sz;
! 404: /* A signal here can make GC_mem_freed and GC_non_gc_bytes */
! 405: /* inconsistent. We claim this is benign. */
! 406: if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
! 407: /* Its unnecessary to clear the mark bit. If the */
! 408: /* object is reallocated, it doesn't matter. O.w. the */
! 409: /* collector will do it, since it's on a free list. */
! 410: if (ok -> ok_init) {
! 411: BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
! 412: }
! 413: flh = &(ok -> ok_freelist[sz]);
! 414: obj_link(p) = *flh;
! 415: *flh = (ptr_t)p;
! 416: # ifdef THREADS
! 417: UNLOCK();
! 418: ENABLE_SIGNALS();
! 419: # endif
! 420: } else {
! 421: DISABLE_SIGNALS();
! 422: LOCK();
! 423: GC_mem_freed += sz;
! 424: if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
! 425: GC_freehblk(h);
! 426: UNLOCK();
! 427: ENABLE_SIGNALS();
! 428: }
! 429: }
! 430:
! 431: # ifdef REDIRECT_MALLOC
! 432: # ifdef __STDC__
! 433: void free(GC_PTR p)
! 434: # else
! 435: void free(p)
! 436: GC_PTR p;
! 437: # endif
! 438: {
! 439: # ifndef IGNORE_FREE
! 440: GC_free(p);
! 441: # endif
! 442: }
! 443: # endif /* REDIRECT_MALLOC */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>