Annotation of coherent/b/kernel/coh.386/alloc.c, revision 1.1

1.1     ! root        1: /* $Header: /y/coh.386/RCS/alloc.c,v 1.4 93/04/14 10:06:13 root Exp $ */
        !             2: /* (lgl-
        !             3:  *     The information contained herein is a trade secret of Mark Williams
        !             4:  *     Company, and  is confidential information.  It is provided  under a
        !             5:  *     license agreement,  and may be  copied or disclosed  only under the
        !             6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
        !             7:  *     material without the express written authorization of Mark Williams
        !             8:  *     Company or persuant to the license agreement is unlawful.
        !             9:  *
        !            10:  *     COHERENT Version 2.3.37
        !            11:  *     Copyright (c) 1982, 1983, 1984.
        !            12:  *     An unpublished work by Mark Williams Company, Chicago.
        !            13:  *     All rights reserved.
        !            14:  -lgl) */
        !            15: /*
        !            16:  * Coherent.
        !            17:  * Storage allocator.
        !            18:  *
        !            19:  * $Log:       alloc.c,v $
        !            20:  * Revision 1.4  93/04/14  10:06:13  root
        !            21:  * r75
        !            22:  * 
        !            23:  * Revision 1.2  92/01/06  11:58:31  hal
        !            24:  * Compile with cc.mwc.
        !            25:  * 
        !            26:  * Revision 1.1        88/03/24  16:13:25      src
        !            27:  * Initial revision
        !            28:  * 
        !            29:  */
        !            30: #include <sys/coherent.h>
        !            31: #include <sys/alloc.h>
        !            32: #include <errno.h>
        !            33: #include <sys/proc.h>
        !            34: #include <sys/param.h>
        !            35: 
        !            36: #ifndef TEST   /* Do not test setarena() or alloc() or free().  */
        !            37: /*
        !            38:  * Create an arena.
        !            39:  */
        !            40: ALL *
        !            41: setarena(cp, n)
        !            42: register char *cp;
        !            43: {
        !            44:        register ALL *ap1;
        !            45:        register ALL *ap2;
        !            46: 
        !            47:        if ((char *)(ap1=align(cp)) < (char *)cp)
        !            48:                ap1++;
        !            49:        if ((ap2=align(&cp[n])-1) < ap1)
        !            50:                panic("Arena %x too small", (int) cp);
        !            51:        ap1->a_link = (char *)ap2;
        !            52:        ap2->a_link = (char *)ap1;
        !            53:        setused(ap2);
        !            54:        return (ap1);
        !            55: }
        !            56: 
        !            57: /*
        !            58:  * Allocate `l' bytes of memory.
        !            59:  */
        !            60: char *
        !            61: alloc(apq, l)
        !            62: ALL *apq;
        !            63: unsigned l;
        !            64: {
        !            65:        register ALL *ap;
        !            66:        register ALL *ap1;
        !            67:        register ALL *ap2;
        !            68:        register unsigned i;
        !            69:        register unsigned n;
        !            70:        register unsigned s;
        !            71:        char * ret = NULL;
        !            72: 
        !            73:        n = 1 + (l + sizeof(ALL) - 1) / sizeof(ALL);
        !            74:        for (i=0; i<2; i++) {
        !            75:                for (ap1=apq; link(ap1)!=apq; ap1=link(ap1)) {
        !            76:                        if (vtop(ap1) == 0) {
        !            77:                                panic("Corrupt arena");
        !            78:                                goto alloc_done;
        !            79:                        }
        !            80:                        if (tstfree(ap1)) {
        !            81:                               for (ap2=link(ap1); tstfree(ap2); ap2=link(ap2))
        !            82:                                        if (ap2 == apq)
        !            83:                                                break;
        !            84:                                ap1->a_link = (char *)ap2;
        !            85:                                if ((s=ap2-ap1) >= n) {
        !            86:                                        if (s > n) {
        !            87:                                                if (i == 0)
        !            88:                                                        continue;
        !            89:                                                ap = &ap1[n];
        !            90:                                                ap->a_link = (char *)ap2;
        !            91:                                                ap1->a_link = (char *)ap;
        !            92:                                        }
        !            93:                                        setused(ap1);
        !            94:                                        kclear((char *)ap1->a_data, l);
        !            95:                                        ret = ap1->a_data;
        !            96:                                        goto alloc_done;
        !            97:                                }
        !            98:                        }
        !            99:                }
        !           100:        }
        !           101:        u.u_error = ENOSPC;
        !           102:        goto alloc_done;
        !           103: alloc_done:
        !           104:        return ret;
        !           105: }
        !           106: 
        !           107: /*
        !           108:  * Free memory.
        !           109:  */
        !           110: free(cp)
        !           111: char *cp;
        !           112: {
        !           113:        register ALL *ap;
        !           114:        extern char __end;
        !           115: 
        !           116: #if 0
        !           117:        ap = ((ALL *)cp) - 1;
        !           118:        if (ap<(ALL *)&__end || tstfree(ap))
        !           119:                panic("Bad free %x\n", (unsigned)cp);
        !           120: #else
        !           121:        ap = ((ALL *)cp) - 1;
        !           122:        if (ap<(ALL *)&__end) {
        !           123:                int *r = (int *)(&cp);  /* return address */
        !           124:                printf("cp=%x ap=%x &__end=%x\n", cp, ap, &__end);
        !           125:                panic("Bad free() from eip=%x\n", *(r-1));
        !           126:        }
        !           127:        if (tstfree(ap)) {
        !           128:                int *r = (int *)(&cp);  /* return address */
        !           129:                printf("cp=%x tstfree(%x)=%x\n", cp, ap, tstfree(ap));
        !           130:                panic("Bad free() from eip=%x\n", *(r-1));
        !           131:        }
        !           132: #endif
        !           133:        setfree(ap);
        !           134: }
        !           135: 
        !           136: #endif /* TEST */
        !           137: 
        !           138: #ifdef _I386
        !           139: /*
        !           140:  * unsigned char *palloc(int size);
        !           141:  *
        !           142:  * Allocate 'size' bytes of kernel space, which does not cross a click
        !           143:  * boundary.  Returns a pointer to the space allocated on success,
        !           144:  * NULL on failure.
        !           145:  *
        !           146:  * Allocate twice as much memory as we need, and then return a chunk that
        !           147:  * does not cross a click boundary.  Immediately before the chunk that
        !           148:  * we return, we store the true address of the chunk that was kalloc()'d.
        !           149:  *
        !           150:  * Since this routine is for relatively small short-lived objects,
        !           151:  * which we expect to allocate frequently, speed is more important than
        !           152:  * space overhead.
        !           153:  *
        !           154:  * We assume that kalloc() returns word aligned addresses.
        !           155:  *
        !           156:  * There are two cases:
        !           157:  * There is enough room before the click boundary (or there is no click
        !           158:  *     boundary) for the pointer and the memory we need.
        !           159:  * Otherwise, return the chunk starting at the click boundary, storing
        !           160:  *     the pointer right before the click boundary.  This trick allows
        !           161:  *     us to allocate up to 1 full click.
        !           162:  *
        !           163:  * If kalloc() did NOT return word aligned chunks, then there would be
        !           164:  * a third case, where there might not be enough space for the pointer
        !           165:  * before the click boundary.
        !           166:  */
        !           167: 
        !           168: #define c_boundry(x)   ctob(btoc((x)+1)) /* Next click boundary above x.  */
        !           169: #define VOID   unsigned char
        !           170: 
        !           171: #ifdef TEST
        !           172: #undef kalloc
        !           173: #undef kfree
        !           174: VOID *kalloc();
        !           175: void kfree();
        !           176: #endif /* TEST */
        !           177: 
        !           178: VOID *
        !           179: palloc(size)
        !           180:        int size;       /* Size in bytes of area to allocate.  */
        !           181: {
        !           182:        VOID *local_arena;      /* Value returned by kalloc().  */
        !           183:        VOID *boundry;          /* Next click boundry above local_arena.  */
        !           184:        VOID *retval;           /* What we give back to our caller.  */
        !           185: 
        !           186:        if (size > NBPC) {
        !           187:                panic("palloc(%x): can not palloc more than 1 click.", size);
        !           188:        }
        !           189: 
        !           190:        /* Fetch twice as much space as requested, plus a pointer.  */
        !           191:        if ( NULL == (local_arena =
        !           192:                (VOID *)kalloc(sizeof(VOID *) + (2 * size)))) {
        !           193:                return NULL;
        !           194:        }
        !           195: 
        !           196:        
        !           197:        boundry = (VOID *) c_boundry(local_arena);
        !           198: 
        !           199:        T_PIGGY(0x2000, printf("b: %x ", boundry); );
        !           200: 
        !           201:        /* First case:  enough space before the boundry.  */
        !           202:        if ( (boundry - local_arena) >= (size + sizeof(VOID *)) ) {
        !           203: 
        !           204:                T_PIGGY(0x2000, printf("c1 "); );
        !           205: 
        !           206:                * (VOID **)local_arena = local_arena;
        !           207:                retval = local_arena + sizeof(VOID *);
        !           208:        } else if ((boundry - local_arena) < sizeof(VOID *)) {
        !           209:                /*
        !           210:                 * Second case: There is not enough space before the
        !           211:                 * boundry for the whole pointer.
        !           212:                 */
        !           213:                T_PIGGY(0x2000, printf("c2 "); );
        !           214: 
        !           215:                * (VOID **)local_arena = local_arena;
        !           216:                retval = local_arena + sizeof(VOID *);
        !           217:        } else {
        !           218: 
        !           219:                T_PIGGY(0x2000, printf("c3: %x ", (boundry - local_arena)); );
        !           220: 
        !           221:                * (VOID **)(boundry - sizeof(VOID *)) = local_arena;
        !           222:                retval = boundry;
        !           223:        }
        !           224: 
        !           225:        T_PIGGY( 0x2000, {
        !           226:                printf("palloc(%x) = %x:%x (was %x:%x), ",
        !           227:                        size, retval, (retval+size)-1,
        !           228:                        local_arena, (local_arena+(2*size)+sizeof(VOID *))-1);
        !           229:        } );
        !           230: 
        !           231:        T_PIGGY( 0x2000, {
        !           232:                if ((retval+size)-1 > (local_arena+(2*size)+sizeof(VOID *))-1) {
        !           233:                        printf("\npalloc() overrun\n");
        !           234:                }
        !           235:                if (retval < local_arena) {
        !           236:                        printf("\npalloc() underrun\n");
        !           237:                }
        !           238:        } );
        !           239:        return((VOID *)retval);
        !           240: } /* palloc() */
        !           241: 
        !           242: /*
        !           243:  * void pfree(VOID *ptr);
        !           244:  * Free the chunk of memory 'ptr' allocated by palloc().
        !           245:  *
        !           246:  * Note that 'ptr' is really a VOID *, but we call it VOID **
        !           247:  * to simplify arithmetic.
        !           248:  *
        !           249:  * The address returned by kalloc() is stored immediately
        !           250:  * before the chunk returned by palloc().
        !           251:  */
        !           252: void
        !           253: pfree(ptr)
        !           254:        VOID *ptr[];
        !           255: {
        !           256:        T_PIGGY(0x2000, { printf("pfree(%x):kfree(%x), ", ptr, *(ptr-1)); } );
        !           257:        kfree(*(ptr-1));
        !           258: } /* pfree() */
        !           259: 
        !           260: 
        !           261: #ifdef TEST
        !           262: 
        !           263: #include <stdio.h>
        !           264: #define FOURK  4096    /* How many bytes in 4K?  */
        !           265: #define NUM_TESTS 40   /* How many tests do we run?  */
        !           266: #define SMALL_NUMBER 6 /* A small number whose exact value we don't care about.  */
        !           267: #define HUGE   (100*FOURK)     /* Allocate from this pool.  */
        !           268: #define IGNORE(v)      (v==v)  /* Lint food.  */
        !           269: 
        !           270: unsigned t_piggy = 0x2000;     /* Turn on TRACER bits.  */
        !           271: 
        !           272: main()
        !           273: {
        !           274:        int i;
        !           275:        VOID *chunk;
        !           276: 
        !           277:        for (i = 0; i < NUM_TESTS; ++i) {
        !           278:                if (NULL == (chunk = palloc(SMALL_NUMBER))) {
        !           279:                        printf("No more fake memory to eat.\n");
        !           280:                        printf("This is probably a bug.\n");
        !           281:                        exit(1);
        !           282:                }
        !           283: 
        !           284:                printf("chunk: %x\n", chunk);
        !           285:        }
        !           286: } /* main() for TEST */
        !           287: 
        !           288: /*
        !           289:  * Print a message and die.
        !           290:  */
        !           291: panic(args)
        !           292: {
        !           293:        printf("%r\n", &args);
        !           294:        exit(1);
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Fake kalloc() for use by palloc().
        !           299:  * Allocate a chunk of some non-existant memory space.
        !           300:  */
        !           301: VOID *
        !           302: kalloc(size)
        !           303:        int size;
        !           304: {
        !           305:        static VOID *base = NULL;
        !           306:        static VOID *top_free = NULL;
        !           307:        VOID *retval;
        !           308: 
        !           309: 
        !           310:        /*
        !           311:         * First time through, allocate a nice big chunk of memory
        !           312:         * to carve up.
        !           313:         */
        !           314:        if (NULL == base) {
        !           315:                if (NULL == (base = malloc(HUGE))) {
        !           316:                        printf("Can not malloc %d bytes.\n", HUGE);
        !           317:                        exit(1);
        !           318:                }
        !           319:                /* Make sure we start close to a click boundry.  */
        !           320:                top_free = c_boundry(base) + SMALL_NUMBER;
        !           321:        }
        !           322: 
        !           323:        retval = top_free;
        !           324:        /*
        !           325:         * We want to encourage test addresses to migrate accross
        !           326:         * click boundries.
        !           327:         */
        !           328:        if (size < (FOURK - 1)) {
        !           329:                top_free += (FOURK - 1);
        !           330:        } else {
        !           331:                top_free += size;
        !           332:        }
        !           333: 
        !           334:        return(retval);
        !           335: } /* kalloc() */
        !           336: 
        !           337: /*
        !           338:  * Fake kfree for pfree() to use.
        !           339:  */
        !           340: void
        !           341: kfree(addr)
        !           342:        VOID *addr;
        !           343: {
        !           344:        IGNORE(addr);
        !           345:        /* Do nothing!  */
        !           346: } /* kfree() */
        !           347: 
        !           348: #endif /* TEST */
        !           349: 
        !           350: #endif /* _I386 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.