Initial commit
[platform/upstream/glib2.0.git] / glib / gmem.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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 #include "gthreadprivate.h"
39
40 #include "galias.h"
41
42 #define MEM_PROFILE_TABLE_SIZE 4096
43
44
45 /* notes on macros:
46  * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
47  * g_mem_profile().
48  * REALLOC_0_WORKS is defined if g_realloc (NULL, x) works.
49  * SANE_MALLOC_PROTOS is defined if the systems malloc() and friends functions
50  * match the corresponding GLib prototypes, keep configure.in and gmem.h in sync here.
51  * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
52  */
53
54 /* --- prototypes --- */
55 static gboolean g_mem_initialized = FALSE;
56 static void     g_mem_init_nomessage (void);
57
58
59 /* --- malloc wrappers --- */
60 #ifndef REALLOC_0_WORKS
61 static gpointer
62 standard_realloc (gpointer mem,
63                   gsize    n_bytes)
64 {
65   if (!mem)
66     return malloc (n_bytes);
67   else
68     return realloc (mem, n_bytes);
69 }
70 #endif  /* !REALLOC_0_WORKS */
71
72 #ifdef SANE_MALLOC_PROTOS
73 #  define standard_malloc       malloc
74 #  ifdef REALLOC_0_WORKS
75 #    define standard_realloc    realloc
76 #  endif /* REALLOC_0_WORKS */
77 #  define standard_free         free
78 #  define standard_calloc       calloc
79 #  define standard_try_malloc   malloc
80 #  define standard_try_realloc  realloc
81 #else   /* !SANE_MALLOC_PROTOS */
82 static gpointer
83 standard_malloc (gsize n_bytes)
84 {
85   return malloc (n_bytes);
86 }
87 #  ifdef REALLOC_0_WORKS
88 static gpointer
89 standard_realloc (gpointer mem,
90                   gsize    n_bytes)
91 {
92   return realloc (mem, n_bytes);
93 }
94 #  endif /* REALLOC_0_WORKS */
95 static void
96 standard_free (gpointer mem)
97 {
98   free (mem);
99 }
100 static gpointer
101 standard_calloc (gsize n_blocks,
102                  gsize n_bytes)
103 {
104   return calloc (n_blocks, n_bytes);
105 }
106 #define standard_try_malloc     standard_malloc
107 #define standard_try_realloc    standard_realloc
108 #endif  /* !SANE_MALLOC_PROTOS */
109
110
111 /* --- variables --- */
112 static GMemVTable glib_mem_vtable = {
113   standard_malloc,
114   standard_realloc,
115   standard_free,
116   standard_calloc,
117   standard_try_malloc,
118   standard_try_realloc,
119 };
120
121
122 /* --- functions --- */
123 gpointer
124 g_malloc (gsize n_bytes)
125 {
126   if (G_UNLIKELY (!g_mem_initialized))
127     g_mem_init_nomessage();
128   if (G_LIKELY (n_bytes))
129     {
130       gpointer mem;
131
132       mem = glib_mem_vtable.malloc (n_bytes);
133       if (mem)
134         return mem;
135
136       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
137                G_STRLOC, n_bytes);
138     }
139
140   return NULL;
141 }
142
143 gpointer
144 g_malloc0 (gsize n_bytes)
145 {
146   if (G_UNLIKELY (!g_mem_initialized))
147     g_mem_init_nomessage();
148   if (G_LIKELY (n_bytes))
149     {
150       gpointer mem;
151
152       mem = glib_mem_vtable.calloc (1, n_bytes);
153       if (mem)
154         return mem;
155
156       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
157                G_STRLOC, n_bytes);
158     }
159
160   return NULL;
161 }
162
163 gpointer
164 g_realloc (gpointer mem,
165            gsize    n_bytes)
166 {
167   if (G_UNLIKELY (!g_mem_initialized))
168     g_mem_init_nomessage();
169   if (G_LIKELY (n_bytes))
170     {
171       mem = glib_mem_vtable.realloc (mem, n_bytes);
172       if (mem)
173         return mem;
174
175       g_error ("%s: failed to allocate %"G_GSIZE_FORMAT" bytes",
176                G_STRLOC, n_bytes);
177     }
178
179   if (mem)
180     glib_mem_vtable.free (mem);
181
182   return NULL;
183 }
184
185 void
186 g_free (gpointer mem)
187 {
188   if (G_UNLIKELY (!g_mem_initialized))
189     g_mem_init_nomessage();
190   if (G_LIKELY (mem))
191     glib_mem_vtable.free (mem);
192 }
193
194 gpointer
195 g_try_malloc (gsize n_bytes)
196 {
197   if (G_UNLIKELY (!g_mem_initialized))
198     g_mem_init_nomessage();
199   if (G_LIKELY (n_bytes))
200     return glib_mem_vtable.try_malloc (n_bytes);
201   else
202     return NULL;
203 }
204
205 gpointer
206 g_try_malloc0 (gsize n_bytes)
207 {
208   gpointer mem;
209
210   mem = g_try_malloc (n_bytes);
211
212   if (mem)
213     memset (mem, 0, n_bytes);
214
215   return mem;
216 }
217
218 gpointer
219 g_try_realloc (gpointer mem,
220                gsize    n_bytes)
221 {
222   if (G_UNLIKELY (!g_mem_initialized))
223     g_mem_init_nomessage();
224   if (G_LIKELY (n_bytes))
225     return glib_mem_vtable.try_realloc (mem, n_bytes);
226
227   if (mem)
228     glib_mem_vtable.free (mem);
229
230   return NULL;
231 }
232
233
234 #define SIZE_OVERFLOWS(a,b) (G_UNLIKELY ((a) > G_MAXSIZE / (b)))
235
236 gpointer
237 g_malloc_n (gsize n_blocks,
238             gsize n_block_bytes)
239 {
240   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
241     {
242       if (G_UNLIKELY (!g_mem_initialized))
243         g_mem_init_nomessage();
244
245       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
246                G_STRLOC, n_blocks, n_block_bytes);
247     }
248
249   return g_malloc (n_blocks * n_block_bytes);
250 }
251
252 gpointer
253 g_malloc0_n (gsize n_blocks,
254              gsize n_block_bytes)
255 {
256   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
257     {
258       if (G_UNLIKELY (!g_mem_initialized))
259         g_mem_init_nomessage();
260
261       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
262                G_STRLOC, n_blocks, n_block_bytes);
263     }
264
265   return g_malloc0 (n_blocks * n_block_bytes);
266 }
267
268 gpointer
269 g_realloc_n (gpointer mem,
270              gsize    n_blocks,
271              gsize    n_block_bytes)
272 {
273   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
274     {
275       if (G_UNLIKELY (!g_mem_initialized))
276         g_mem_init_nomessage();
277
278       g_error ("%s: overflow allocating %"G_GSIZE_FORMAT"*%"G_GSIZE_FORMAT" bytes",
279                G_STRLOC, n_blocks, n_block_bytes);
280     }
281
282   return g_realloc (mem, n_blocks * n_block_bytes);
283 }
284
285 gpointer
286 g_try_malloc_n (gsize n_blocks,
287                 gsize n_block_bytes)
288 {
289   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
290     return NULL;
291
292   return g_try_malloc (n_blocks * n_block_bytes);
293 }
294
295 gpointer
296 g_try_malloc0_n (gsize n_blocks,
297                  gsize n_block_bytes)
298 {
299   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
300     return NULL;
301
302   return g_try_malloc0 (n_blocks * n_block_bytes);
303 }
304
305 gpointer
306 g_try_realloc_n (gpointer mem,
307                  gsize    n_blocks,
308                  gsize    n_block_bytes)
309 {
310   if (SIZE_OVERFLOWS (n_blocks, n_block_bytes))
311     return NULL;
312
313   return g_try_realloc (mem, n_blocks * n_block_bytes);
314 }
315
316
317
318 static gpointer
319 fallback_calloc (gsize n_blocks,
320                  gsize n_block_bytes)
321 {
322   gsize l = n_blocks * n_block_bytes;
323   gpointer mem = glib_mem_vtable.malloc (l);
324
325   if (mem)
326     memset (mem, 0, l);
327
328   return mem;
329 }
330
331 static gboolean vtable_set = FALSE;
332
333 /**
334  * g_mem_is_system_malloc
335  * 
336  * Checks whether the allocator used by g_malloc() is the system's
337  * malloc implementation. If it returns %TRUE memory allocated with
338  * malloc() can be used interchangeable with memory allocated using g_malloc(). 
339  * This function is useful for avoiding an extra copy of allocated memory returned
340  * by a non-GLib-based API.
341  *
342  * A different allocator can be set using g_mem_set_vtable().
343  *
344  * Return value: if %TRUE, malloc() and g_malloc() can be mixed.
345  **/
346 gboolean
347 g_mem_is_system_malloc (void)
348 {
349   return !vtable_set;
350 }
351
352 void
353 g_mem_set_vtable (GMemVTable *vtable)
354 {
355   if (!vtable_set)
356     {
357       if (vtable->malloc && vtable->realloc && vtable->free)
358         {
359           glib_mem_vtable.malloc = vtable->malloc;
360           glib_mem_vtable.realloc = vtable->realloc;
361           glib_mem_vtable.free = vtable->free;
362           glib_mem_vtable.calloc = vtable->calloc ? vtable->calloc : fallback_calloc;
363           glib_mem_vtable.try_malloc = vtable->try_malloc ? vtable->try_malloc : glib_mem_vtable.malloc;
364           glib_mem_vtable.try_realloc = vtable->try_realloc ? vtable->try_realloc : glib_mem_vtable.realloc;
365           vtable_set = TRUE;
366         }
367       else
368         g_warning (G_STRLOC ": memory allocation vtable lacks one of malloc(), realloc() or free()");
369     }
370   else
371     g_warning (G_STRLOC ": memory allocation vtable can only be set once at startup");
372 }
373
374
375 /* --- memory profiling and checking --- */
376 #ifdef  G_DISABLE_CHECKS
377 GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
378 void
379 g_mem_profile (void)
380 {
381 }
382 #else   /* !G_DISABLE_CHECKS */
383 typedef enum {
384   PROFILER_FREE         = 0,
385   PROFILER_ALLOC        = 1,
386   PROFILER_RELOC        = 2,
387   PROFILER_ZINIT        = 4
388 } ProfilerJob;
389 static guint *profile_data = NULL;
390 static gsize profile_allocs = 0;
391 static gsize profile_zinit = 0;
392 static gsize profile_frees = 0;
393 static GMutex *gmem_profile_mutex = NULL;
394 #ifdef  G_ENABLE_DEBUG
395 static volatile gsize g_trap_free_size = 0;
396 static volatile gsize g_trap_realloc_size = 0;
397 static volatile gsize g_trap_malloc_size = 0;
398 #endif  /* G_ENABLE_DEBUG */
399
400 #define PROFILE_TABLE(f1,f2,f3)   ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
401
402 static void
403 profiler_log (ProfilerJob job,
404               gsize       n_bytes,
405               gboolean    success)
406 {
407   g_mutex_lock (gmem_profile_mutex);
408   if (!profile_data)
409     {
410       profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8, 
411                                       sizeof (profile_data[0]));
412       if (!profile_data)        /* memory system kiddin' me, eh? */
413         {
414           g_mutex_unlock (gmem_profile_mutex);
415           return;
416         }
417     }
418
419   if (n_bytes < MEM_PROFILE_TABLE_SIZE)
420     profile_data[n_bytes + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
421                                           (job & PROFILER_RELOC) != 0,
422                                           success != 0)] += 1;
423   else
424     profile_data[MEM_PROFILE_TABLE_SIZE + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
425                                                          (job & PROFILER_RELOC) != 0,
426                                                          success != 0)] += 1;
427   if (success)
428     {
429       if (job & PROFILER_ALLOC)
430         {
431           profile_allocs += n_bytes;
432           if (job & PROFILER_ZINIT)
433             profile_zinit += n_bytes;
434         }
435       else
436         profile_frees += n_bytes;
437     }
438   g_mutex_unlock (gmem_profile_mutex);
439 }
440
441 static void
442 profile_print_locked (guint   *local_data,
443                       gboolean success)
444 {
445   gboolean need_header = TRUE;
446   guint i;
447
448   for (i = 0; i <= MEM_PROFILE_TABLE_SIZE; i++)
449     {
450       glong t_malloc = local_data[i + PROFILE_TABLE (1, 0, success)];
451       glong t_realloc = local_data[i + PROFILE_TABLE (1, 1, success)];
452       glong t_free = local_data[i + PROFILE_TABLE (0, 0, success)];
453       glong t_refree = local_data[i + PROFILE_TABLE (0, 1, success)];
454       
455       if (!t_malloc && !t_realloc && !t_free && !t_refree)
456         continue;
457       else if (need_header)
458         {
459           need_header = FALSE;
460           g_print (" blocks of | allocated  | freed      | allocated  | freed      | n_bytes   \n");
461           g_print ("  n_bytes  | n_times by | n_times by | n_times by | n_times by | remaining \n");
462           g_print ("           | malloc()   | free()     | realloc()  | realloc()  |           \n");
463           g_print ("===========|============|============|============|============|===========\n");
464         }
465       if (i < MEM_PROFILE_TABLE_SIZE)
466         g_print ("%10u | %10ld | %10ld | %10ld | %10ld |%+11ld\n",
467                  i, t_malloc, t_free, t_realloc, t_refree,
468                  (t_malloc - t_free + t_realloc - t_refree) * i);
469       else if (i >= MEM_PROFILE_TABLE_SIZE)
470         g_print ("   >%6u | %10ld | %10ld | %10ld | %10ld |        ***\n",
471                  i, t_malloc, t_free, t_realloc, t_refree);
472     }
473   if (need_header)
474     g_print (" --- none ---\n");
475 }
476
477 void
478 g_mem_profile (void)
479 {
480   guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])];
481   gsize local_allocs;
482   gsize local_zinit;
483   gsize local_frees;
484
485   if (G_UNLIKELY (!g_mem_initialized))
486     g_mem_init_nomessage();
487
488   g_mutex_lock (gmem_profile_mutex);
489
490   local_allocs = profile_allocs;
491   local_zinit = profile_zinit;
492   local_frees = profile_frees;
493
494   if (!profile_data)
495     {
496       g_mutex_unlock (gmem_profile_mutex);
497       return;
498     }
499
500   memcpy (local_data, profile_data, 
501           (MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0]));
502   
503   g_mutex_unlock (gmem_profile_mutex);
504
505   g_print ("GLib Memory statistics (successful operations):\n");
506   profile_print_locked (local_data, TRUE);
507   g_print ("GLib Memory statistics (failing operations):\n");
508   profile_print_locked (local_data, FALSE);
509   g_print ("Total bytes: allocated=%"G_GSIZE_FORMAT", "
510            "zero-initialized=%"G_GSIZE_FORMAT" (%.2f%%), "
511            "freed=%"G_GSIZE_FORMAT" (%.2f%%), "
512            "remaining=%"G_GSIZE_FORMAT"\n",
513            local_allocs,
514            local_zinit,
515            ((gdouble) local_zinit) / local_allocs * 100.0,
516            local_frees,
517            ((gdouble) local_frees) / local_allocs * 100.0,
518            local_allocs - local_frees);
519 }
520
521 static gpointer
522 profiler_try_malloc (gsize n_bytes)
523 {
524   gsize *p;
525
526 #ifdef  G_ENABLE_DEBUG
527   if (g_trap_malloc_size == n_bytes)
528     G_BREAKPOINT ();
529 #endif  /* G_ENABLE_DEBUG */
530
531   p = standard_malloc (sizeof (gsize) * 2 + n_bytes);
532
533   if (p)
534     {
535       p[0] = 0;         /* free count */
536       p[1] = n_bytes;   /* length */
537       profiler_log (PROFILER_ALLOC, n_bytes, TRUE);
538       p += 2;
539     }
540   else
541     profiler_log (PROFILER_ALLOC, n_bytes, FALSE);
542   
543   return p;
544 }
545
546 static gpointer
547 profiler_malloc (gsize n_bytes)
548 {
549   gpointer mem = profiler_try_malloc (n_bytes);
550
551   if (!mem)
552     g_mem_profile ();
553
554   return mem;
555 }
556
557 static gpointer
558 profiler_calloc (gsize n_blocks,
559                  gsize n_block_bytes)
560 {
561   gsize l = n_blocks * n_block_bytes;
562   gsize *p;
563
564 #ifdef  G_ENABLE_DEBUG
565   if (g_trap_malloc_size == l)
566     G_BREAKPOINT ();
567 #endif  /* G_ENABLE_DEBUG */
568   
569   p = standard_calloc (1, sizeof (gsize) * 2 + l);
570
571   if (p)
572     {
573       p[0] = 0;         /* free count */
574       p[1] = l;         /* length */
575       profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, TRUE);
576       p += 2;
577     }
578   else
579     {
580       profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, FALSE);
581       g_mem_profile ();
582     }
583
584   return p;
585 }
586
587 static void
588 profiler_free (gpointer mem)
589 {
590   gsize *p = mem;
591
592   p -= 2;
593   if (p[0])     /* free count */
594     {
595       g_warning ("free(%p): memory has been freed %"G_GSIZE_FORMAT" times already",
596                  p + 2, p[0]);
597       profiler_log (PROFILER_FREE,
598                     p[1],       /* length */
599                     FALSE);
600     }
601   else
602     {
603 #ifdef  G_ENABLE_DEBUG
604       if (g_trap_free_size == p[1])
605         G_BREAKPOINT ();
606 #endif  /* G_ENABLE_DEBUG */
607
608       profiler_log (PROFILER_FREE,
609                     p[1],       /* length */
610                     TRUE);
611       memset (p + 2, 0xaa, p[1]);
612
613       /* for all those that miss standard_free (p); in this place, yes,
614        * we do leak all memory when profiling, and that is intentional
615        * to catch double frees. patch submissions are futile.
616        */
617     }
618   p[0] += 1;
619 }
620
621 static gpointer
622 profiler_try_realloc (gpointer mem,
623                       gsize    n_bytes)
624 {
625   gsize *p = mem;
626
627   p -= 2;
628
629 #ifdef  G_ENABLE_DEBUG
630   if (g_trap_realloc_size == n_bytes)
631     G_BREAKPOINT ();
632 #endif  /* G_ENABLE_DEBUG */
633   
634   if (mem && p[0])      /* free count */
635     {
636       g_warning ("realloc(%p, %"G_GSIZE_FORMAT"): "
637                  "memory has been freed %"G_GSIZE_FORMAT" times already",
638                  p + 2, (gsize) n_bytes, p[0]);
639       profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
640
641       return NULL;
642     }
643   else
644     {
645       p = standard_realloc (mem ? p : NULL, sizeof (gsize) * 2 + n_bytes);
646
647       if (p)
648         {
649           if (mem)
650             profiler_log (PROFILER_FREE | PROFILER_RELOC, p[1], TRUE);
651           p[0] = 0;
652           p[1] = n_bytes;
653           profiler_log (PROFILER_ALLOC | PROFILER_RELOC, p[1], TRUE);
654           p += 2;
655         }
656       else
657         profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
658
659       return p;
660     }
661 }
662
663 static gpointer
664 profiler_realloc (gpointer mem,
665                   gsize    n_bytes)
666 {
667   mem = profiler_try_realloc (mem, n_bytes);
668
669   if (!mem)
670     g_mem_profile ();
671
672   return mem;
673 }
674
675 static GMemVTable profiler_table = {
676   profiler_malloc,
677   profiler_realloc,
678   profiler_free,
679   profiler_calloc,
680   profiler_try_malloc,
681   profiler_try_realloc,
682 };
683 GMemVTable *glib_mem_profiler_table = &profiler_table;
684
685 #endif  /* !G_DISABLE_CHECKS */
686
687 /* --- MemChunks --- */
688 /**
689  * SECTION: allocators
690  * @title: Memory Allocators
691  * @short_description: deprecated way to allocate chunks of memory for
692  *                     GList, GSList and GNode
693  *
694  * Prior to 2.10, #GAllocator was used as an efficient way to allocate
695  * small pieces of memory for use with the #GList, #GSList and #GNode
696  * data structures. Since 2.10, it has been completely replaced by the
697  * <link linkend="glib-Memory-Slices">slice allocator</link> and
698  * deprecated.
699  **/
700
701 /**
702  * SECTION: memory_chunks
703  * @title: Memory Chunks
704  * @short_description: deprecated way to allocate groups of equal-sized
705  *                     chunks of memory
706  *
707  * Memory chunks provide an space-efficient way to allocate equal-sized
708  * pieces of memory, called atoms. However, due to the administrative
709  * overhead (in particular for #G_ALLOC_AND_FREE, and when used from
710  * multiple threads), they are in practise often slower than direct use
711  * of g_malloc(). Therefore, memory chunks have been deprecated in
712  * favor of the <link linkend="glib-Memory-Slices">slice
713  * allocator</link>, which has been added in 2.10. All internal uses of
714  * memory chunks in GLib have been converted to the
715  * <literal>g_slice</literal> API.
716  *
717  * There are two types of memory chunks, #G_ALLOC_ONLY, and
718  * #G_ALLOC_AND_FREE. <itemizedlist> <listitem><para> #G_ALLOC_ONLY
719  * chunks only allow allocation of atoms. The atoms can never be freed
720  * individually. The memory chunk can only be free in its entirety.
721  * </para></listitem> <listitem><para> #G_ALLOC_AND_FREE chunks do
722  * allow atoms to be freed individually. The disadvantage of this is
723  * that the memory chunk has to keep track of which atoms have been
724  * freed. This results in more memory being used and a slight
725  * degradation in performance. </para></listitem> </itemizedlist>
726  *
727  * To create a memory chunk use g_mem_chunk_new() or the convenience
728  * macro g_mem_chunk_create().
729  *
730  * To allocate a new atom use g_mem_chunk_alloc(),
731  * g_mem_chunk_alloc0(), or the convenience macros g_chunk_new() or
732  * g_chunk_new0().
733  *
734  * To free an atom use g_mem_chunk_free(), or the convenience macro
735  * g_chunk_free(). (Atoms can only be freed if the memory chunk is
736  * created with the type set to #G_ALLOC_AND_FREE.)
737  *
738  * To free any blocks of memory which are no longer being used, use
739  * g_mem_chunk_clean(). To clean all memory chunks, use g_blow_chunks().
740  *
741  * To reset the memory chunk, freeing all of the atoms, use
742  * g_mem_chunk_reset().
743  *
744  * To destroy a memory chunk, use g_mem_chunk_destroy().
745  *
746  * To help debug memory chunks, use g_mem_chunk_info() and
747  * g_mem_chunk_print().
748  *
749  * <example>
750  *  <title>Using a #GMemChunk</title>
751  *  <programlisting>
752  *   GMemChunk *mem_chunk;
753  *   gchar *mem[10000];
754  *   gint i;
755  *
756  *   /<!-- -->* Create a GMemChunk with atoms 50 bytes long, and memory
757  *      blocks holding 100 bytes. Note that this means that only 2 atoms
758  *      fit into each memory block and so isn't very efficient. *<!-- -->/
759  *   mem_chunk = g_mem_chunk_new ("test mem chunk", 50, 100, G_ALLOC_AND_FREE);
760  *   /<!-- -->* Now allocate 10000 atoms. *<!-- -->/
761  *   for (i = 0; i &lt; 10000; i++)
762  *     {
763  *       mem[i] = g_chunk_new (gchar, mem_chunk);
764  *       /<!-- -->* Fill in the atom memory with some junk. *<!-- -->/
765  *       for (j = 0; j &lt; 50; j++)
766  *         mem[i][j] = i * j;
767  *     }
768  *   /<!-- -->* Now free all of the atoms. Note that since we are going to
769  *      destroy the GMemChunk, this wouldn't normally be used. *<!-- -->/
770  *   for (i = 0; i &lt; 10000; i++)
771  *     {
772  *       g_mem_chunk_free (mem_chunk, mem[i]);
773  *     }
774  *   /<!-- -->* We are finished with the GMemChunk, so we destroy it. *<!-- -->/
775  *   g_mem_chunk_destroy (mem_chunk);
776  *  </programlisting>
777  * </example>
778  *
779  * <example>
780  *  <title>Using a #GMemChunk with data structures</title>
781  *  <programlisting>
782  *    GMemChunk *array_mem_chunk;
783  *    GRealArray *array;
784  *    /<!-- -->* Create a GMemChunk to hold GRealArray structures, using
785  *       the g_mem_chunk_create(<!-- -->) convenience macro. We want 1024 atoms in each
786  *       memory block, and we want to be able to free individual atoms. *<!-- -->/
787  *    array_mem_chunk = g_mem_chunk_create (GRealArray, 1024, G_ALLOC_AND_FREE);
788  *    /<!-- -->* Allocate one atom, using the g_chunk_new(<!-- -->) convenience macro. *<!-- -->/
789  *    array = g_chunk_new (GRealArray, array_mem_chunk);
790  *    /<!-- -->* We can now use array just like a normal pointer to a structure. *<!-- -->/
791  *    array->data            = NULL;
792  *    array->len             = 0;
793  *    array->alloc           = 0;
794  *    array->zero_terminated = (zero_terminated ? 1 : 0);
795  *    array->clear           = (clear ? 1 : 0);
796  *    array->elt_size        = elt_size;
797  *    /<!-- -->* We can free the element, so it can be reused. *<!-- -->/
798  *    g_chunk_free (array, array_mem_chunk);
799  *    /<!-- -->* We destroy the GMemChunk when we are finished with it. *<!-- -->/
800  *    g_mem_chunk_destroy (array_mem_chunk);
801  *  </programlisting>
802  * </example>
803  **/
804
805 #ifndef G_ALLOC_AND_FREE
806
807 /**
808  * GAllocator:
809  *
810  * The #GAllocator struct contains private data. and should only be
811  * accessed using the following functions.
812  **/
813 typedef struct _GAllocator GAllocator;
814
815 /**
816  * GMemChunk:
817  *
818  * The #GMemChunk struct is an opaque data structure representing a
819  * memory chunk. It should be accessed only through the use of the
820  * following functions.
821  **/
822 typedef struct _GMemChunk  GMemChunk;
823
824 /**
825  * G_ALLOC_ONLY:
826  *
827  * Specifies the type of a #GMemChunk. Used in g_mem_chunk_new() and
828  * g_mem_chunk_create() to specify that atoms will never be freed
829  * individually.
830  **/
831 #define G_ALLOC_ONLY      1
832
833 /**
834  * G_ALLOC_AND_FREE:
835  *
836  * Specifies the type of a #GMemChunk. Used in g_mem_chunk_new() and
837  * g_mem_chunk_create() to specify that atoms will be freed
838  * individually.
839  **/
840 #define G_ALLOC_AND_FREE  2
841 #endif
842
843 struct _GMemChunk {
844   guint alloc_size;           /* the size of an atom */
845 };
846
847 /**
848  * g_mem_chunk_new:
849  * @name: a string to identify the #GMemChunk. It is not copied so it
850  *        should be valid for the lifetime of the #GMemChunk. It is
851  *        only used in g_mem_chunk_print(), which is used for debugging.
852  * @atom_size: the size, in bytes, of each element in the #GMemChunk.
853  * @area_size: the size, in bytes, of each block of memory allocated to
854  *             contain the atoms.
855  * @type: the type of the #GMemChunk.  #G_ALLOC_AND_FREE is used if the
856  *        atoms will be freed individually.  #G_ALLOC_ONLY should be
857  *        used if atoms will never be freed individually.
858  *        #G_ALLOC_ONLY is quicker, since it does not need to track
859  *        free atoms, but it obviously wastes memory if you no longer
860  *        need many of the atoms.
861  * @Returns: the new #GMemChunk.
862  *
863  * Creates a new #GMemChunk.
864  *
865  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
866  *                  allocator</link> instead
867  **/
868 GMemChunk*
869 g_mem_chunk_new (const gchar  *name,
870                  gint          atom_size,
871                  gsize         area_size,
872                  gint          type)
873 {
874   GMemChunk *mem_chunk;
875   g_return_val_if_fail (atom_size > 0, NULL);
876
877   mem_chunk = g_slice_new (GMemChunk);
878   mem_chunk->alloc_size = atom_size;
879   return mem_chunk;
880 }
881
882 /**
883  * g_mem_chunk_destroy:
884  * @mem_chunk: a #GMemChunk.
885  *
886  * Frees all of the memory allocated for a #GMemChunk.
887  *
888  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
889  *                  allocator</link> instead
890  **/
891 void
892 g_mem_chunk_destroy (GMemChunk *mem_chunk)
893 {
894   g_return_if_fail (mem_chunk != NULL);
895   
896   g_slice_free (GMemChunk, mem_chunk);
897 }
898
899 /**
900  * g_mem_chunk_alloc:
901  * @mem_chunk: a #GMemChunk.
902  * @Returns: a pointer to the allocated atom.
903  *
904  * Allocates an atom of memory from a #GMemChunk.
905  *
906  * Deprecated:2.10: Use g_slice_alloc() instead
907  **/
908 gpointer
909 g_mem_chunk_alloc (GMemChunk *mem_chunk)
910 {
911   g_return_val_if_fail (mem_chunk != NULL, NULL);
912   
913   return g_slice_alloc (mem_chunk->alloc_size);
914 }
915
916 /**
917  * g_mem_chunk_alloc0:
918  * @mem_chunk: a #GMemChunk.
919  * @Returns: a pointer to the allocated atom.
920  *
921  * Allocates an atom of memory from a #GMemChunk, setting the memory to
922  * 0.
923  *
924  * Deprecated:2.10: Use g_slice_alloc0() instead
925  **/
926 gpointer
927 g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
928 {
929   g_return_val_if_fail (mem_chunk != NULL, NULL);
930   
931   return g_slice_alloc0 (mem_chunk->alloc_size);
932 }
933
934 /**
935  * g_mem_chunk_free:
936  * @mem_chunk: a #GMemChunk.
937  * @mem: a pointer to the atom to free.
938  *
939  * Frees an atom in a #GMemChunk. This should only be called if the
940  * #GMemChunk was created with #G_ALLOC_AND_FREE. Otherwise it will
941  * simply return.
942  *
943  * Deprecated:2.10: Use g_slice_free1() instead
944  **/
945 void
946 g_mem_chunk_free (GMemChunk *mem_chunk,
947                   gpointer   mem)
948 {
949   g_return_if_fail (mem_chunk != NULL);
950   
951   g_slice_free1 (mem_chunk->alloc_size, mem);
952 }
953
954 /**
955  * g_mem_chunk_clean:
956  * @mem_chunk: a #GMemChunk.
957  *
958  * Frees any blocks in a #GMemChunk which are no longer being used.
959  *
960  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
961  *                  allocator</link> instead
962  **/
963 void    g_mem_chunk_clean       (GMemChunk *mem_chunk)  {}
964
965 /**
966  * g_mem_chunk_reset:
967  * @mem_chunk: a #GMemChunk.
968  *
969  * Resets a GMemChunk to its initial state. It frees all of the
970  * currently allocated blocks of memory.
971  *
972  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
973  *                  allocator</link> instead
974  **/
975 void    g_mem_chunk_reset       (GMemChunk *mem_chunk)  {}
976
977
978 /**
979  * g_mem_chunk_print:
980  * @mem_chunk: a #GMemChunk.
981  *
982  * Outputs debugging information for a #GMemChunk. It outputs the name
983  * of the #GMemChunk (set with g_mem_chunk_new()), the number of bytes
984  * used, and the number of blocks of memory allocated.
985  *
986  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
987  *                  allocator</link> instead
988  **/
989 void    g_mem_chunk_print       (GMemChunk *mem_chunk)  {}
990
991
992 /**
993  * g_mem_chunk_info:
994  *
995  * Outputs debugging information for all #GMemChunk objects currently
996  * in use. It outputs the number of #GMemChunk objects currently
997  * allocated, and calls g_mem_chunk_print() to output information on
998  * each one.
999  *
1000  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
1001  *                  allocator</link> instead
1002  **/
1003 void    g_mem_chunk_info        (void)                  {}
1004
1005 /**
1006  * g_blow_chunks:
1007  *
1008  * Calls g_mem_chunk_clean() on all #GMemChunk objects.
1009  *
1010  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
1011  *                  allocator</link> instead
1012  **/
1013 void    g_blow_chunks           (void)                  {}
1014
1015 /**
1016  * g_chunk_new0:
1017  * @type: the type of the #GMemChunk atoms, typically a structure name.
1018  * @chunk: a #GMemChunk.
1019  * @Returns: a pointer to the allocated atom, cast to a pointer to
1020  *           @type.
1021  *
1022  * A convenience macro to allocate an atom of memory from a #GMemChunk.
1023  * It calls g_mem_chunk_alloc0() and casts the returned atom to a
1024  * pointer to the given type, avoiding a type cast in the source code.
1025  *
1026  * Deprecated:2.10: Use g_slice_new0() instead
1027  **/
1028
1029 /**
1030  * g_chunk_free:
1031  * @mem: a pointer to the atom to be freed.
1032  * @mem_chunk: a #GMemChunk.
1033  *
1034  * A convenience macro to free an atom of memory from a #GMemChunk. It
1035  * simply switches the arguments and calls g_mem_chunk_free() It is
1036  * included simply to complement the other convenience macros,
1037  * g_chunk_new() and g_chunk_new0().
1038  *
1039  * Deprecated:2.10: Use g_slice_free() instead
1040  **/
1041
1042 /**
1043  * g_chunk_new:
1044  * @type: the type of the #GMemChunk atoms, typically a structure name.
1045  * @chunk: a #GMemChunk.
1046  * @Returns: a pointer to the allocated atom, cast to a pointer to
1047  *           @type.
1048  *
1049  * A convenience macro to allocate an atom of memory from a #GMemChunk.
1050  * It calls g_mem_chunk_alloc() and casts the returned atom to a
1051  * pointer to the given type, avoiding a type cast in the source code.
1052  *
1053  * Deprecated:2.10: Use g_slice_new() instead
1054  **/
1055
1056 /**
1057  * g_mem_chunk_create:
1058  * @type: the type of the atoms, typically a structure name.
1059  * @pre_alloc: the number of atoms to store in each block of memory.
1060  * @alloc_type: the type of the #GMemChunk.  #G_ALLOC_AND_FREE is used
1061  *              if the atoms will be freed individually.  #G_ALLOC_ONLY
1062  *              should be used if atoms will never be freed
1063  *              individually.  #G_ALLOC_ONLY is quicker, since it does
1064  *              not need to track free atoms, but it obviously wastes
1065  *              memory if you no longer need many of the atoms.
1066  * @Returns: the new #GMemChunk.
1067  *
1068  * A convenience macro for creating a new #GMemChunk. It calls
1069  * g_mem_chunk_new(), using the given type to create the #GMemChunk
1070  * name. The atom size is determined using
1071  * <function>sizeof()</function>, and the area size is calculated by
1072  * multiplying the @pre_alloc parameter with the atom size.
1073  *
1074  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
1075  *                  allocator</link> instead
1076  **/
1077
1078
1079 /**
1080  * g_allocator_new:
1081  * @name: the name of the #GAllocator. This name is used to set the
1082  *        name of the #GMemChunk used by the #GAllocator, and is only
1083  *        used for debugging.
1084  * @n_preallocs: the number of elements in each block of memory
1085  *               allocated.  Larger blocks mean less calls to
1086  *               g_malloc(), but some memory may be wasted.  (GLib uses
1087  *               128 elements per block by default.) The value must be
1088  *               between 1 and 65535.
1089  * @Returns: a new #GAllocator.
1090  *
1091  * Creates a new #GAllocator.
1092  *
1093  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
1094  *                  allocator</link> instead
1095  **/
1096 GAllocator*
1097 g_allocator_new (const gchar *name,
1098                  guint        n_preallocs)
1099 {
1100   static struct _GAllocator {
1101     gchar      *name;
1102     guint16     n_preallocs;
1103     guint       is_unused : 1;
1104     guint       type : 4;
1105     GAllocator *last;
1106     GMemChunk  *mem_chunk;
1107     gpointer    free_list;
1108   } dummy = {
1109     "GAllocator is deprecated", 1, TRUE, 0, NULL, NULL, NULL,
1110   };
1111   /* some (broken) GAllocator uses depend on non-NULL allocators */
1112   return (void*) &dummy;
1113 }
1114
1115 /**
1116  * g_allocator_free:
1117  * @allocator: a #GAllocator.
1118  *
1119  * Frees all of the memory allocated by the #GAllocator.
1120  *
1121  * Deprecated:2.10: Use the <link linkend="glib-Memory-Slices">slice
1122  *                  allocator</link> instead
1123  **/
1124 void
1125 g_allocator_free (GAllocator *allocator)
1126 {
1127 }
1128
1129 #ifdef ENABLE_GC_FRIENDLY_DEFAULT
1130 gboolean g_mem_gc_friendly = TRUE;
1131 #else
1132 gboolean g_mem_gc_friendly = FALSE;
1133 #endif
1134
1135 static void
1136 g_mem_init_nomessage (void)
1137 {
1138   gchar buffer[1024];
1139   const gchar *val;
1140   const GDebugKey keys[] = {
1141     { "gc-friendly", 1 },
1142   };
1143   gint flags;
1144   if (g_mem_initialized)
1145     return;
1146   /* don't use g_malloc/g_message here */
1147   val = _g_getenv_nomalloc ("G_DEBUG", buffer);
1148   flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
1149   if (flags & 1)        /* gc-friendly */
1150     {
1151       g_mem_gc_friendly = TRUE;
1152     }
1153   g_mem_initialized = TRUE;
1154 }
1155
1156 void
1157 _g_mem_thread_init_noprivate_nomessage (void)
1158 {
1159   /* we may only create mutexes here, locking/
1160    * unlocking a mutex does not yet work.
1161    */
1162   g_mem_init_nomessage();
1163 #ifndef G_DISABLE_CHECKS
1164   gmem_profile_mutex = g_mutex_new ();
1165 #endif
1166 }
1167
1168 #define __G_MEM_C__
1169 #include "galiasdef.c"