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