home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume12 / pathalias9 / part01 / mem.c < prev    next >
C/C++ Source or Header  |  1987-10-08  |  4KB  |  241 lines

  1. /* pathalias -- by steve bellovin, as told to peter honeyman */
  2. #ifndef lint
  3. static char    *sccsid = "@(#)mem.c    9.1 87/10/04";
  4. #endif
  5.  
  6. #include "def.h"
  7.  
  8. /* exports */
  9. extern void freelink(), wasted();
  10. extern long allocation();
  11. long Ncount;
  12.  
  13. /* imports */
  14. extern char *sbrk();
  15. extern char *Netchars;
  16. extern int Vflag;
  17. extern void die();
  18.  
  19. /* privates */
  20. STATIC void nomem();
  21. static link *Lcache;
  22. static unsigned int Memwaste;
  23.  
  24. link    *
  25. newlink()
  26. {    register link *rval;
  27.  
  28.     if (Lcache) {
  29.          rval = Lcache;
  30.         Lcache = Lcache->l_next;
  31.         strclear((char *) rval, sizeof(link));
  32.     } else if ((rval = (link * ) calloc(1, sizeof(link))) == 0)
  33.         nomem();
  34.     return rval;
  35. }
  36.  
  37. /* caution: this destroys the contents of l_next */
  38. void
  39. freelink(l)
  40.     link *l;
  41. {
  42.     l->l_next = Lcache;
  43.     Lcache = l;
  44. }
  45.  
  46. node    *
  47. newnode()
  48. {    register node *rval;
  49.  
  50.     if ((rval = (node * ) calloc(1, sizeof(node))) == 0)
  51.         nomem();
  52.     Ncount++;
  53.     return rval;
  54. }
  55.  
  56. char    *
  57. strsave(s)
  58.     char *s;
  59. {    register char *r;
  60.  
  61.     if ((r = malloc((unsigned) strlen(s) + 1)) == 0)
  62.         nomem();
  63.     (void) strcpy(r, s);
  64.     return r;
  65. }
  66.  
  67. #ifndef strclear
  68. void
  69. strclear(str, len)
  70.     register char *str;
  71.     register long len;
  72. {
  73.     while (--len >= 0)
  74.         *str++ = 0;
  75. }
  76. #endif /*strclear*/
  77.  
  78. node    **
  79. newtable(size)
  80.     long size;
  81. {    register node **rval;
  82.  
  83.     if ((rval = (node **) calloc(1, (unsigned int) size * sizeof(node *))) == 0) 
  84.         nomem();
  85.     return rval;
  86. }
  87.  
  88. freetable(t, size)
  89.     node **t;
  90.     long size;
  91. {
  92. #ifdef MYMALLOC
  93.     addtoheap((char *) t, size * sizeof(node *));
  94. #else
  95.     free((char *) t);
  96. #endif
  97. }
  98.  
  99. STATIC void
  100. nomem()
  101. {
  102.     static char epitaph[128];
  103.  
  104.     sprintf(epitaph, "out of memory (%ldk allocated)", allocation());
  105.     die(epitaph);
  106. }
  107.  
  108. /* data space allocation -- main sets `dataspace' very early */
  109. long
  110. allocation()
  111. {
  112.     static char *dataspace;
  113.     long rval;
  114.  
  115.     if (dataspace == 0) {        /* first time */
  116.         dataspace = sbrk(0);    /* &end? */
  117.         return 0;
  118.     }
  119.     rval = (sbrk(0) - dataspace)/1024;
  120.     if (rval < 0)            /* funny architecture? */
  121.         rval = -rval;
  122.     return rval;
  123. }
  124.  
  125. /* how much memory has been wasted? */
  126. void
  127. wasted()
  128. {
  129.     if (Memwaste == 0)
  130.         return;
  131.     vprintf(stderr, "memory allocator wasted %ld bytes\n", Memwaste);
  132. }
  133.  
  134. #ifdef MYMALLOC
  135.  
  136. /* use c library malloc/calloc here, and here only */
  137. #undef malloc
  138. #undef calloc
  139. extern char *malloc(), *calloc();
  140.  
  141. /* allocate in MBUFSIZ chunks.  4k works ok (less 16 for malloc quirks). */
  142. #define MBUFSIZ (4 * 1024 - 16)
  143.  
  144. /* 
  145.  * mess with ALIGN at your peril.  longword (== 0 mod 4)
  146.  * alignment seems to work everywhere.
  147.  */
  148.  
  149. #define ALIGN 2
  150.  
  151. typedef struct heap heap;
  152. struct heap {
  153.     heap *h_next;
  154.     long h_size;
  155. };
  156.  
  157. static heap *Mheap;    /* not to be confused with a priority queue */
  158.  
  159. addtoheap(p, size)
  160.     char *p;
  161.     long size;
  162. {    int adjustment;
  163.     heap *pheap;
  164.  
  165.     /* p is aligned, but it doesn't hurt to check */
  166.     adjustment = align(p);
  167.     p += adjustment;
  168.     size -= adjustment;
  169.  
  170.     if (size < 1024)
  171.         return;        /* can't happen */
  172.     pheap = (heap *) p;    /* pheap is shorthand */
  173.     pheap->h_next = Mheap;
  174.     pheap->h_size = size;
  175.     Mheap = pheap;
  176. }
  177.  
  178. /*
  179.  * buffered malloc()
  180.  *    returns space initialized to 0.  calloc isn't used, since
  181.  *    strclear can be faster.
  182.  *
  183.  * free is ignored, except for very large objects,
  184.  * which are returned to the heap with addtoheap(). 
  185.  */
  186.  
  187. char    *
  188. mymalloc(n)
  189.     register unsigned int n;
  190. {    static unsigned int size; /* how much do we have on hand? */
  191.     static char *mstash;      /* where is it? */
  192.     register char *rval;
  193.  
  194.     if (n >= 1024) {        /* for hash table */
  195.         rval = malloc(n);    /* aligned */
  196.         if (rval)
  197.             strclear(rval, n);
  198.         return rval;
  199.     }
  200.  
  201.     n += align((char *) n);    /* keep everything aligned */
  202.  
  203.     if (n > size) {
  204.         Memwaste += size;    /* toss the fragment */
  205.         /* look in the heap */
  206.         if (Mheap) {
  207.             mstash = (char *) Mheap;    /* aligned */
  208.             size = Mheap->h_size;
  209.             Mheap = Mheap->h_next;
  210.         } else {
  211.             mstash = malloc(MBUFSIZ);    /* aligned */
  212.             if (mstash == 0) {
  213.                 size = 0;
  214.                 return 0;
  215.             }
  216.             size = MBUFSIZ;
  217.         }
  218.         strclear(mstash, size);        /* what if size > 2^16? */
  219.     }
  220.     rval = mstash;
  221.     mstash += n;
  222.     size -= n;
  223.     return rval;
  224. }
  225.  
  226. /*
  227.  * what's the (mis-)alignment of n?  return the complement of
  228.  * n mod 2^ALIGN
  229.  */
  230. align(n)
  231.     char *n;
  232. {    register int abits;    /* misalignment bits in n */
  233.  
  234.     abits = (int) n & ~(0xff << ALIGN) & 0xff;
  235.     if (abits == 0)
  236.         return 0;
  237.     return (1 << ALIGN) - abits;
  238. }
  239.  
  240. #endif /*MYMALLOC*/
  241.