home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / g77-0.5.15-src.tgz / tar.out / fsf / g77 / f / malloc.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  11KB  |  474 lines

  1. /* malloc.c -- Implementation File (module.c template V1.0)
  2.    Copyright (C) 1995 Free Software Foundation, Inc.
  3.    Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
  4.  
  5. This file is part of GNU Fortran.
  6.  
  7. GNU Fortran is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU Fortran is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU Fortran; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Related Modules:
  22.       None
  23.  
  24.    Description:
  25.       Fast pool-based memory allocation.
  26.  
  27.    Modifications:
  28. */
  29.  
  30. /* Include files. */
  31.  
  32. #include "proj.h"
  33. #include "malloc.h"
  34.  
  35. /* For systems where <stdlib.h> is missing: */
  36.  
  37. void *malloc (size_t size);
  38. void *realloc (void *ptr, size_t size);
  39.  
  40. /* Externals defined here.  */
  41.  
  42. struct _malloc_root_ malloc_root_
  43. =
  44. {
  45.   {
  46.     &malloc_root_.malloc_pool_image_,
  47.     &malloc_root_.malloc_pool_image_,
  48.     (mallocPool) & malloc_root_.malloc_pool_image_.eldest,
  49.     (mallocPool) & malloc_root_.malloc_pool_image_.eldest,
  50.     (mallocArea_) & malloc_root_.malloc_pool_image_.first,
  51.     (mallocArea_) & malloc_root_.malloc_pool_image_.first,
  52.     0, 0, 0, 0, 0, 0, 0},
  53.   "Image"
  54. };
  55.  
  56. /* Simple definitions and enumerations. */
  57.  
  58.  
  59. /* Internal typedefs. */
  60.  
  61.  
  62. /* Private include files. */
  63.  
  64.  
  65. /* Internal structure definitions. */
  66.  
  67.  
  68. /* Static objects accessed by functions in this module. */
  69.  
  70. static void *malloc_reserve_ = NULL;    /* For crashes. */
  71. static char *malloc_types_[]
  72. =
  73. {"KS", "KSR", "NF", "NFR", "US", "USR"};
  74.  
  75. /* Static functions (internal). */
  76.  
  77. static void malloc_kill_area_ (mallocPool pool, mallocArea_ a);
  78.  
  79. /* Internal macros. */
  80.  
  81. #define malloc_kill_(ptr,s) do {memset((ptr),127,(s));free((ptr));} while(0)
  82.  
  83. /* malloc_kill_area_ -- Kill storage area and its object
  84.  
  85.    malloc_kill_area_(mallocPool pool,mallocArea_ area);
  86.  
  87.    Does the actual killing of a storage area.  */
  88.  
  89. static void
  90. malloc_kill_area_ (mallocPool pool, mallocArea_ a)
  91. {
  92.   mallocSize s = a->size;
  93.  
  94.   assert (strcmp (a->name, ((char *) (a->where)) + s) == 0);
  95.   malloc_kill_ (a->where, s);
  96.   a->next->previous = a->previous;
  97.   a->previous->next = a->next;
  98.   pool->freed += s;
  99.   pool->frees++;
  100.   malloc_kill_ (a,
  101.         offsetof (struct _malloc_area_, name)
  102.         + strlen (a->name) + 1);
  103. }
  104.  
  105. /* malloc_init -- Initialize malloc cluster
  106.  
  107.    malloc_init();
  108.  
  109.    Call malloc_init before you do anything else.  */
  110.  
  111. void
  112. malloc_init ()
  113. {
  114.   if (malloc_reserve_ != NULL)
  115.     return;
  116.   malloc_reserve_ = malloc (20 * 1024);    /* In case of crash, free this first. */
  117.   assert (malloc_reserve_ != NULL);
  118. }
  119.  
  120. /* malloc_pool_display -- Display a pool
  121.  
  122.    mallocPool p;
  123.    malloc_pool_display(p);
  124.  
  125.    Displays information associated with the pool and its subpools.  */
  126.  
  127. void
  128. malloc_pool_display (mallocPool p)
  129. {
  130.   mallocPool q;
  131.   mallocArea_ a;
  132.  
  133.   fprintf (stdout, "Pool \"%s\": bytes allocated=%lu, freed=%lu, old sizes=%lu, new sizes\
  134. =%lu,\n   allocations=%lu, frees=%lu, resizes=%lu, uses=%lu\n   Subpools:\n",
  135.        p->name, p->allocated, p->freed, p->old_sizes, p->new_sizes, p->allocations,
  136.        p->frees, p->resizes, p->uses);
  137.  
  138.   for (q = p->eldest; q != (mallocPool) & p->eldest; q = q->next)
  139.     fprintf (stdout, "      \"%s\"\n", q->name);
  140.  
  141.   fprintf (stdout, "   Storage areas:\n");
  142.  
  143.   for (a = p->first; a != (mallocArea_) & p->first; a = a->next)
  144.     {
  145.       fprintf (stdout, "      ");
  146.       malloc_display_ (a);
  147.     }
  148. }
  149.  
  150. /* malloc_pool_kill -- Destroy a pool
  151.  
  152.    mallocPool p;
  153.    malloc_pool_kill(p);
  154.  
  155.    Releases all storage associated with the pool and its subpools.  */
  156.  
  157. void
  158. malloc_pool_kill (mallocPool p)
  159. {
  160.   mallocPool q;
  161.   mallocArea_ a;
  162.  
  163.   if (--p->uses != 0)
  164.     return;
  165.  
  166. #if 0
  167.   malloc_pool_display (p);
  168. #endif
  169.  
  170.   assert (p->next->previous == p);
  171.   assert (p->previous->next == p);
  172.  
  173.   /* Kill off all the subpools. */
  174.  
  175.   while ((q = p->eldest) != (mallocPool) & p->eldest)
  176.     {
  177.       p->uses = 1;        /* Force the kill. */
  178.       malloc_pool_kill (q);
  179.     }
  180.  
  181.   /* Now free all the storage areas. */
  182.  
  183.   while ((a = p->first) != (mallocArea_) & p->first)
  184.     {
  185.       malloc_kill_area_ (p, a);
  186.     }
  187.  
  188.   /* Now remove from list of sibling pools. */
  189.  
  190.   p->next->previous = p->previous;
  191.   p->previous->next = p->next;
  192.  
  193.   /* Finally, free the pool itself. */
  194.  
  195.   malloc_kill_ (p,
  196.         offsetof (struct _malloc_pool_, name)
  197.         + strlen (p->name) + 1);
  198. }
  199.  
  200. /* malloc_pool_new -- Make a new pool
  201.  
  202.    mallocPool p;
  203.    p = malloc_pool_new("My new pool",malloc_pool_image(),1024);
  204.  
  205.    Makes a new pool with the given name and default new-chunk allocation.  */
  206.  
  207. mallocPool
  208. malloc_pool_new (char *name, mallocPool parent, unsigned long chunks)
  209. {
  210.   mallocPool p;
  211.  
  212.   if (parent == NULL)
  213.     parent = malloc_pool_image ();
  214.  
  215.   p = malloc_new_ (offsetof (struct _malloc_pool_, name) + strlen (name) + 1);
  216.   p->next = (mallocPool) & (parent->eldest);
  217.   p->previous = parent->youngest;
  218.   parent->youngest->next = p;
  219.   parent->youngest = p;
  220.   p->eldest = (mallocPool) & (p->eldest);
  221.   p->youngest = (mallocPool) & (p->eldest);
  222.   p->first = (mallocArea_) & (p->first);
  223.   p->last = (mallocArea_) & (p->first);
  224.   p->allocated = p->freed = p->old_sizes = p->new_sizes = p->allocations
  225.     = p->frees = p->resizes = 0;
  226.   p->uses = 1;
  227.   strcpy (p->name, name);
  228.   return p;
  229. }
  230.  
  231. /* malloc_pool_use -- Use an existing pool
  232.  
  233.    mallocPool p;
  234.    p = malloc_pool_new(pool);
  235.  
  236.    Increments use count for pool; means a matching malloc_pool_kill must
  237.    be performed before a subsequent one will actually kill the pool.  */
  238.  
  239. mallocPool
  240. malloc_pool_use (mallocPool pool)
  241. {
  242.   ++pool->uses;
  243.   return pool;
  244. }
  245.  
  246. /* malloc_display_ -- Display info on a mallocArea_
  247.  
  248.    mallocArea_ a;
  249.    malloc_display_(a);
  250.  
  251.    Simple.  */
  252.  
  253. void
  254. malloc_display_ (mallocArea_ a)
  255. {
  256.   fprintf (stdout, "At %08lX, size=%" mallocSize_f "u, type=%s, \"%s\"\n",
  257.     (unsigned long) a->where, a->size, malloc_types_[a->type], a->name);
  258. }
  259.  
  260. /* malloc_find_inpool_ -- Find mallocArea_ for object in pool
  261.  
  262.    mallocPool pool;
  263.    void *ptr;
  264.    mallocArea_ a;
  265.    a = malloc_find_inpool_(pool,ptr);
  266.  
  267.    Search for object in list of mallocArea_s, die if not found.     */
  268.  
  269. mallocArea_
  270. malloc_find_inpool_ (mallocPool pool, void *ptr)
  271. {
  272.   mallocArea_ a;
  273.   int n = 0;
  274.  
  275.   for (a = pool->first; a != (mallocArea_) & pool->first; a = a->next)
  276.     {
  277.       if (a->where == ptr)
  278.     return a;
  279.       ++n;
  280.     }
  281.   assert ("Couldn't find object in pool!" == NULL);
  282.   return NULL;
  283. }
  284.  
  285. /* malloc_kill_inpool_ -- Kill object
  286.  
  287.    malloc_kill_inpool_(NULL,MALLOC_typeUS_,ptr,size_in_bytes);
  288.  
  289.    Find the mallocArea_ for the pointer, make sure the type is proper, and
  290.    kill both of them.  */
  291.  
  292. void
  293. malloc_kill_inpool_ (mallocPool pool, mallocType_ type, void *ptr, mallocSize s)
  294. {
  295.   mallocArea_ a;
  296.  
  297.   if (pool == NULL)
  298.     pool = malloc_pool_image ();
  299.  
  300.   assert ((pool == malloc_pool_image ())
  301.       || malloc_pool_find_ (pool, malloc_pool_image ()));
  302.  
  303.   a = malloc_find_inpool_ (pool, ptr);
  304.   assert (a->type == type);
  305.   if ((type != MALLOC_typeUS_) && (type != MALLOC_typeUSR_))
  306.     assert (a->size == s);
  307.   malloc_kill_area_ (pool, a);
  308. }
  309.  
  310. /* malloc_new_ -- Allocate new object, die if unable
  311.  
  312.    ptr = malloc_new_(size_in_bytes);
  313.  
  314.    Call malloc, bomb if it returns NULL.  */
  315.  
  316. void *
  317. malloc_new_ (mallocSize s)
  318. {
  319.   void *ptr;
  320.   size_t ss = s;
  321.  
  322.   assert (s == (mallocSize) ss);/* Else alloc is too big for this
  323.                    library/sys. */
  324.   ptr = malloc (ss);
  325.   if (ptr == NULL)
  326.     {
  327.       free (malloc_reserve_);
  328.       assert (ptr != NULL);
  329.     }
  330.   memset (ptr, 126, ss);    /* Catch some kinds of errors more
  331.                    quickly/reliably. */
  332.   return ptr;
  333. }
  334.  
  335. /* malloc_new_inpool_ -- Allocate new object, die if unable
  336.  
  337.    ptr = malloc_new_inpool_(NULL,MALLOC_typeUS_,"object",size_in_bytes);
  338.  
  339.    Allocate the structure and allocate a mallocArea_ to describe it, then
  340.    add it to the list of mallocArea_s for the pool.  */
  341.  
  342. void *
  343. malloc_new_inpool_ (mallocPool pool, mallocType_ type, char *name, mallocSize s)
  344. {
  345.   void *ptr;
  346.   mallocArea_ a;
  347.   unsigned short i;
  348.  
  349.   if (pool == NULL)
  350.     pool = malloc_pool_image ();
  351.  
  352.   assert ((pool == malloc_pool_image ())
  353.       || malloc_pool_find_ (pool, malloc_pool_image ()));
  354.  
  355.   ptr = malloc_new_ (s + (i = strlen (name) + 1));
  356.   strcpy (((char *) (ptr)) + s, name);
  357.   a = malloc_new_ (offsetof (struct _malloc_area_, name) + i);
  358.   switch (type)
  359.     {                /* A little optimization to speed up killing
  360.                    of non-permanent stuff. */
  361.     case MALLOC_typeKP_:
  362.     case MALLOC_typeKPR_:
  363.       a->next = (mallocArea_) & pool->first;
  364.       break;
  365.  
  366.     default:
  367.       a->next = pool->first;
  368.       break;
  369.     }
  370.   a->previous = a->next->previous;
  371.   a->next->previous = a;
  372.   a->previous->next = a;
  373.   a->where = ptr;
  374.   a->size = s;
  375.   a->type = type;
  376.   strcpy (a->name, name);
  377.   pool->allocated += s;
  378.   pool->allocations++;
  379.   return ptr;
  380. }
  381.  
  382. /* malloc_new_zinpool_ -- Allocate new zeroed object, die if unable
  383.  
  384.    ptr = malloc_new_zinpool_(NULL,MALLOC_typeUS_,"object",size_in_bytes,0);
  385.  
  386.    Like malloc_new_inpool_, but zeros out all the bytes in the area (assuming
  387.    you pass it a 0).  */
  388.  
  389. void *
  390. malloc_new_zinpool_ (mallocPool pool, mallocType_ type, char *name, mallocSize s,
  391.              int z)
  392. {
  393.   void *ptr;
  394.  
  395.   ptr = malloc_new_inpool_ (pool, type, name, s);
  396.   memset (ptr, z, s);
  397.   return ptr;
  398. }
  399.  
  400. /* malloc_pool_find_ -- See if pool is a descendant of another pool
  401.  
  402.    if (malloc_pool_find_(target_pool,parent_pool)) ...;
  403.  
  404.    Recursive descent on each of the children of the parent pool, after
  405.    first checking the children themselves.  */
  406.  
  407. char
  408. malloc_pool_find_ (mallocPool pool, mallocPool parent)
  409. {
  410.   mallocPool p;
  411.  
  412.   for (p = parent->eldest; p != (mallocPool) & parent->eldest; p = p->next)
  413.     {
  414.       if ((p == pool) || malloc_pool_find_ (pool, p))
  415.     return 1;
  416.     }
  417.   return 0;
  418. }
  419.  
  420. /* malloc_resize_inpool_ -- Resize existing object in pool
  421.  
  422.    ptr = malloc_resize_inpool_(NULL,MALLOC_typeUSR_,ptr,new_size,old_size);
  423.  
  424.    Find the object's mallocArea_, check it out, then do the resizing.  */
  425.  
  426. void *
  427. malloc_resize_inpool_ (mallocPool pool, mallocType_ type, void *ptr,
  428.                mallocSize ns, mallocSize os)
  429. {
  430.   mallocArea_ a;
  431.  
  432.   if (pool == NULL)
  433.     pool = malloc_pool_image ();
  434.  
  435.   assert ((pool == malloc_pool_image ())
  436.       || malloc_pool_find_ (pool, malloc_pool_image ()));
  437.  
  438.   a = malloc_find_inpool_ (pool, ptr);
  439.   assert (a->type == type);
  440.   if ((type == MALLOC_typeKSR_) || (type == MALLOC_typeKPR_))
  441.     assert (a->size == os);
  442.   assert (strcmp (a->name, ((char *) (ptr)) + os) == 0);
  443.   ptr = malloc_resize_ (ptr, ns + strlen (a->name) + 1);
  444.   a->where = ptr;
  445.   a->size = ns;
  446.   strcpy (((char *) (ptr)) + ns, a->name);
  447.   pool->old_sizes += os;
  448.   pool->new_sizes += ns;
  449.   pool->resizes++;
  450.   return ptr;
  451. }
  452.  
  453. /* malloc_resize_ -- Reallocate object, die if unable
  454.  
  455.    ptr = malloc_resize_(ptr,size_in_bytes);
  456.  
  457.    Call realloc, bomb if it returns NULL.  */
  458.  
  459. void *
  460. malloc_resize_ (void *ptr, mallocSize s)
  461. {
  462.   size_t ss = s;
  463.  
  464.   assert (s == (mallocSize) ss);/* Too big if failure here. */
  465.  
  466.   ptr = realloc (ptr, ss);
  467.   if (ptr == NULL)
  468.     {
  469.       free (malloc_reserve_);
  470.       assert (ptr != NULL);
  471.     }
  472.   return ptr;
  473. }
  474.