|
|
1.1 ! root 1: /*** ! 2: Begin memory management routines: pcreat2, gblock, and rblock. ! 3: Assumes fixed sized blocks. This approach produces no memory ! 4: fragmentation, and requires no garbage collection. This feature ! 5: is important in a real-time environment. ! 6: ! 7: (c) 1988 Philip Zimmermann ! 8: Boulder Software Engineering ! 9: 3021 Eleventh Street ! 10: Boulder, CO 80304 ! 11: (303) 444-4541 ! 12: ! 13: 31 July 88 ! 14: Revised 15 Dec 90 ! 15: ***/ ! 16: ! 17: /* #define _NOPRINTF /* define if no printf available */ ! 18: #ifndef _NOPRINTF ! 19: #include <stdio.h> /* for printf(), puts() */ ! 20: #endif ! 21: /* Define whether malloc is available. Some embedded systems lack it. */ ! 22: /* #define _NOMALLOC */ /* define if no malloc is available. */ ! 23: #ifndef _NOMALLOC /* malloc library routine available */ ! 24: #include <stdlib.h> /* ANSI C library - for malloc() and free() */ ! 25: /* #include <alloc.h> */ /* Borland Turbo C has malloc in <alloc.h> */ ! 26: #endif /* malloc available */ ! 27: ! 28: #include "memmgr.h" /* memory manager headers */ ! 29: ! 30: #define putstr(s) puts(s) /* put string */ ! 31: ! 32: /* gblock and rblock contain critical sections of code that should not ! 33: be interrupted by any other process that might use the same data ! 34: structure. We protect this critical code by disabling interrupts. ! 35: The primitives for this are begin_critical_section() and ! 36: end_critical_section(). These are necessarily machine-dependent ! 37: primitives, and are only needed in multitasking or interrupt- ! 38: driven realtime environments. For non-realtime environments, ! 39: stubs are provided here for these primitives. ! 40: */ ! 41: #define begin_critical_section() /* null stub */ ! 42: #define end_critical_section() /* null stub */ ! 43: ! 44: /* This typedef for a memory partition is unused, but is here for clarity */ ! 45: typedef struct /* memory manager partition structure */ ! 46: { ptr head; /* ptr to head of free list */ ! 47: p_range psize; /* partition size, as measured in bytes */ ! 48: byte body; /* body of memory partition starts here */ ! 49: } partition; ! 50: ! 51: ! 52: /* ! 53: ** partsize - returns size of partition in bytes ! 54: ** Used to declare storage for a memory partition array of bytes. ! 55: ** Computed from the block size, the number of blocks, ! 56: ** plus partheadsize. ! 57: ** ! 58: ** partheadsize is a #define in the header file "memmgr.h" ! 59: ** partsize() is a #define in the header file "memmgr.h" ! 60: */ ! 61: ! 62: ! 63: /* ! 64: ** pcreate - initialize memory manager partition ! 65: ** Similar to pcreat2, but with slightly different arguments. ! 66: ** ! 67: ** pcreate() is a #define in the header file "memmgr.h" ! 68: */ ! 69: ! 70: ! 71: /* ! 72: ** pcreat2 - initialize memory manager partition ! 73: ** ! 74: ** Create a linked list of fixed-sized free memory blocks. ! 75: ** Note that the link field of each block has meaning only when the ! 76: ** block is in the list of deallocated blocks. ! 77: ** If invoked in a real-time environment, we assume this entire ! 78: ** routine is executed without interruption. ! 79: */ ! 80: void pcreat2(ptr part, word16 bsize, word16 nblocks) ! 81: /* part is pointer to memory partition, better if aligned ! 82: to ptr boundary. ! 83: bsize is block size, must be ptr aligned. ! 84: nblocks is number of blocks. ! 85: */ ! 86: { ptr link; /* scratch pointer */ ! 87: p_range * psize; /* pointer to partition size */ ! 88: psize = (p_range *) (part + sizeof(ptr)); ! 89: *psize = partsize(bsize,nblocks); ! 90: link = part + partheadsize; /* address of 1st block */ ! 91: *(ptr *) part = link; /* point head at 1st block */ ! 92: ! 93: while (nblocks--) ! 94: { part = link; /* skip to next block */ ! 95: /* compute addr of next block */ ! 96: link += bsize; /* compute addr of next block */ ! 97: *(ptr *) part = link; /* create link to it */ ! 98: } ! 99: *(ptr *) part = nil; /* last link in chain is nil */ ! 100: } /* pcreat2 */ ! 101: ! 102: #ifndef _NOMALLOC /* malloc library routine available */ ! 103: /* ! 104: ** partalloc - allocate and initialize memory manager partition ! 105: ** Returns a ptr to the initialized partition, or NULL if there's no room. ! 106: ** Can be called instead of pcreat2, if the storage needs allocating. ! 107: ** If invoked in a real-time environment, we assume this entire ! 108: ** routine is executed without interruption. ! 109: */ ! 110: ptr partalloc(word16 bsize, word16 nblocks) ! 111: /* bsize is block size. ! 112: nblocks is number of blocks. ! 113: */ ! 114: { ptr *part; ! 115: /* allign block size to ptr boundary */ ! 116: bsize = alignptr(bsize); ! 117: /* allocate memory partition... */ ! 118: part = (ptr *) malloc(partsize(bsize,nblocks)); ! 119: if (part != NULL) /* if memory is not exhausted... */ ! 120: pcreat2((ptr) part,bsize,nblocks); ! 121: return ((ptr) part); ! 122: } /* partalloc */ ! 123: #endif /* ifndef _NOMALLOC */ ! 124: ! 125: /* ! 126: ** gblock - get memory block from partition ! 127: ** ! 128: ** Delink a block from the head of the linked list of free blocks. ! 129: */ ! 130: ptr gblock(register ptr part) ! 131: /* part is pointer to memory partition. */ ! 132: { register ptr link; /* scratch pointer */ ! 133: begin_critical_section(); /* prevent interruption */ ! 134: link = *(ptr *) part; /* get head of free list */ ! 135: if (link != nil) /* list exhausted if head is nil */ ! 136: *(ptr *) part = *(ptr *) link; /* update head */ ! 137: #ifdef DEBUG ! 138: else putstr("\nGblock warning: memory partion exhausted!\07\n"); ! 139: #endif /* DEBUG */ ! 140: end_critical_section(); ! 141: return (link); /* return address of memory block or nil */ ! 142: /* Note that this allocated block's link field is now trashable. */ ! 143: } /* gblock */ ! 144: ! 145: ! 146: /* ! 147: ** rblock - release memory block to partition ! 148: ** ! 149: ** Insert a block at the head of the linked list of free blocks. ! 150: */ ! 151: ptr rblock(register ptr part, register ptr addr) ! 152: /* part is pointer to memory partition. ! 153: addr is pointer to block--must belong to partition. ! 154: */ ! 155: { register ptr link; /* scratch pointer */ ! 156: #ifdef DEBUG ! 157: { p_range * psize; /* pointer to partition size */ ! 158: psize = (p_range *) (part + sizeof(ptr)); ! 159: if ( ( addr > (part + *psize) ) ! 160: || ( addr < (part + partheadsize) ) ) ! 161: { if (addr==nil) /* special case diagnostic */ ! 162: putstr("\nRblock warning: nil memory block pointer\07\n"); ! 163: else ! 164: putstr("\nRblock error: memory block not in partition!\07\n"); ! 165: return (addr); /* return ptr unmodified */ ! 166: } ! 167: } ! 168: #endif /* DEBUG */ ! 169: begin_critical_section(); /* prevent interruption */ ! 170: link = *(ptr *) part; /* save old head of free list */ ! 171: *(ptr *) addr = link; /* point released block at old head */ ! 172: *(ptr *) part = addr; /* point head at released block */ ! 173: end_critical_section(); ! 174: return (nil); /* normal return--nil ptr */ ! 175: } /* rblock */ ! 176: ! 177: ! 178: #ifndef _NOPRINTF /* printf available */ ! 179: /* ! 180: ** dumpfree - dump a partition's free block list in hex. ! 181: ** If invoked in a real-time environment, we assume this entire ! 182: ** routine is executed without interruption. ! 183: */ ! 184: void dumpfree(ptr part) ! 185: /* part is pointer to memory partition. */ ! 186: { byte i; ! 187: p_range * psize; /* pointer to partition size */ ! 188: psize = (p_range *) (part + sizeof(ptr)); ! 189: i = 0; ! 190: printf("\nMemory partition at %04X, size=%04X ",part,*psize); ! 191: while ((*(ptr *)part)!=nil) /* go until we hit a nil ptr */ ! 192: { if ((i-- & 7)==0) putchar('\n'); ! 193: printf("%04X ",*(ptr *)part); /* print a pointer */ ! 194: part = *(ptr *)part; /* follow chain */ ! 195: } ! 196: putstr("nil\n"); ! 197: } /* dumpfree */ ! 198: #endif /* ifndef _NOPRINTF */ ! 199: ! 200:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.