[BACK]Return to malloc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

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>