home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------
- getmem.c
-
- Implements low overhead memory management for nonrelocatable
- blocks on the Macintosh. This code is based on "Operating System
- Design: The XINU Approach" by Douglas Comer (Prentice Hall, 1984.
- Great book!)
-
- Motivation:
-
- The Macintosh Memory Manager is designed to use relocatable
- blocks (i.e. pointers to pointers) for heap data structures. In
- order that relocatable blocks be free to move the Memory Manager
- tries to keep nonrelocatable blocks (i.e. blocks referred to by
- pointers) out of the way, i.e. in low mem. To do this, when a program
- asks for a nonrelocatable block the Memory Manager starts a linear
- search for available space at the bottom of the heap. In an
- application such as a tree, where many thousands of small blocks are
- needed, the linear search technique quickly dies.
-
- The code below bypasses this problem by requesting one large block at
- the start of execution (i.e. when init_mem is called). The function
- getmem then maintains a pointer to the next available block. Thus
- any request for memory is satisfied immediately. No search is needed.
- The performance difference in the contour analysis is quite dramatic.
-
- The code below is quite simple but not flexible. One notable
- lack is for a routine to free memory. Such a function is shown in
- Comer's book. Another limitation that only one block is used.
- The functions can be extended to be able to add new blocks when it
- needs additional space.
-
-
- William May
- 303A Ridgefield Circle
- Clinton, MA 01510
-
- created: 3/25/87 very primitive version, but works:
- one pool only created
- user has to guess the required space
- speed increase is dramatic, especially
- as the contour algorithm progresses (i.e.
- as the AVL tree gets quite large).
- -------------------------------------------------------------------- */
-
- #include <MemoryMgr.h>
- #include "mem.h"
-
- struct mblock memlist; /* head of free memory list */
- struct pool *plist; /* head of pool list */
-
- /*---------------------------------------------------------------------
- init_mem creates a large memory pool, and initializes the necessary
- data structures.
- ---------------------------------------------------------------------*/
- int init_mem()
- {
- plist = (struct pool *)NewPtr(sizeof(struct pool) + DEFSIZE);
-
- if (MemErr == noErr) {
- plist->pnext = (struct pool *)0;
-
- memlist.mnext = &(plist->firstblock);
- (memlist.mnext)->mnext = (struct mblock *)0;
- (memlist.mnext)->mlen = (long)(DEFSIZE);
- }
-
- return MemErr;
- }
-
- /*---------------------------------------------------------------------
- getmem allocates memory in the pool. On successful completion
- a pointer to the allocated space is returned to the caller. Otherwise
- a null pointer (0L) is returned.
- ----------------------------------------------------------------------*/
- int *getmem(nbytes)
- unsigned long nbytes;
- {
- register struct mblock *p, *q, *leftover;
-
- if (nbytes == 0) {
- return (int *)0;
- }
-
- nbytes = (unsigned long)roundew(nbytes);
-
- for (q=&memlist, p=memlist.mnext; p != 0L; q=p, p=p->mnext)
- if (p->mlen == nbytes) {
- q->mnext = p->mnext;
- return ((int *)p);
- } else if (p->mlen > nbytes) {
- leftover = (struct mblock *)((unsigned long)p + nbytes);
- q->mnext = leftover;
- leftover->mnext = p->mnext;
- leftover->mlen = (long)(p->mlen - nbytes);
- return ((int *)p);
- }
-
- return ((int *)0);
- }