Annotation of coherent/d/PS2_KERNEL/coh.386/alloc.c, revision 1.1

1.1     ! root        1: /* $Header: /kernel/kersrc/coh.386/RCS/alloc.c,v 1.2 92/08/04 12:29:54 bin Exp Locker: bin $ */
        !             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.2  92/08/04  12:29:54  bin
        !            21:  * changed for kernel 59
        !            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:        ap = ((ALL *)cp) - 1;
        !           117:        if (ap<(ALL *)&__end || tstfree(ap))
        !           118:                panic("Bad free %x\n", (unsigned)cp);
        !           119:        setfree(ap);
        !           120: }
        !           121: 
        !           122: #endif /* TEST */
        !           123: 
        !           124: #ifdef _I386
        !           125: /*
        !           126:  * unsigned char *palloc(int size);
        !           127:  *
        !           128:  * Allocate 'size' bytes of kernel space, which does not cross a click
        !           129:  * boundary.  Returns a pointer to the space allocated on success,
        !           130:  * NULL on failure.
        !           131:  *
        !           132:  * Allocate twice as much memory as we need, and then return a chunk that
        !           133:  * does not cross a click boundary.  Immediately before the chunk that
        !           134:  * we return, we store the true address of the chunk that was kalloc()'d.
        !           135:  *
        !           136:  * Since this routine is for relatively small short-lived objects,
        !           137:  * which we expect to allocate frequently, speed is more important than
        !           138:  * space overhead.
        !           139:  *
        !           140:  * We assume that kalloc() returns word aligned addresses.
        !           141:  *
        !           142:  * There are two cases:
        !           143:  * There is enough room before the click boundary (or there is no click
        !           144:  *     boundary) for the pointer and the memory we need.
        !           145:  * Otherwise, return the chunk starting at the click boundary, storing
        !           146:  *     the pointer right before the click boundary.  This trick allows
        !           147:  *     us to allocate up to 1 full click.
        !           148:  *
        !           149:  * If kalloc() did NOT return word aligned chunks, then there would be
        !           150:  * a third case, where there might not be enough space for the pointer
        !           151:  * before the click boundary.
        !           152:  */
        !           153: 
        !           154: #define c_boundry(x)   ctob(btoc((x)+1)) /* Next click boundary above x.  */
        !           155: #define VOID   unsigned char
        !           156: 
        !           157: #ifdef TEST
        !           158: #undef kalloc
        !           159: #undef kfree
        !           160: VOID *kalloc();
        !           161: void kfree();
        !           162: #endif /* TEST */
        !           163: 
        !           164: VOID *
        !           165: palloc(size)
        !           166:        int size;       /* Size in bytes of area to allocate.  */
        !           167: {
        !           168:        VOID *local_arena;      /* Value returned by kalloc().  */
        !           169:        VOID *boundry;          /* Next click boundry above local_arena.  */
        !           170:        VOID *retval;           /* What we give back to our caller.  */
        !           171: 
        !           172:        if (size > NBPC) {
        !           173:                panic("palloc(%x): can not palloc more than 1 click.", size);
        !           174:        }
        !           175: 
        !           176:        /* Fetch twice as much space as requested, plus a pointer.  */
        !           177:        if ( NULL == (local_arena =
        !           178:                (VOID *)kalloc(sizeof(VOID *) + (2 * size)))) {
        !           179:                return NULL;
        !           180:        }
        !           181: 
        !           182:        
        !           183:        boundry = (VOID *) c_boundry(local_arena);
        !           184: 
        !           185:        T_PIGGY(0x2000, printf("b: %x ", boundry); );
        !           186: 
        !           187:        /* First case:  enough space before the boundry.  */
        !           188:        if ( (boundry - local_arena) >= (size + sizeof(VOID *)) ) {
        !           189: 
        !           190:                T_PIGGY(0x2000, printf("c1 "); );
        !           191: 
        !           192:                * (VOID **)local_arena = local_arena;
        !           193:                retval = local_arena + sizeof(VOID *);
        !           194:        } else if ((boundry - local_arena) < sizeof(VOID *)) {
        !           195:                /*
        !           196:                 * Second case: There is not enough space before the
        !           197:                 * boundry for the whole pointer.
        !           198:                 */
        !           199:                T_PIGGY(0x2000, printf("c2 "); );
        !           200: 
        !           201:                * (VOID **)local_arena = local_arena;
        !           202:                retval = local_arena + sizeof(VOID *);
        !           203:        } else {
        !           204: 
        !           205:                T_PIGGY(0x2000, printf("c3: %x ", (boundry - local_arena)); );
        !           206: 
        !           207:                * (VOID **)(boundry - sizeof(VOID *)) = local_arena;
        !           208:                retval = boundry;
        !           209:        }
        !           210: 
        !           211:        T_PIGGY( 0x2000, {
        !           212:                printf("palloc(%x) = %x:%x (was %x:%x), ",
        !           213:                        size, retval, (retval+size)-1,
        !           214:                        local_arena, (local_arena+(2*size)+sizeof(VOID *))-1);
        !           215:        } );
        !           216: 
        !           217:        T_PIGGY( 0x2000, {
        !           218:                if ((retval+size)-1 > (local_arena+(2*size)+sizeof(VOID *))-1) {
        !           219:                        printf("\npalloc() overrun\n");
        !           220:                }
        !           221:                if (retval < local_arena) {
        !           222:                        printf("\npalloc() underrun\n");
        !           223:                }
        !           224:        } );
        !           225:        return((VOID *)retval);
        !           226: } /* palloc() */
        !           227: 
        !           228: /*
        !           229:  * void pfree(VOID *ptr);
        !           230:  * Free the chunk of memory 'ptr' allocated by palloc().
        !           231:  *
        !           232:  * Note that 'ptr' is really a VOID *, but we call it VOID **
        !           233:  * to simplify arithmetic.
        !           234:  *
        !           235:  * The address returned by kalloc() is stored immediately
        !           236:  * before the chunk returned by palloc().
        !           237:  */
        !           238: void
        !           239: pfree(ptr)
        !           240:        VOID *ptr[];
        !           241: {
        !           242:        T_PIGGY(0x2000, { printf("pfree(%x):kfree(%x), ", ptr, *(ptr-1)); } );
        !           243:        kfree(*(ptr-1));
        !           244: } /* pfree() */
        !           245: 
        !           246: 
        !           247: #ifdef TEST
        !           248: 
        !           249: #include <stdio.h>
        !           250: #define FOURK  4096    /* How many bytes in 4K?  */
        !           251: #define NUM_TESTS 40   /* How many tests do we run?  */
        !           252: #define SMALL_NUMBER 6 /* A small number whose exact value we don't care about.  */
        !           253: #define HUGE   (100*FOURK)     /* Allocate from this pool.  */
        !           254: #define IGNORE(v)      (v==v)  /* Lint food.  */
        !           255: 
        !           256: unsigned t_piggy = 0x2000;     /* Turn on TRACER bits.  */
        !           257: 
        !           258: main()
        !           259: {
        !           260:        int i;
        !           261:        VOID *chunk;
        !           262: 
        !           263:        for (i = 0; i < NUM_TESTS; ++i) {
        !           264:                if (NULL == (chunk = palloc(SMALL_NUMBER))) {
        !           265:                        printf("No more fake memory to eat.\n");
        !           266:                        printf("This is probably a bug.\n");
        !           267:                        exit(1);
        !           268:                }
        !           269: 
        !           270:                printf("chunk: %x\n", chunk);
        !           271:        }
        !           272: } /* main() for TEST */
        !           273: 
        !           274: /*
        !           275:  * Print a message and die.
        !           276:  */
        !           277: panic(args)
        !           278: {
        !           279:        printf("%r\n", &args);
        !           280:        exit(1);
        !           281: }
        !           282: 
        !           283: /*
        !           284:  * Fake kalloc() for use by palloc().
        !           285:  * Allocate a chunk of some non-existant memory space.
        !           286:  */
        !           287: VOID *
        !           288: kalloc(size)
        !           289:        int size;
        !           290: {
        !           291:        static VOID *base = NULL;
        !           292:        static VOID *top_free = NULL;
        !           293:        VOID *retval;
        !           294: 
        !           295: 
        !           296:        /*
        !           297:         * First time through, allocate a nice big chunk of memory
        !           298:         * to carve up.
        !           299:         */
        !           300:        if (NULL == base) {
        !           301:                if (NULL == (base = malloc(HUGE))) {
        !           302:                        printf("Can not malloc %d bytes.\n", HUGE);
        !           303:                        exit(1);
        !           304:                }
        !           305:                /* Make sure we start close to a click boundry.  */
        !           306:                top_free = c_boundry(base) + SMALL_NUMBER;
        !           307:        }
        !           308: 
        !           309:        retval = top_free;
        !           310:        /*
        !           311:         * We want to encourage test addresses to migrate accross
        !           312:         * click boundries.
        !           313:         */
        !           314:        if (size < (FOURK - 1)) {
        !           315:                top_free += (FOURK - 1);
        !           316:        } else {
        !           317:                top_free += size;
        !           318:        }
        !           319: 
        !           320:        return(retval);
        !           321: } /* kalloc() */
        !           322: 
        !           323: /*
        !           324:  * Fake kfree for pfree() to use.
        !           325:  */
        !           326: void
        !           327: kfree(addr)
        !           328:        VOID *addr;
        !           329: {
        !           330:        IGNORE(addr);
        !           331:        /* Do nothing!  */
        !           332: } /* kfree() */
        !           333: 
        !           334: #endif /* TEST */
        !           335: 
        !           336: #endif /* _I386 */

unix.superglobalmegacorp.com

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