home *** CD-ROM | disk | FTP | other *** search
/ IRIS Development Option 6.2 / IRIS_Development_Option_6.2_814-0478-001.iso / dist / c_dev.idb / usr / share / src / customalloc / Record.c.z / Record.c
C/C++ Source or Header  |  1996-03-14  |  6KB  |  303 lines

  1. #include <stdio.h>
  2. #include <assert.h>
  3. #include <sys/types.h>
  4. #include <unistd.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7.  
  8. static CacheItem *Root = 0;
  9.  
  10. static unsigned int max(unsigned int a, unsigned int b)
  11. {
  12.   if (a > b ) return(a); else return(b);
  13. }
  14.  
  15. static unsigned int min(unsigned int a, unsigned int b)
  16. {
  17.   if (a > b ) return(b); else return(a);
  18. }
  19.  
  20. /*
  21.  * Allocates and initializes a new CacheItem
  22.  */
  23. int TotalEvents = 0;
  24.  
  25. static CacheItem *cache_new(int size, CacheItem *next)
  26. {
  27.   CacheItem *item = (CacheItem *) __internal_malloc(sizeof(CacheItem));
  28.   memset(item, 0, sizeof(CacheItem) );
  29.   item -> size = size;
  30.   item -> next = next;
  31.   item -> last_event = TotalEvents;
  32.   return( item );
  33. }
  34.  
  35. static update_sums(CacheItem *item)
  36. {
  37.   double delta = (TotalEvents - item -> last_event);
  38.   item -> sum_objects_in_free_list += delta * item -> objects_in_free_list;
  39.   item -> sum_objects_in_use += delta * item -> objects_in_use;
  40.   item -> last_event = TotalEvents;
  41. }
  42.  
  43. /*
  44.  * Takes an adjusted size, returns the adjusted CacheItem and moves
  45.  * the CacheItem to the front
  46.  */
  47. static CacheItem *cache_find(int size)
  48. {
  49.   CacheItem *prior = 0;
  50.   CacheItem *item;
  51.  
  52.   assert (size >= 0 );
  53.  
  54.   for (item = Root; item != 0; item = item -> next) {
  55.     if ( item -> size ==  size ) {
  56.       if ( prior != 0 ) {
  57.  
  58.     /* unlink */
  59.  
  60.     prior -> next = item -> next;
  61.     
  62.     /* relink */
  63.     item -> next = Root;
  64.     Root = item;
  65.       }
  66.       return (item);
  67.     }
  68.     prior = item;
  69.   }
  70.   Root = cache_new(size, Root);
  71.   return( Root );
  72. }
  73.  
  74. /*
  75.  * Check that an address is valid
  76.  */
  77. static unsigned int trap_address = 0x0;
  78. static valid_address(void *xx)
  79. {
  80. #if _DEBUG_
  81.   unsigned int x = (unsigned int) xx;
  82. #if 0
  83.   static unsigned int foo = 0x0ff00000;
  84.   extern int end;    
  85.   static unsigned int end_addr = (unsigned int) &end;
  86. #else
  87.   static unsigned int foo = 0xffffffff;
  88.   static unsigned int end_addr = (unsigned int) &Root;
  89. #endif
  90.   
  91.   if ( x != 0 ) {      
  92.     assert (  x >  end_addr );
  93.     assert (  x !=  trap_address );
  94.     assert (  x <  foo );
  95.   } 
  96. #endif
  97. }
  98.  
  99. /*
  100.  * Adds a MallocChunk to a CacheItem
  101.  */
  102. static void cache_enq(CacheItem *item, MallocChunk *store)
  103. {
  104.   valid_address( (void *)store);
  105.   valid_address( (void *)item);
  106.   valid_address( (void *)item->root);
  107.  
  108.   store -> fd = item -> root;
  109.   item -> root = store;
  110.  
  111. #ifndef _IGNORE_COUNTS_
  112.   item -> objects_in_free_list += 1;
  113.   item -> max_objects_in_free_list = max(item -> max_objects_in_free_list,
  114.                      item -> objects_in_free_list);
  115.   update_sums(item);
  116. #endif
  117.  
  118.   valid_address( (void *)item);
  119.   valid_address( (void *)item->root);
  120. }
  121.  
  122. /*
  123.  * Removes a MallocChunk from a CacheItem
  124.  */
  125. static MallocChunk* cache_deq(CacheItem *item)
  126. {
  127.   MallocChunk *store;
  128.  
  129.   valid_address( (void *)item);
  130.   valid_address( (void *)item->root);
  131.  
  132.   store = item -> root;
  133.   item -> root = store -> fd;
  134.  
  135. #ifndef _IGNORE_COUNTS_
  136.   item -> objects_in_free_list -= 1;
  137.   item -> sum_objects_in_free_list += item -> objects_in_free_list;
  138.   update_sums(item);
  139. #endif
  140.  
  141.   valid_address( (void *)item);
  142.   valid_address( (void *)item->root);
  143.   valid_address( (void *)store);
  144.  
  145.   return( store );
  146. }
  147.  
  148.  
  149.  
  150. static int __cache_malloc_initialized__ = 0;
  151.  
  152. static void __cache_exit()
  153. {
  154.   CacheItem *item;
  155.   for (item = Root; item != 0; item = item -> next) {
  156.     update_sums(item);
  157.   }
  158.   customalloc_write_database(Root);
  159. }
  160.  
  161. static void __cache_malloc_initialize()
  162. {
  163.   __cache_malloc_initialized__ = 1;
  164.   Root = customalloc_read_database();
  165.   atexit(__cache_exit); 
  166. }
  167.  
  168.  
  169.  
  170. MallocPtrType malloc(MallocArgType size)
  171. {
  172.   int adjusted_size;
  173.   CacheItem *item;
  174.   void *return_value;
  175.   
  176.   TotalEvents++;
  177.   
  178.   if (size == 0) {
  179.     /*
  180.      * Record occurance of 0-sized item...
  181.      */
  182.     item = cache_find( 0 ); 
  183.     item -> mallocs += 1;
  184.     size = CUSTOMALLOC_CACHE_VALUE;
  185.   }
  186.   assert( size > 0 );
  187.   
  188.   if ( ! __cache_malloc_initialized__ ) {
  189.     __cache_malloc_initialize();
  190.   }
  191.   
  192.   adjusted_size = size_external_to_internal( size );
  193.   
  194.   item = cache_find( adjusted_size );
  195.   
  196. #ifndef _IGNORE_COUNTS_
  197.   item -> mallocs += 1;
  198.   item -> objects_in_use += 1;
  199.   item -> max_objects_in_use= max(item -> max_objects_in_use,
  200.                   item -> objects_in_use);
  201.   update_sums(item);
  202. #endif
  203.   
  204.   if ( item -> root ) {
  205.     return_value = (void *) malloc_to_external( cache_deq(item) );
  206.   } else {
  207.     return_value = (void *) __internal_malloc( adjusted_size );
  208.   }
  209.   valid_address( (void *)return_value);
  210.   
  211.   if ( return_value == 0 ) { 
  212.     static  char *argle = "Out of memory!\n";
  213.     write(2,argle,strlen(argle));
  214.     abort();
  215.   }
  216.   
  217.   return ( return_value );
  218. }
  219.  
  220. /*
  221.  * We're inefficient about this in order to gather malloc stats..
  222.  */ 
  223.  
  224. void* realloc(void* mem, unsigned int bytes)
  225. {
  226.  
  227.  if ( mem == 0 ) {
  228.     /*
  229.      * Some people do the weirdest things.
  230.      */
  231.     return( (void *) malloc(bytes) );
  232.   } else {
  233.     MallocChunk *chunk = external_to_malloc(mem);
  234.     int data_size = size_malloc_to_internal(malloc_size(chunk));
  235.     int copy_size = (data_size < bytes) ? data_size : bytes;
  236.     void *newmem = malloc(bytes);
  237.     bcopy(mem, newmem, copy_size );
  238.     free(mem);
  239.     return( newmem );
  240.   }
  241. }
  242.  
  243.  
  244. FreeRetType free(FreePtrType  p)
  245. {
  246.   TotalEvents++;
  247.   
  248.   valid_address( (void *)p);
  249.   
  250.   if ( p ) {
  251.     MallocChunk *chunk = external_to_malloc(p);
  252.     int adjusted_size =
  253.       size_malloc_to_internal(malloc_size(chunk) - (2 * SIZE_SZ) );
  254.     
  255.     CacheItem *item;
  256.     
  257.     assert( adjusted_size > 0 );
  258.     
  259.     item = cache_find( adjusted_size );
  260.  
  261.     valid_address( (void *)item);
  262.     valid_address( (void *)item->root);
  263.     valid_address( (void *) chunk );
  264. #ifndef _IGNORE_COUNTS_
  265.     item -> objects_in_use -= 1;
  266.     item -> sum_objects_in_use += item -> objects_in_use;
  267.     item -> frees += 1;
  268.     update_sums(item);
  269. #endif
  270.     cache_enq(item, chunk);
  271.   }
  272. }
  273.  
  274. static sanity_check(mchunkptr p, int size)
  275. {
  276. #if _DEBUG_
  277.   /* a quick sanity check */
  278.   unsigned int sz = p -> size & ~0x1;
  279.   if ( size > 0 ) {
  280.     if (sz != size || sz != *((int*)((char*)(p) + sz - SIZE_SZ)))
  281.       malloc_user_error();
  282.   } else {
  283.     if (sz != *((int*)((char*)(p) + sz - SIZE_SZ)))
  284.       malloc_user_error();
  285.   }
  286. #endif
  287. }
  288.  
  289.  
  290. void
  291. check_user(void *p, int s)
  292. {
  293.   MallocChunk *chunk = external_to_malloc(p);
  294.   unsigned foo = malloc_size(chunk);
  295.  
  296.   assert( size_malloc_to_internal(foo) >= size_malloc_to_internal(s) );
  297.  
  298.   assert( (foo - (2 * SIZE_SZ)) >= s );
  299.  
  300.   sanity_check( (mchunkptr)chunk, 0 );
  301. }
  302.  
  303.