|
|
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.