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

Annotation of OpenXM_contrib/gc/malloc.c, Revision 1.1

1.1     ! maekawa     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:        while ((h = GC_allochblk(lw, k, 0)) == 0
        !            97:                && GC_collect_or_expand(n_blocks, FALSE));
        !            98:        if (h == 0) {
        !            99:            op = 0;
        !           100:        } else {
        !           101:            op = (ptr_t) (h -> hb_body);
        !           102:            GC_words_wasted += BYTES_TO_WORDS(n_blocks * HBLKSIZE) - lw;
        !           103:        }
        !           104:     }
        !           105:     GC_words_allocd += lw;
        !           106:
        !           107: out:
        !           108:     return((ptr_t)op);
        !           109: }
        !           110:
        !           111: ptr_t GC_generic_malloc(lb, k)
        !           112: register word lb;
        !           113: register int k;
        !           114: {
        !           115:     ptr_t result;
        !           116:     DCL_LOCK_STATE;
        !           117:
        !           118:     GC_INVOKE_FINALIZERS();
        !           119:     DISABLE_SIGNALS();
        !           120:     LOCK();
        !           121:     result = GC_generic_malloc_inner(lb, k);
        !           122:     UNLOCK();
        !           123:     ENABLE_SIGNALS();
        !           124:     if (0 == result) {
        !           125:         return((*GC_oom_fn)(lb));
        !           126:     } else {
        !           127:         return(result);
        !           128:     }
        !           129: }
        !           130:
        !           131:
        !           132: #define GENERAL_MALLOC(lb,k) \
        !           133:     (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
        !           134: /* We make the GC_clear_stack_call a tail call, hoping to get more of  */
        !           135: /* the stack.                                                          */
        !           136:
        !           137: /* Allocate lb bytes of atomic (pointerfree) data */
        !           138: # ifdef __STDC__
        !           139:     GC_PTR GC_malloc_atomic(size_t lb)
        !           140: # else
        !           141:     GC_PTR GC_malloc_atomic(lb)
        !           142:     size_t lb;
        !           143: # endif
        !           144: {
        !           145: register ptr_t op;
        !           146: register ptr_t * opp;
        !           147: register word lw;
        !           148: DCL_LOCK_STATE;
        !           149:
        !           150:     if( SMALL_OBJ(lb) ) {
        !           151: #       ifdef MERGE_SIZES
        !           152:          lw = GC_size_map[lb];
        !           153: #      else
        !           154:          lw = ALIGNED_WORDS(lb);
        !           155: #       endif
        !           156:        opp = &(GC_aobjfreelist[lw]);
        !           157:        FASTLOCK();
        !           158:         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
        !           159:             FASTUNLOCK();
        !           160:             return(GENERAL_MALLOC((word)lb, PTRFREE));
        !           161:         }
        !           162:         /* See above comment on signals.       */
        !           163:         *opp = obj_link(op);
        !           164:         GC_words_allocd += lw;
        !           165:         FASTUNLOCK();
        !           166:         return((GC_PTR) op);
        !           167:    } else {
        !           168:        return(GENERAL_MALLOC((word)lb, PTRFREE));
        !           169:    }
        !           170: }
        !           171:
        !           172: /* Allocate lb bytes of composite (pointerful) data */
        !           173: # ifdef __STDC__
        !           174:     GC_PTR GC_malloc(size_t lb)
        !           175: # else
        !           176:     GC_PTR GC_malloc(lb)
        !           177:     size_t lb;
        !           178: # endif
        !           179: {
        !           180: register ptr_t op;
        !           181: register ptr_t *opp;
        !           182: register word lw;
        !           183: DCL_LOCK_STATE;
        !           184:
        !           185:     if( SMALL_OBJ(lb) ) {
        !           186: #       ifdef MERGE_SIZES
        !           187:          lw = GC_size_map[lb];
        !           188: #      else
        !           189:          lw = ALIGNED_WORDS(lb);
        !           190: #       endif
        !           191:        opp = &(GC_objfreelist[lw]);
        !           192:        FASTLOCK();
        !           193:         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
        !           194:             FASTUNLOCK();
        !           195:             return(GENERAL_MALLOC((word)lb, NORMAL));
        !           196:         }
        !           197:         /* See above comment on signals.       */
        !           198:         *opp = obj_link(op);
        !           199:         obj_link(op) = 0;
        !           200:         GC_words_allocd += lw;
        !           201:         FASTUNLOCK();
        !           202:         return((GC_PTR) op);
        !           203:    } else {
        !           204:        return(GENERAL_MALLOC((word)lb, NORMAL));
        !           205:    }
        !           206: }
        !           207:
        !           208: # ifdef REDIRECT_MALLOC
        !           209: # ifdef __STDC__
        !           210:     GC_PTR malloc(size_t lb)
        !           211: # else
        !           212:     GC_PTR malloc(lb)
        !           213:     size_t lb;
        !           214: # endif
        !           215:   {
        !           216:     /* It might help to manually inline the GC_malloc call here.       */
        !           217:     /* But any decent compiler should reduce the extra procedure call  */
        !           218:     /* to at most a jump instruction in this case.                     */
        !           219: #   if defined(I386) && defined(SOLARIS_THREADS)
        !           220:       /*
        !           221:        * Thread initialisation can call malloc before
        !           222:        * we're ready for it.
        !           223:        * It's not clear that this is enough to help matters.
        !           224:        * The thread implementation may well call malloc at other
        !           225:        * inopportune times.
        !           226:        */
        !           227:       if (!GC_is_initialized) return sbrk(lb);
        !           228: #   endif /* I386 && SOLARIS_THREADS */
        !           229:     return(REDIRECT_MALLOC(lb));
        !           230:   }
        !           231:
        !           232: # ifdef __STDC__
        !           233:     GC_PTR calloc(size_t n, size_t lb)
        !           234: # else
        !           235:     GC_PTR calloc(n, lb)
        !           236:     size_t n, lb;
        !           237: # endif
        !           238:   {
        !           239:     return(REDIRECT_MALLOC(n*lb));
        !           240:   }
        !           241: # endif /* REDIRECT_MALLOC */
        !           242:
        !           243: GC_PTR GC_generic_or_special_malloc(lb,knd)
        !           244: word lb;
        !           245: int knd;
        !           246: {
        !           247:     switch(knd) {
        !           248: #     ifdef STUBBORN_ALLOC
        !           249:        case STUBBORN:
        !           250:            return(GC_malloc_stubborn((size_t)lb));
        !           251: #     endif
        !           252:        case PTRFREE:
        !           253:            return(GC_malloc_atomic((size_t)lb));
        !           254:        case NORMAL:
        !           255:            return(GC_malloc((size_t)lb));
        !           256:        case UNCOLLECTABLE:
        !           257:            return(GC_malloc_uncollectable((size_t)lb));
        !           258: #       ifdef ATOMIC_UNCOLLECTABLE
        !           259:          case AUNCOLLECTABLE:
        !           260:            return(GC_malloc_atomic_uncollectable((size_t)lb));
        !           261: #      endif /* ATOMIC_UNCOLLECTABLE */
        !           262:        default:
        !           263:            return(GC_generic_malloc(lb,knd));
        !           264:     }
        !           265: }
        !           266:
        !           267:
        !           268: /* Change the size of the block pointed to by p to contain at least   */
        !           269: /* lb bytes.  The object may be (and quite likely will be) moved.     */
        !           270: /* The kind (e.g. atomic) is the same as that of the old.            */
        !           271: /* Shrinking of large blocks is not implemented well.                 */
        !           272: # ifdef __STDC__
        !           273:     GC_PTR GC_realloc(GC_PTR p, size_t lb)
        !           274: # else
        !           275:     GC_PTR GC_realloc(p,lb)
        !           276:     GC_PTR p;
        !           277:     size_t lb;
        !           278: # endif
        !           279: {
        !           280: register struct hblk * h;
        !           281: register hdr * hhdr;
        !           282: register word sz;       /* Current size in bytes       */
        !           283: register word orig_sz;  /* Original sz in bytes        */
        !           284: int obj_kind;
        !           285:
        !           286:     if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */
        !           287:     h = HBLKPTR(p);
        !           288:     hhdr = HDR(h);
        !           289:     sz = hhdr -> hb_sz;
        !           290:     obj_kind = hhdr -> hb_obj_kind;
        !           291:     sz = WORDS_TO_BYTES(sz);
        !           292:     orig_sz = sz;
        !           293:
        !           294:     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
        !           295:        /* Round it up to the next whole heap block */
        !           296:          register word descr;
        !           297:
        !           298:          sz = (sz+HDR_BYTES+HBLKSIZE-1)
        !           299:                & (~HBLKMASK);
        !           300:          sz -= HDR_BYTES;
        !           301:          hhdr -> hb_sz = BYTES_TO_WORDS(sz);
        !           302:          descr = GC_obj_kinds[obj_kind].ok_descriptor;
        !           303:           if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz;
        !           304:           hhdr -> hb_descr = descr;
        !           305:          if (IS_UNCOLLECTABLE(obj_kind)) GC_non_gc_bytes += (sz - orig_sz);
        !           306:          /* Extra area is already cleared by allochblk. */
        !           307:     }
        !           308:     if (ADD_SLOP(lb) <= sz) {
        !           309:        if (lb >= (sz >> 1)) {
        !           310: #          ifdef STUBBORN_ALLOC
        !           311:                if (obj_kind == STUBBORN) GC_change_stubborn(p);
        !           312: #          endif
        !           313:            if (orig_sz > lb) {
        !           314:              /* Clear unneeded part of object to avoid bogus pointer */
        !           315:              /* tracing.                                             */
        !           316:              /* Safe for stubborn objects.                           */
        !           317:                BZERO(((ptr_t)p) + lb, orig_sz - lb);
        !           318:            }
        !           319:            return(p);
        !           320:        } else {
        !           321:            /* shrink */
        !           322:              GC_PTR result =
        !           323:                        GC_generic_or_special_malloc((word)lb, obj_kind);
        !           324:
        !           325:              if (result == 0) return(0);
        !           326:                  /* Could also return original object.  But this       */
        !           327:                  /* gives the client warning of imminent disaster.     */
        !           328:              BCOPY(p, result, lb);
        !           329: #            ifndef IGNORE_FREE
        !           330:                GC_free(p);
        !           331: #            endif
        !           332:              return(result);
        !           333:        }
        !           334:     } else {
        !           335:        /* grow */
        !           336:          GC_PTR result =
        !           337:                GC_generic_or_special_malloc((word)lb, obj_kind);
        !           338:
        !           339:          if (result == 0) return(0);
        !           340:          BCOPY(p, result, sz);
        !           341: #        ifndef IGNORE_FREE
        !           342:            GC_free(p);
        !           343: #        endif
        !           344:          return(result);
        !           345:     }
        !           346: }
        !           347:
        !           348: # ifdef REDIRECT_MALLOC
        !           349: # ifdef __STDC__
        !           350:     GC_PTR realloc(GC_PTR p, size_t lb)
        !           351: # else
        !           352:     GC_PTR realloc(p,lb)
        !           353:     GC_PTR p;
        !           354:     size_t lb;
        !           355: # endif
        !           356:   {
        !           357:     return(GC_realloc(p, lb));
        !           358:   }
        !           359: # endif /* REDIRECT_MALLOC */
        !           360:
        !           361: /* Explicitly deallocate an object p.                          */
        !           362: # ifdef __STDC__
        !           363:     void GC_free(GC_PTR p)
        !           364: # else
        !           365:     void GC_free(p)
        !           366:     GC_PTR p;
        !           367: # endif
        !           368: {
        !           369:     register struct hblk *h;
        !           370:     register hdr *hhdr;
        !           371:     register signed_word sz;
        !           372:     register ptr_t * flh;
        !           373:     register int knd;
        !           374:     register struct obj_kind * ok;
        !           375:     DCL_LOCK_STATE;
        !           376:
        !           377:     if (p == 0) return;
        !           378:        /* Required by ANSI.  It's not my fault ...     */
        !           379:     h = HBLKPTR(p);
        !           380:     hhdr = HDR(h);
        !           381: #   if defined(REDIRECT_MALLOC) && \
        !           382:        (defined(SOLARIS_THREADS) || defined(LINUX_THREADS))
        !           383:        /* We have to redirect malloc calls during initialization.      */
        !           384:        /* Don't try to deallocate that memory.                         */
        !           385:        if (0 == hhdr) return;
        !           386: #   endif
        !           387:     knd = hhdr -> hb_obj_kind;
        !           388:     sz = hhdr -> hb_sz;
        !           389:     ok = &GC_obj_kinds[knd];
        !           390:     if (sz <= MAXOBJSZ) {
        !           391: #      ifdef THREADS
        !           392:            DISABLE_SIGNALS();
        !           393:            LOCK();
        !           394: #      endif
        !           395:        GC_mem_freed += sz;
        !           396:        /* A signal here can make GC_mem_freed and GC_non_gc_bytes      */
        !           397:        /* inconsistent.  We claim this is benign.                      */
        !           398:        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        !           399:                /* Its unnecessary to clear the mark bit.  If the       */
        !           400:                /* object is reallocated, it doesn't matter.  O.w. the  */
        !           401:                /* collector will do it, since it's on a free list.     */
        !           402:        if (ok -> ok_init) {
        !           403:            BZERO((word *)p + 1, WORDS_TO_BYTES(sz-1));
        !           404:        }
        !           405:        flh = &(ok -> ok_freelist[sz]);
        !           406:        obj_link(p) = *flh;
        !           407:        *flh = (ptr_t)p;
        !           408: #      ifdef THREADS
        !           409:            UNLOCK();
        !           410:            ENABLE_SIGNALS();
        !           411: #      endif
        !           412:     } else {
        !           413:        DISABLE_SIGNALS();
        !           414:         LOCK();
        !           415:         GC_mem_freed += sz;
        !           416:        if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= WORDS_TO_BYTES(sz);
        !           417:         GC_freehblk(h);
        !           418:         UNLOCK();
        !           419:         ENABLE_SIGNALS();
        !           420:     }
        !           421: }
        !           422:
        !           423: # ifdef REDIRECT_MALLOC
        !           424: #   ifdef __STDC__
        !           425:       void free(GC_PTR p)
        !           426: #   else
        !           427:       void free(p)
        !           428:       GC_PTR p;
        !           429: #   endif
        !           430:   {
        !           431: #   ifndef IGNORE_FREE
        !           432:       GC_free(p);
        !           433: #   endif
        !           434:   }
        !           435: # endif  /* REDIRECT_MALLOC */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>