Annotation of coherent/b/kernel/coh.386/alloc.c, revision 1.1.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.