|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.