home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 1222.MEMMGR.C < prev    next >
Text File  |  1990-12-17  |  7KB  |  201 lines

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