glib/tests/memchunks.c
changeset 18 47c74d1534e1
equal deleted inserted replaced
0:e4d67989cc36 18:47c74d1534e1
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  * Portions copyright (c) 2009 Nokia Corporation.  All rights reserved.
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Lesser General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Lesser General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Lesser General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /*
       
    21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    22  * file for a list of people on the GLib Team.  See the ChangeLog
       
    23  * files for a list of changes.  These files are distributed with
       
    24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    25  */
       
    26 
       
    27 /* 
       
    28  * MT safe
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 
       
    33 #include <stdlib.h>
       
    34 #include <string.h>
       
    35 #include <signal.h>
       
    36 
       
    37 #include "glib.h"
       
    38 
       
    39 #ifdef __SYMBIAN32__
       
    40 #include <glib_global.h>
       
    41 #endif//__SYMBIAN32__
       
    42 
       
    43 /* notes on macros:
       
    44  * if ENABLE_GC_FRIENDLY is defined, freed memory should be 0-wiped.
       
    45  */
       
    46 
       
    47 #define MEM_PROFILE_TABLE_SIZE 4096
       
    48 
       
    49 #define MEM_AREA_SIZE 4L
       
    50 
       
    51 static guint mem_chunk_recursion = 0;
       
    52 #  define MEM_CHUNK_ROUTINE_COUNT()	(mem_chunk_recursion)
       
    53 #  define ENTER_MEM_CHUNK_ROUTINE()	(mem_chunk_recursion = MEM_CHUNK_ROUTINE_COUNT () + 1)
       
    54 #  define LEAVE_MEM_CHUNK_ROUTINE()	(mem_chunk_recursion = MEM_CHUNK_ROUTINE_COUNT () - 1)
       
    55 
       
    56 /* --- old memchunk prototypes --- */
       
    57 void            old_mem_chunks_init     (void);
       
    58 GMemChunk*      old_mem_chunk_new       (const gchar  *name,
       
    59                                          gint          atom_size,
       
    60                                          gulong        area_size,
       
    61                                          gint          type);
       
    62 void            old_mem_chunk_destroy   (GMemChunk *mem_chunk);
       
    63 gpointer        old_mem_chunk_alloc     (GMemChunk *mem_chunk);
       
    64 gpointer        old_mem_chunk_alloc0    (GMemChunk *mem_chunk);
       
    65 void            old_mem_chunk_free      (GMemChunk *mem_chunk,
       
    66                                          gpointer   mem);
       
    67 void            old_mem_chunk_clean     (GMemChunk *mem_chunk);
       
    68 void            old_mem_chunk_reset     (GMemChunk *mem_chunk);
       
    69 void            old_mem_chunk_print     (GMemChunk *mem_chunk);
       
    70 void            old_mem_chunk_info      (void);
       
    71 
       
    72 
       
    73 /* --- MemChunks --- */
       
    74 #ifndef G_ALLOC_AND_FREE
       
    75 typedef struct _GAllocator GAllocator;
       
    76 typedef struct _GMemChunk  GMemChunk;
       
    77 #define G_ALLOC_ONLY	  1
       
    78 #define G_ALLOC_AND_FREE  2
       
    79 #endif
       
    80 
       
    81 typedef struct _GFreeAtom      GFreeAtom;
       
    82 typedef struct _GMemArea       GMemArea;
       
    83 
       
    84 struct _GFreeAtom
       
    85 {
       
    86   GFreeAtom *next;
       
    87 };
       
    88 
       
    89 struct _GMemArea
       
    90 {
       
    91   GMemArea *next;            /* the next mem area */
       
    92   GMemArea *prev;            /* the previous mem area */
       
    93   gulong index;              /* the current index into the "mem" array */
       
    94   gulong free;               /* the number of free bytes in this mem area */
       
    95   gulong allocated;          /* the number of atoms allocated from this area */
       
    96   gulong mark;               /* is this mem area marked for deletion */
       
    97   gchar mem[MEM_AREA_SIZE];  /* the mem array from which atoms get allocated
       
    98 			      * the actual size of this array is determined by
       
    99 			      *  the mem chunk "area_size". ANSI says that it
       
   100 			      *  must be declared to be the maximum size it
       
   101 			      *  can possibly be (even though the actual size
       
   102 			      *  may be less).
       
   103 			      */
       
   104 };
       
   105 
       
   106 struct _GMemChunk
       
   107 {
       
   108   const gchar *name;         /* name of this MemChunk...used for debugging output */
       
   109   gint type;                 /* the type of MemChunk: ALLOC_ONLY or ALLOC_AND_FREE */
       
   110   gint num_mem_areas;        /* the number of memory areas */
       
   111   gint num_marked_areas;     /* the number of areas marked for deletion */
       
   112   guint atom_size;           /* the size of an atom */
       
   113   gulong area_size;          /* the size of a memory area */
       
   114   GMemArea *mem_area;        /* the current memory area */
       
   115   GMemArea *mem_areas;       /* a list of all the mem areas owned by this chunk */
       
   116   GMemArea *free_mem_area;   /* the free area...which is about to be destroyed */
       
   117   GFreeAtom *free_atoms;     /* the free atoms list */
       
   118   GTree *mem_tree;           /* tree of mem areas sorted by memory address */
       
   119   GMemChunk *next;           /* pointer to the next chunk */
       
   120   GMemChunk *prev;           /* pointer to the previous chunk */
       
   121 };
       
   122 
       
   123 
       
   124 static gulong old_mem_chunk_compute_size (gulong    size,
       
   125                                           gulong    min_size) G_GNUC_CONST;
       
   126 static gint   old_mem_chunk_area_compare (GMemArea *a,
       
   127                                           GMemArea *b);
       
   128 static gint   old_mem_chunk_area_search  (GMemArea *a,
       
   129                                           gchar    *addr);
       
   130 
       
   131 /* here we can't use StaticMutexes, as they depend upon a working
       
   132  * g_malloc, the same holds true for StaticPrivate
       
   133  */
       
   134 static GMutex        *mem_chunks_lock = NULL;
       
   135 static GMemChunk     *mem_chunks = NULL;
       
   136 
       
   137 void
       
   138 old_mem_chunks_init (void)
       
   139 {
       
   140   mem_chunks_lock = g_mutex_new ();
       
   141 }
       
   142 
       
   143 GMemChunk*
       
   144 old_mem_chunk_new (const gchar  *name,
       
   145                    gint          atom_size,
       
   146                    gulong        area_size,
       
   147                    gint          type)
       
   148 {
       
   149   GMemChunk *mem_chunk;
       
   150   gulong rarea_size;
       
   151   
       
   152   g_return_val_if_fail (atom_size > 0, NULL);
       
   153   g_return_val_if_fail (area_size >= atom_size, NULL);
       
   154   
       
   155   ENTER_MEM_CHUNK_ROUTINE ();
       
   156   
       
   157   area_size = (area_size + atom_size - 1) / atom_size;
       
   158   area_size *= atom_size;
       
   159   
       
   160   mem_chunk = g_new (GMemChunk, 1);
       
   161   mem_chunk->name = name;
       
   162   mem_chunk->type = type;
       
   163   mem_chunk->num_mem_areas = 0;
       
   164   mem_chunk->num_marked_areas = 0;
       
   165   mem_chunk->mem_area = NULL;
       
   166   mem_chunk->free_mem_area = NULL;
       
   167   mem_chunk->free_atoms = NULL;
       
   168   mem_chunk->mem_tree = NULL;
       
   169   mem_chunk->mem_areas = NULL;
       
   170   mem_chunk->atom_size = atom_size;
       
   171   
       
   172   if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   173     mem_chunk->mem_tree = g_tree_new ((GCompareFunc) old_mem_chunk_area_compare);
       
   174   
       
   175   if (mem_chunk->atom_size % G_MEM_ALIGN)
       
   176     mem_chunk->atom_size += G_MEM_ALIGN - (mem_chunk->atom_size % G_MEM_ALIGN);
       
   177   
       
   178   rarea_size = area_size + sizeof (GMemArea) - MEM_AREA_SIZE;
       
   179   rarea_size = old_mem_chunk_compute_size (rarea_size, atom_size + sizeof (GMemArea) - MEM_AREA_SIZE);
       
   180   mem_chunk->area_size = rarea_size - (sizeof (GMemArea) - MEM_AREA_SIZE);
       
   181   
       
   182   g_mutex_lock (mem_chunks_lock);
       
   183   mem_chunk->next = mem_chunks;
       
   184   mem_chunk->prev = NULL;
       
   185   if (mem_chunks)
       
   186     mem_chunks->prev = mem_chunk;
       
   187   mem_chunks = mem_chunk;
       
   188   g_mutex_unlock (mem_chunks_lock);
       
   189   
       
   190   LEAVE_MEM_CHUNK_ROUTINE ();
       
   191   
       
   192   return mem_chunk;
       
   193 }
       
   194 
       
   195 void
       
   196 old_mem_chunk_destroy (GMemChunk *mem_chunk)
       
   197 {
       
   198   GMemArea *mem_areas;
       
   199   GMemArea *temp_area;
       
   200   
       
   201   g_return_if_fail (mem_chunk != NULL);
       
   202   
       
   203   ENTER_MEM_CHUNK_ROUTINE ();
       
   204   
       
   205   mem_areas = mem_chunk->mem_areas;
       
   206   while (mem_areas)
       
   207     {
       
   208       temp_area = mem_areas;
       
   209       mem_areas = mem_areas->next;
       
   210       g_free (temp_area);
       
   211     }
       
   212   
       
   213   g_mutex_lock (mem_chunks_lock);
       
   214   if (mem_chunk->next)
       
   215     mem_chunk->next->prev = mem_chunk->prev;
       
   216   if (mem_chunk->prev)
       
   217     mem_chunk->prev->next = mem_chunk->next;
       
   218   
       
   219   if (mem_chunk == mem_chunks)
       
   220     mem_chunks = mem_chunks->next;
       
   221   g_mutex_unlock (mem_chunks_lock);
       
   222   
       
   223   if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   224     g_tree_destroy (mem_chunk->mem_tree);  
       
   225   
       
   226   g_free (mem_chunk);
       
   227   
       
   228   LEAVE_MEM_CHUNK_ROUTINE ();
       
   229 }
       
   230 
       
   231 gpointer
       
   232 old_mem_chunk_alloc (GMemChunk *mem_chunk)
       
   233 {
       
   234   GMemArea *temp_area;
       
   235   gpointer mem;
       
   236   
       
   237   ENTER_MEM_CHUNK_ROUTINE ();
       
   238   
       
   239   g_return_val_if_fail (mem_chunk != NULL, NULL);
       
   240   
       
   241   while (mem_chunk->free_atoms)
       
   242     {
       
   243       /* Get the first piece of memory on the "free_atoms" list.
       
   244        * We can go ahead and destroy the list node we used to keep
       
   245        *  track of it with and to update the "free_atoms" list to
       
   246        *  point to its next element.
       
   247        */
       
   248       mem = mem_chunk->free_atoms;
       
   249       mem_chunk->free_atoms = mem_chunk->free_atoms->next;
       
   250       
       
   251       /* Determine which area this piece of memory is allocated from */
       
   252       temp_area = g_tree_search (mem_chunk->mem_tree,
       
   253 				 (GCompareFunc) old_mem_chunk_area_search,
       
   254 				 mem);
       
   255       
       
   256       /* If the area has been marked, then it is being destroyed.
       
   257        *  (ie marked to be destroyed).
       
   258        * We check to see if all of the segments on the free list that
       
   259        *  reference this area have been removed. This occurs when
       
   260        *  the ammount of free memory is less than the allocatable size.
       
   261        * If the chunk should be freed, then we place it in the "free_mem_area".
       
   262        * This is so we make sure not to free the mem area here and then
       
   263        *  allocate it again a few lines down.
       
   264        * If we don't allocate a chunk a few lines down then the "free_mem_area"
       
   265        *  will be freed.
       
   266        * If there is already a "free_mem_area" then we'll just free this mem area.
       
   267        */
       
   268       if (temp_area->mark)
       
   269         {
       
   270           /* Update the "free" memory available in that area */
       
   271           temp_area->free += mem_chunk->atom_size;
       
   272 	  
       
   273           if (temp_area->free == mem_chunk->area_size)
       
   274             {
       
   275               if (temp_area == mem_chunk->mem_area)
       
   276                 mem_chunk->mem_area = NULL;
       
   277 	      
       
   278               if (mem_chunk->free_mem_area)
       
   279                 {
       
   280                   mem_chunk->num_mem_areas -= 1;
       
   281 		  
       
   282                   if (temp_area->next)
       
   283                     temp_area->next->prev = temp_area->prev;
       
   284                   if (temp_area->prev)
       
   285                     temp_area->prev->next = temp_area->next;
       
   286                   if (temp_area == mem_chunk->mem_areas)
       
   287                     mem_chunk->mem_areas = mem_chunk->mem_areas->next;
       
   288 		  
       
   289 		  if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   290 		    g_tree_remove (mem_chunk->mem_tree, temp_area);
       
   291                   g_free (temp_area);
       
   292                 }
       
   293               else
       
   294                 mem_chunk->free_mem_area = temp_area;
       
   295 	      
       
   296 	      mem_chunk->num_marked_areas -= 1;
       
   297 	    }
       
   298 	}
       
   299       else
       
   300         {
       
   301           /* Update the number of allocated atoms count.
       
   302 	   */
       
   303           temp_area->allocated += 1;
       
   304 	  
       
   305           /* The area wasn't marked...return the memory
       
   306 	   */
       
   307 	  goto outa_here;
       
   308         }
       
   309     }
       
   310   
       
   311   /* If there isn't a current mem area or the current mem area is out of space
       
   312    *  then allocate a new mem area. We'll first check and see if we can use
       
   313    *  the "free_mem_area". Otherwise we'll just malloc the mem area.
       
   314    */
       
   315   if ((!mem_chunk->mem_area) ||
       
   316       ((mem_chunk->mem_area->index + mem_chunk->atom_size) > mem_chunk->area_size))
       
   317     {
       
   318       if (mem_chunk->free_mem_area)
       
   319         {
       
   320           mem_chunk->mem_area = mem_chunk->free_mem_area;
       
   321 	  mem_chunk->free_mem_area = NULL;
       
   322         }
       
   323       else
       
   324         {
       
   325 #ifdef ENABLE_GC_FRIENDLY
       
   326 	  mem_chunk->mem_area = (GMemArea*) g_malloc0 (sizeof (GMemArea) -
       
   327 						       MEM_AREA_SIZE +
       
   328 						       mem_chunk->area_size); 
       
   329 #else /* !ENABLE_GC_FRIENDLY */
       
   330 	  mem_chunk->mem_area = (GMemArea*) g_malloc (sizeof (GMemArea) -
       
   331 						      MEM_AREA_SIZE +
       
   332 						      mem_chunk->area_size);
       
   333 #endif /* ENABLE_GC_FRIENDLY */
       
   334 	  
       
   335 	  mem_chunk->num_mem_areas += 1;
       
   336 	  mem_chunk->mem_area->next = mem_chunk->mem_areas;
       
   337 	  mem_chunk->mem_area->prev = NULL;
       
   338 	  
       
   339 	  if (mem_chunk->mem_areas)
       
   340 	    mem_chunk->mem_areas->prev = mem_chunk->mem_area;
       
   341 	  mem_chunk->mem_areas = mem_chunk->mem_area;
       
   342 	  
       
   343 	  if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   344 	    g_tree_insert (mem_chunk->mem_tree, mem_chunk->mem_area, mem_chunk->mem_area);
       
   345         }
       
   346       
       
   347       mem_chunk->mem_area->index = 0;
       
   348       mem_chunk->mem_area->free = mem_chunk->area_size;
       
   349       mem_chunk->mem_area->allocated = 0;
       
   350       mem_chunk->mem_area->mark = 0;
       
   351     }
       
   352   
       
   353   /* Get the memory and modify the state variables appropriately.
       
   354    */
       
   355   mem = (gpointer) &mem_chunk->mem_area->mem[mem_chunk->mem_area->index];
       
   356   mem_chunk->mem_area->index += mem_chunk->atom_size;
       
   357   mem_chunk->mem_area->free -= mem_chunk->atom_size;
       
   358   mem_chunk->mem_area->allocated += 1;
       
   359   
       
   360  outa_here:
       
   361   
       
   362   LEAVE_MEM_CHUNK_ROUTINE ();
       
   363   
       
   364   return mem;
       
   365 }
       
   366 
       
   367 gpointer
       
   368 old_mem_chunk_alloc0 (GMemChunk *mem_chunk)
       
   369 {
       
   370   gpointer mem;
       
   371   
       
   372   mem = old_mem_chunk_alloc (mem_chunk);
       
   373   if (mem)
       
   374     {
       
   375       memset (mem, 0, mem_chunk->atom_size);
       
   376     }
       
   377   
       
   378   return mem;
       
   379 }
       
   380 
       
   381 void
       
   382 old_mem_chunk_free (GMemChunk *mem_chunk,
       
   383                     gpointer   mem)
       
   384 {
       
   385   GMemArea *temp_area;
       
   386   GFreeAtom *free_atom;
       
   387   
       
   388   g_return_if_fail (mem_chunk != NULL);
       
   389   g_return_if_fail (mem != NULL);
       
   390   
       
   391   ENTER_MEM_CHUNK_ROUTINE ();
       
   392   
       
   393 #ifdef ENABLE_GC_FRIENDLY
       
   394   memset (mem, 0, mem_chunk->atom_size);
       
   395 #endif /* ENABLE_GC_FRIENDLY */
       
   396   
       
   397   /* Don't do anything if this is an ALLOC_ONLY chunk
       
   398    */
       
   399   if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   400     {
       
   401       /* Place the memory on the "free_atoms" list
       
   402        */
       
   403       free_atom = (GFreeAtom*) mem;
       
   404       free_atom->next = mem_chunk->free_atoms;
       
   405       mem_chunk->free_atoms = free_atom;
       
   406       
       
   407       temp_area = g_tree_search (mem_chunk->mem_tree,
       
   408 				 (GCompareFunc) old_mem_chunk_area_search,
       
   409 				 mem);
       
   410       
       
   411       temp_area->allocated -= 1;
       
   412       
       
   413       if (temp_area->allocated == 0)
       
   414 	{
       
   415 	  temp_area->mark = 1;
       
   416 	  mem_chunk->num_marked_areas += 1;
       
   417 	}
       
   418     }
       
   419   
       
   420   LEAVE_MEM_CHUNK_ROUTINE ();
       
   421 }
       
   422 
       
   423 /* This doesn't free the free_area if there is one */
       
   424 void
       
   425 old_mem_chunk_clean (GMemChunk *mem_chunk)
       
   426 {
       
   427   GMemArea *mem_area;
       
   428   GFreeAtom *prev_free_atom;
       
   429   GFreeAtom *temp_free_atom;
       
   430   gpointer mem;
       
   431   
       
   432   g_return_if_fail (mem_chunk != NULL);
       
   433   
       
   434   ENTER_MEM_CHUNK_ROUTINE ();
       
   435   
       
   436   if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   437     {
       
   438       prev_free_atom = NULL;
       
   439       temp_free_atom = mem_chunk->free_atoms;
       
   440       
       
   441       while (temp_free_atom)
       
   442 	{
       
   443 	  mem = (gpointer) temp_free_atom;
       
   444 	  
       
   445 	  mem_area = g_tree_search (mem_chunk->mem_tree,
       
   446 				    (GCompareFunc) old_mem_chunk_area_search,
       
   447 				    mem);
       
   448 	  
       
   449           /* If this mem area is marked for destruction then delete the
       
   450 	   *  area and list node and decrement the free mem.
       
   451            */
       
   452 	  if (mem_area->mark)
       
   453 	    {
       
   454 	      if (prev_free_atom)
       
   455 		prev_free_atom->next = temp_free_atom->next;
       
   456 	      else
       
   457 		mem_chunk->free_atoms = temp_free_atom->next;
       
   458 	      temp_free_atom = temp_free_atom->next;
       
   459 	      
       
   460 	      mem_area->free += mem_chunk->atom_size;
       
   461 	      if (mem_area->free == mem_chunk->area_size)
       
   462 		{
       
   463 		  mem_chunk->num_mem_areas -= 1;
       
   464 		  mem_chunk->num_marked_areas -= 1;
       
   465 		  
       
   466 		  if (mem_area->next)
       
   467 		    mem_area->next->prev = mem_area->prev;
       
   468 		  if (mem_area->prev)
       
   469 		    mem_area->prev->next = mem_area->next;
       
   470 		  if (mem_area == mem_chunk->mem_areas)
       
   471 		    mem_chunk->mem_areas = mem_chunk->mem_areas->next;
       
   472 		  if (mem_area == mem_chunk->mem_area)
       
   473 		    mem_chunk->mem_area = NULL;
       
   474 		  
       
   475 		  if (mem_chunk->type == G_ALLOC_AND_FREE)
       
   476 		    g_tree_remove (mem_chunk->mem_tree, mem_area);
       
   477 		  g_free (mem_area);
       
   478 		}
       
   479 	    }
       
   480 	  else
       
   481 	    {
       
   482 	      prev_free_atom = temp_free_atom;
       
   483 	      temp_free_atom = temp_free_atom->next;
       
   484 	    }
       
   485 	}
       
   486     }
       
   487   LEAVE_MEM_CHUNK_ROUTINE ();
       
   488 }
       
   489 
       
   490 void
       
   491 old_mem_chunk_reset (GMemChunk *mem_chunk)
       
   492 {
       
   493   GMemArea *mem_areas;
       
   494   GMemArea *temp_area;
       
   495   
       
   496   g_return_if_fail (mem_chunk != NULL);
       
   497   
       
   498   ENTER_MEM_CHUNK_ROUTINE ();
       
   499   
       
   500   mem_areas = mem_chunk->mem_areas;
       
   501   mem_chunk->num_mem_areas = 0;
       
   502   mem_chunk->mem_areas = NULL;
       
   503   mem_chunk->mem_area = NULL;
       
   504   
       
   505   while (mem_areas)
       
   506     {
       
   507       temp_area = mem_areas;
       
   508       mem_areas = mem_areas->next;
       
   509       g_free (temp_area);
       
   510     }
       
   511   
       
   512   mem_chunk->free_atoms = NULL;
       
   513   
       
   514   if (mem_chunk->mem_tree)
       
   515     {
       
   516       g_tree_destroy (mem_chunk->mem_tree);
       
   517       mem_chunk->mem_tree = g_tree_new ((GCompareFunc) old_mem_chunk_area_compare);
       
   518     }
       
   519   
       
   520   LEAVE_MEM_CHUNK_ROUTINE ();
       
   521 }
       
   522 
       
   523 void
       
   524 old_mem_chunk_print (GMemChunk *mem_chunk)
       
   525 {
       
   526   GMemArea *mem_areas;
       
   527   gulong mem;
       
   528   
       
   529   g_return_if_fail (mem_chunk != NULL);
       
   530   
       
   531   mem_areas = mem_chunk->mem_areas;
       
   532   mem = 0;
       
   533   
       
   534   while (mem_areas)
       
   535     {
       
   536       mem += mem_chunk->area_size - mem_areas->free;
       
   537       mem_areas = mem_areas->next;
       
   538     }
       
   539   
       
   540   g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
       
   541 	 "%s: %ld bytes using %d mem areas",
       
   542 	 mem_chunk->name, mem, mem_chunk->num_mem_areas);
       
   543 }
       
   544 
       
   545 void
       
   546 old_mem_chunk_info (void)
       
   547 {
       
   548   GMemChunk *mem_chunk;
       
   549   gint count;
       
   550   
       
   551   count = 0;
       
   552   g_mutex_lock (mem_chunks_lock);
       
   553   mem_chunk = mem_chunks;
       
   554   while (mem_chunk)
       
   555     {
       
   556       count += 1;
       
   557       mem_chunk = mem_chunk->next;
       
   558     }
       
   559   g_mutex_unlock (mem_chunks_lock);
       
   560   
       
   561   g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%d mem chunks", count);
       
   562   
       
   563   g_mutex_lock (mem_chunks_lock);
       
   564   mem_chunk = mem_chunks;
       
   565   g_mutex_unlock (mem_chunks_lock);
       
   566   
       
   567   while (mem_chunk)
       
   568     {
       
   569       old_mem_chunk_print ((GMemChunk*) mem_chunk);
       
   570       mem_chunk = mem_chunk->next;
       
   571     }  
       
   572 }
       
   573 
       
   574 static gulong
       
   575 old_mem_chunk_compute_size (gulong size,
       
   576                             gulong min_size)
       
   577 {
       
   578   gulong power_of_2;
       
   579   gulong lower, upper;
       
   580   
       
   581   power_of_2 = 16;
       
   582   while (power_of_2 < size)
       
   583     power_of_2 <<= 1;
       
   584   
       
   585   lower = power_of_2 >> 1;
       
   586   upper = power_of_2;
       
   587   
       
   588   if (size - lower < upper - size && lower >= min_size)
       
   589     return lower;
       
   590   else
       
   591     return upper;
       
   592 }
       
   593 
       
   594 static gint
       
   595 old_mem_chunk_area_compare (GMemArea *a,
       
   596                             GMemArea *b)
       
   597 {
       
   598   if (a->mem > b->mem)
       
   599     return 1;
       
   600   else if (a->mem < b->mem)
       
   601     return -1;
       
   602   return 0;
       
   603 }
       
   604 
       
   605 static gint
       
   606 old_mem_chunk_area_search (GMemArea *a,
       
   607                            gchar    *addr)
       
   608 {
       
   609   if (a->mem <= addr)
       
   610     {
       
   611       if (addr < &a->mem[a->index])
       
   612 	return 0;
       
   613       return 1;
       
   614     }
       
   615   return -1;
       
   616 }