~ubuntu-branches/ubuntu/utopic/glib2.0/utopic

« back to all changes in this revision

Viewing changes to glib/gmem.c

Tags: upstream-2.12.12
ImportĀ upstreamĀ versionĀ 2.12.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "galias.h"
 
40
 
 
41
#define MEM_PROFILE_TABLE_SIZE 4096
 
42
 
 
43
 
 
44
/* notes on macros:
 
45
 * having G_DISABLE_CHECKS defined disables use of glib_mem_profiler_table and
 
46
 * g_mem_profile().
 
47
 * REALLOC_0_WORKS is defined if g_realloc (NULL, x) works.
 
48
 * SANE_MALLOC_PROTOS is defined if the systems malloc() and friends functions
 
49
 * match the corresponding GLib prototypes, keep configure.in and gmem.h in sync here.
 
50
 * g_mem_gc_friendly is TRUE, freed memory should be 0-wiped.
 
51
 */
 
52
 
 
53
/* --- prototypes --- */
 
54
static gboolean g_mem_initialized = FALSE;
 
55
static void     g_mem_init_nomessage (void);
 
56
 
 
57
 
 
58
/* --- malloc wrappers --- */
 
59
#ifndef REALLOC_0_WORKS
 
60
static gpointer
 
61
standard_realloc (gpointer mem,
 
62
                  gsize    n_bytes)
 
63
{
 
64
  if (!mem)
 
65
    return malloc (n_bytes);
 
66
  else
 
67
    return realloc (mem, n_bytes);
 
68
}
 
69
#endif  /* !REALLOC_0_WORKS */
 
70
 
 
71
#ifdef SANE_MALLOC_PROTOS
 
72
#  define standard_malloc       malloc
 
73
#  ifdef REALLOC_0_WORKS
 
74
#    define standard_realloc    realloc
 
75
#  endif /* REALLOC_0_WORKS */
 
76
#  define standard_free         free
 
77
#  define standard_calloc       calloc
 
78
#  define standard_try_malloc   malloc
 
79
#  define standard_try_realloc  realloc
 
80
#else   /* !SANE_MALLOC_PROTOS */
 
81
static gpointer
 
82
standard_malloc (gsize n_bytes)
 
83
{
 
84
  return malloc (n_bytes);
 
85
}
 
86
#  ifdef REALLOC_0_WORKS
 
87
static gpointer
 
88
standard_realloc (gpointer mem,
 
89
                  gsize    n_bytes)
 
90
{
 
91
  return realloc (mem, n_bytes);
 
92
}
 
93
#  endif /* REALLOC_0_WORKS */
 
94
static void
 
95
standard_free (gpointer mem)
 
96
{
 
97
  free (mem);
 
98
}
 
99
static gpointer
 
100
standard_calloc (gsize n_blocks,
 
101
                 gsize n_bytes)
 
102
{
 
103
  return calloc (n_blocks, n_bytes);
 
104
}
 
105
#define standard_try_malloc     standard_malloc
 
106
#define standard_try_realloc    standard_realloc
 
107
#endif  /* !SANE_MALLOC_PROTOS */
 
108
 
 
109
 
 
110
/* --- variables --- */
 
111
static GMemVTable glib_mem_vtable = {
 
112
  standard_malloc,
 
113
  standard_realloc,
 
114
  standard_free,
 
115
  standard_calloc,
 
116
  standard_try_malloc,
 
117
  standard_try_realloc,
 
118
};
 
119
 
 
120
 
 
121
/* --- functions --- */
 
122
gpointer
 
123
g_malloc (gulong n_bytes)
 
124
{
 
125
  if (G_UNLIKELY (!g_mem_initialized))
 
126
    g_mem_init_nomessage();
 
127
  if (G_LIKELY (n_bytes))
 
128
    {
 
129
      gpointer mem;
 
130
 
 
131
      mem = glib_mem_vtable.malloc (n_bytes);
 
132
      if (mem)
 
133
        return mem;
 
134
 
 
135
      g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
 
136
    }
 
137
 
 
138
  return NULL;
 
139
}
 
140
 
 
141
gpointer
 
142
g_malloc0 (gulong n_bytes)
 
143
{
 
144
  if (G_UNLIKELY (!g_mem_initialized))
 
145
    g_mem_init_nomessage();
 
146
  if (G_LIKELY (n_bytes))
 
147
    {
 
148
      gpointer mem;
 
149
 
 
150
      mem = glib_mem_vtable.calloc (1, n_bytes);
 
151
      if (mem)
 
152
        return mem;
 
153
 
 
154
      g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
 
155
    }
 
156
 
 
157
  return NULL;
 
158
}
 
159
 
 
160
gpointer
 
161
g_realloc (gpointer mem,
 
162
           gulong   n_bytes)
 
163
{
 
164
  if (G_UNLIKELY (!g_mem_initialized))
 
165
    g_mem_init_nomessage();
 
166
  if (G_LIKELY (n_bytes))
 
167
    {
 
168
      mem = glib_mem_vtable.realloc (mem, n_bytes);
 
169
      if (mem)
 
170
        return mem;
 
171
 
 
172
      g_error ("%s: failed to allocate %lu bytes", G_STRLOC, n_bytes);
 
173
    }
 
174
 
 
175
  if (mem)
 
176
    glib_mem_vtable.free (mem);
 
177
 
 
178
  return NULL;
 
179
}
 
180
 
 
181
void
 
182
g_free (gpointer mem)
 
183
{
 
184
  if (G_UNLIKELY (!g_mem_initialized))
 
185
    g_mem_init_nomessage();
 
186
  if (G_LIKELY (mem))
 
187
    glib_mem_vtable.free (mem);
 
188
}
 
189
 
 
190
gpointer
 
191
g_try_malloc (gulong n_bytes)
 
192
{
 
193
  if (G_UNLIKELY (!g_mem_initialized))
 
194
    g_mem_init_nomessage();
 
195
  if (G_LIKELY (n_bytes))
 
196
    return glib_mem_vtable.try_malloc (n_bytes);
 
197
  else
 
198
    return NULL;
 
199
}
 
200
 
 
201
gpointer
 
202
g_try_malloc0 (gulong n_bytes)
 
203
 
204
  gpointer mem;
 
205
 
 
206
  mem = g_try_malloc (n_bytes);
 
207
  
 
208
  if (mem)
 
209
    memset (mem, 0, n_bytes);
 
210
 
 
211
  return mem;
 
212
}
 
213
 
 
214
gpointer
 
215
g_try_realloc (gpointer mem,
 
216
               gulong   n_bytes)
 
217
{
 
218
  if (G_UNLIKELY (!g_mem_initialized))
 
219
    g_mem_init_nomessage();
 
220
  if (G_LIKELY (n_bytes))
 
221
    return glib_mem_vtable.try_realloc (mem, n_bytes);
 
222
 
 
223
  if (mem)
 
224
    glib_mem_vtable.free (mem);
 
225
 
 
226
  return NULL;
 
227
}
 
228
 
 
229
static gpointer
 
230
fallback_calloc (gsize n_blocks,
 
231
                 gsize n_block_bytes)
 
232
{
 
233
  gsize l = n_blocks * n_block_bytes;
 
234
  gpointer mem = glib_mem_vtable.malloc (l);
 
235
 
 
236
  if (mem)
 
237
    memset (mem, 0, l);
 
238
 
 
239
  return mem;
 
240
}
 
241
 
 
242
static gboolean vtable_set = FALSE;
 
243
 
 
244
/**
 
245
 * g_mem_is_system_malloc
 
246
 * 
 
247
 * Checks whether the allocator used by g_malloc() is the system's
 
248
 * malloc implementation. If it returns %TRUE memory allocated with
 
249
 * malloc() can be used interchangeable with memory allocated using g_malloc(). 
 
250
 * This function is useful for avoiding an extra copy of allocated memory returned
 
251
 * by a non-GLib-based API.
 
252
 *
 
253
 * A different allocator can be set using g_mem_set_vtable().
 
254
 *
 
255
 * Return value: if %TRUE, malloc() and g_malloc() can be mixed.
 
256
 **/
 
257
gboolean
 
258
g_mem_is_system_malloc (void)
 
259
{
 
260
  return !vtable_set;
 
261
}
 
262
 
 
263
void
 
264
g_mem_set_vtable (GMemVTable *vtable)
 
265
{
 
266
  if (!vtable_set)
 
267
    {
 
268
      if (vtable->malloc && vtable->realloc && vtable->free)
 
269
        {
 
270
          glib_mem_vtable.malloc = vtable->malloc;
 
271
          glib_mem_vtable.realloc = vtable->realloc;
 
272
          glib_mem_vtable.free = vtable->free;
 
273
          glib_mem_vtable.calloc = vtable->calloc ? vtable->calloc : fallback_calloc;
 
274
          glib_mem_vtable.try_malloc = vtable->try_malloc ? vtable->try_malloc : glib_mem_vtable.malloc;
 
275
          glib_mem_vtable.try_realloc = vtable->try_realloc ? vtable->try_realloc : glib_mem_vtable.realloc;
 
276
          vtable_set = TRUE;
 
277
        }
 
278
      else
 
279
        g_warning (G_STRLOC ": memory allocation vtable lacks one of malloc(), realloc() or free()");
 
280
    }
 
281
  else
 
282
    g_warning (G_STRLOC ": memory allocation vtable can only be set once at startup");
 
283
}
 
284
 
 
285
 
 
286
/* --- memory profiling and checking --- */
 
287
#ifdef  G_DISABLE_CHECKS
 
288
GMemVTable *glib_mem_profiler_table = &glib_mem_vtable;
 
289
void
 
290
g_mem_profile (void)
 
291
{
 
292
}
 
293
#else   /* !G_DISABLE_CHECKS */
 
294
typedef enum {
 
295
  PROFILER_FREE         = 0,
 
296
  PROFILER_ALLOC        = 1,
 
297
  PROFILER_RELOC        = 2,
 
298
  PROFILER_ZINIT        = 4
 
299
} ProfilerJob;
 
300
static guint *profile_data = NULL;
 
301
static gulong profile_allocs = 0;
 
302
static gulong profile_zinit = 0;
 
303
static gulong profile_frees = 0;
 
304
static GMutex *gmem_profile_mutex = NULL;
 
305
#ifdef  G_ENABLE_DEBUG
 
306
static volatile gulong g_trap_free_size = 0;
 
307
static volatile gulong g_trap_realloc_size = 0;
 
308
static volatile gulong g_trap_malloc_size = 0;
 
309
#endif  /* G_ENABLE_DEBUG */
 
310
 
 
311
#define PROFILE_TABLE(f1,f2,f3)   ( ( ((f3) << 2) | ((f2) << 1) | (f1) ) * (MEM_PROFILE_TABLE_SIZE + 1))
 
312
 
 
313
static void
 
314
profiler_log (ProfilerJob job,
 
315
              gulong      n_bytes,
 
316
              gboolean    success)
 
317
{
 
318
  g_mutex_lock (gmem_profile_mutex);
 
319
  if (!profile_data)
 
320
    {
 
321
      profile_data = standard_calloc ((MEM_PROFILE_TABLE_SIZE + 1) * 8, 
 
322
                                      sizeof (profile_data[0]));
 
323
      if (!profile_data)        /* memory system kiddin' me, eh? */
 
324
        {
 
325
          g_mutex_unlock (gmem_profile_mutex);
 
326
          return;
 
327
        }
 
328
    }
 
329
 
 
330
  if (n_bytes < MEM_PROFILE_TABLE_SIZE)
 
331
    profile_data[n_bytes + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
 
332
                                          (job & PROFILER_RELOC) != 0,
 
333
                                          success != 0)] += 1;
 
334
  else
 
335
    profile_data[MEM_PROFILE_TABLE_SIZE + PROFILE_TABLE ((job & PROFILER_ALLOC) != 0,
 
336
                                                         (job & PROFILER_RELOC) != 0,
 
337
                                                         success != 0)] += 1;
 
338
  if (success)
 
339
    {
 
340
      if (job & PROFILER_ALLOC)
 
341
        {
 
342
          profile_allocs += n_bytes;
 
343
          if (job & PROFILER_ZINIT)
 
344
            profile_zinit += n_bytes;
 
345
        }
 
346
      else
 
347
        profile_frees += n_bytes;
 
348
    }
 
349
  g_mutex_unlock (gmem_profile_mutex);
 
350
}
 
351
 
 
352
static void
 
353
profile_print_locked (guint   *local_data,
 
354
                      gboolean success)
 
355
{
 
356
  gboolean need_header = TRUE;
 
357
  guint i;
 
358
 
 
359
  for (i = 0; i <= MEM_PROFILE_TABLE_SIZE; i++)
 
360
    {
 
361
      glong t_malloc = local_data[i + PROFILE_TABLE (1, 0, success)];
 
362
      glong t_realloc = local_data[i + PROFILE_TABLE (1, 1, success)];
 
363
      glong t_free = local_data[i + PROFILE_TABLE (0, 0, success)];
 
364
      glong t_refree = local_data[i + PROFILE_TABLE (0, 1, success)];
 
365
      
 
366
      if (!t_malloc && !t_realloc && !t_free && !t_refree)
 
367
        continue;
 
368
      else if (need_header)
 
369
        {
 
370
          need_header = FALSE;
 
371
          g_print (" blocks of | allocated  | freed      | allocated  | freed      | n_bytes   \n");
 
372
          g_print ("  n_bytes  | n_times by | n_times by | n_times by | n_times by | remaining \n");
 
373
          g_print ("           | malloc()   | free()     | realloc()  | realloc()  |           \n");
 
374
          g_print ("===========|============|============|============|============|===========\n");
 
375
        }
 
376
      if (i < MEM_PROFILE_TABLE_SIZE)
 
377
        g_print ("%10u | %10ld | %10ld | %10ld | %10ld |%+11ld\n",
 
378
                 i, t_malloc, t_free, t_realloc, t_refree,
 
379
                 (t_malloc - t_free + t_realloc - t_refree) * i);
 
380
      else if (i >= MEM_PROFILE_TABLE_SIZE)
 
381
        g_print ("   >%6u | %10ld | %10ld | %10ld | %10ld |        ***\n",
 
382
                 i, t_malloc, t_free, t_realloc, t_refree);
 
383
    }
 
384
  if (need_header)
 
385
    g_print (" --- none ---\n");
 
386
}
 
387
 
 
388
void
 
389
g_mem_profile (void)
 
390
{
 
391
  guint local_data[(MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0])];
 
392
  gulong local_allocs;
 
393
  gulong local_zinit;
 
394
  gulong local_frees;
 
395
 
 
396
  if (G_UNLIKELY (!g_mem_initialized))
 
397
    g_mem_init_nomessage();
 
398
 
 
399
  g_mutex_lock (gmem_profile_mutex);
 
400
 
 
401
  local_allocs = profile_allocs;
 
402
  local_zinit = profile_zinit;
 
403
  local_frees = profile_frees;
 
404
 
 
405
  if (!profile_data)
 
406
    {
 
407
      g_mutex_unlock (gmem_profile_mutex);
 
408
      return;
 
409
    }
 
410
 
 
411
  memcpy (local_data, profile_data, 
 
412
          (MEM_PROFILE_TABLE_SIZE + 1) * 8 * sizeof (profile_data[0]));
 
413
  
 
414
  g_mutex_unlock (gmem_profile_mutex);
 
415
 
 
416
  g_print ("GLib Memory statistics (successful operations):\n");
 
417
  profile_print_locked (local_data, TRUE);
 
418
  g_print ("GLib Memory statistics (failing operations):\n");
 
419
  profile_print_locked (local_data, FALSE);
 
420
  g_print ("Total bytes: allocated=%lu, zero-initialized=%lu (%.2f%%), freed=%lu (%.2f%%), remaining=%lu\n",
 
421
           local_allocs,
 
422
           local_zinit,
 
423
           ((gdouble) local_zinit) / local_allocs * 100.0,
 
424
           local_frees,
 
425
           ((gdouble) local_frees) / local_allocs * 100.0,
 
426
           local_allocs - local_frees);
 
427
}
 
428
 
 
429
static gpointer
 
430
profiler_try_malloc (gsize n_bytes)
 
431
{
 
432
  gulong *p;
 
433
 
 
434
#ifdef  G_ENABLE_DEBUG
 
435
  if (g_trap_malloc_size == n_bytes)
 
436
    G_BREAKPOINT ();
 
437
#endif  /* G_ENABLE_DEBUG */
 
438
 
 
439
  p = standard_malloc (sizeof (gulong) * 2 + n_bytes);
 
440
 
 
441
  if (p)
 
442
    {
 
443
      p[0] = 0;         /* free count */
 
444
      p[1] = n_bytes;   /* length */
 
445
      profiler_log (PROFILER_ALLOC, n_bytes, TRUE);
 
446
      p += 2;
 
447
    }
 
448
  else
 
449
    profiler_log (PROFILER_ALLOC, n_bytes, FALSE);
 
450
  
 
451
  return p;
 
452
}
 
453
 
 
454
static gpointer
 
455
profiler_malloc (gsize n_bytes)
 
456
{
 
457
  gpointer mem = profiler_try_malloc (n_bytes);
 
458
 
 
459
  if (!mem)
 
460
    g_mem_profile ();
 
461
 
 
462
  return mem;
 
463
}
 
464
 
 
465
static gpointer
 
466
profiler_calloc (gsize n_blocks,
 
467
                 gsize n_block_bytes)
 
468
{
 
469
  gsize l = n_blocks * n_block_bytes;
 
470
  gulong *p;
 
471
 
 
472
#ifdef  G_ENABLE_DEBUG
 
473
  if (g_trap_malloc_size == l)
 
474
    G_BREAKPOINT ();
 
475
#endif  /* G_ENABLE_DEBUG */
 
476
  
 
477
  p = standard_calloc (1, sizeof (gulong) * 2 + l);
 
478
 
 
479
  if (p)
 
480
    {
 
481
      p[0] = 0;         /* free count */
 
482
      p[1] = l;         /* length */
 
483
      profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, TRUE);
 
484
      p += 2;
 
485
    }
 
486
  else
 
487
    {
 
488
      profiler_log (PROFILER_ALLOC | PROFILER_ZINIT, l, FALSE);
 
489
      g_mem_profile ();
 
490
    }
 
491
 
 
492
  return p;
 
493
}
 
494
 
 
495
static void
 
496
profiler_free (gpointer mem)
 
497
{
 
498
  gulong *p = mem;
 
499
 
 
500
  p -= 2;
 
501
  if (p[0])     /* free count */
 
502
    {
 
503
      g_warning ("free(%p): memory has been freed %lu times already", p + 2, p[0]);
 
504
      profiler_log (PROFILER_FREE,
 
505
                    p[1],       /* length */
 
506
                    FALSE);
 
507
    }
 
508
  else
 
509
    {
 
510
#ifdef  G_ENABLE_DEBUG
 
511
      if (g_trap_free_size == p[1])
 
512
        G_BREAKPOINT ();
 
513
#endif  /* G_ENABLE_DEBUG */
 
514
 
 
515
      profiler_log (PROFILER_FREE,
 
516
                    p[1],       /* length */
 
517
                    TRUE);
 
518
      memset (p + 2, 0xaa, p[1]);
 
519
 
 
520
      /* for all those that miss standard_free (p); in this place, yes,
 
521
       * we do leak all memory when profiling, and that is intentional
 
522
       * to catch double frees. patch submissions are futile.
 
523
       */
 
524
    }
 
525
  p[0] += 1;
 
526
}
 
527
 
 
528
static gpointer
 
529
profiler_try_realloc (gpointer mem,
 
530
                      gsize    n_bytes)
 
531
{
 
532
  gulong *p = mem;
 
533
 
 
534
  p -= 2;
 
535
 
 
536
#ifdef  G_ENABLE_DEBUG
 
537
  if (g_trap_realloc_size == n_bytes)
 
538
    G_BREAKPOINT ();
 
539
#endif  /* G_ENABLE_DEBUG */
 
540
  
 
541
  if (mem && p[0])      /* free count */
 
542
    {
 
543
      g_warning ("realloc(%p, %lu): memory has been freed %lu times already", p + 2, (gulong)n_bytes, p[0]);
 
544
      profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
 
545
 
 
546
      return NULL;
 
547
    }
 
548
  else
 
549
    {
 
550
      p = standard_realloc (mem ? p : NULL, sizeof (gulong) * 2 + n_bytes);
 
551
 
 
552
      if (p)
 
553
        {
 
554
          if (mem)
 
555
            profiler_log (PROFILER_FREE | PROFILER_RELOC, p[1], TRUE);
 
556
          p[0] = 0;
 
557
          p[1] = n_bytes;
 
558
          profiler_log (PROFILER_ALLOC | PROFILER_RELOC, p[1], TRUE);
 
559
          p += 2;
 
560
        }
 
561
      else
 
562
        profiler_log (PROFILER_ALLOC | PROFILER_RELOC, n_bytes, FALSE);
 
563
 
 
564
      return p;
 
565
    }
 
566
}
 
567
 
 
568
static gpointer
 
569
profiler_realloc (gpointer mem,
 
570
                  gsize    n_bytes)
 
571
{
 
572
  mem = profiler_try_realloc (mem, n_bytes);
 
573
 
 
574
  if (!mem)
 
575
    g_mem_profile ();
 
576
 
 
577
  return mem;
 
578
}
 
579
 
 
580
static GMemVTable profiler_table = {
 
581
  profiler_malloc,
 
582
  profiler_realloc,
 
583
  profiler_free,
 
584
  profiler_calloc,
 
585
  profiler_try_malloc,
 
586
  profiler_try_realloc,
 
587
};
 
588
GMemVTable *glib_mem_profiler_table = &profiler_table;
 
589
 
 
590
#endif  /* !G_DISABLE_CHECKS */
 
591
 
 
592
/* --- MemChunks --- */
 
593
#ifndef G_ALLOC_AND_FREE
 
594
typedef struct _GAllocator GAllocator;
 
595
typedef struct _GMemChunk  GMemChunk;
 
596
#define G_ALLOC_ONLY      1
 
597
#define G_ALLOC_AND_FREE  2
 
598
#endif
 
599
 
 
600
struct _GMemChunk {
 
601
  guint alloc_size;           /* the size of an atom */
 
602
};
 
603
 
 
604
GMemChunk*
 
605
g_mem_chunk_new (const gchar  *name,
 
606
                 gint          atom_size,
 
607
                 gulong        area_size,
 
608
                 gint          type)
 
609
{
 
610
  GMemChunk *mem_chunk;
 
611
  g_return_val_if_fail (atom_size > 0, NULL);
 
612
 
 
613
  mem_chunk = g_slice_new (GMemChunk);
 
614
  mem_chunk->alloc_size = atom_size;
 
615
  return mem_chunk;
 
616
}
 
617
 
 
618
void
 
619
g_mem_chunk_destroy (GMemChunk *mem_chunk)
 
620
{
 
621
  g_return_if_fail (mem_chunk != NULL);
 
622
  
 
623
  g_slice_free (GMemChunk, mem_chunk);
 
624
}
 
625
 
 
626
gpointer
 
627
g_mem_chunk_alloc (GMemChunk *mem_chunk)
 
628
{
 
629
  g_return_val_if_fail (mem_chunk != NULL, NULL);
 
630
  
 
631
  return g_slice_alloc (mem_chunk->alloc_size);
 
632
}
 
633
 
 
634
gpointer
 
635
g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
 
636
{
 
637
  g_return_val_if_fail (mem_chunk != NULL, NULL);
 
638
  
 
639
  return g_slice_alloc0 (mem_chunk->alloc_size);
 
640
}
 
641
 
 
642
void
 
643
g_mem_chunk_free (GMemChunk *mem_chunk,
 
644
                  gpointer   mem)
 
645
{
 
646
  g_return_if_fail (mem_chunk != NULL);
 
647
  
 
648
  g_slice_free1 (mem_chunk->alloc_size, mem);
 
649
}
 
650
 
 
651
void    g_mem_chunk_clean       (GMemChunk *mem_chunk)  {}
 
652
void    g_mem_chunk_reset       (GMemChunk *mem_chunk)  {}
 
653
void    g_mem_chunk_print       (GMemChunk *mem_chunk)  {}
 
654
void    g_mem_chunk_info        (void)                  {}
 
655
void    g_blow_chunks           (void)                  {}
 
656
 
 
657
GAllocator*
 
658
g_allocator_new (const gchar *name,
 
659
                 guint        n_preallocs)
 
660
{
 
661
  static struct _GAllocator {
 
662
    gchar      *name;
 
663
    guint16     n_preallocs;
 
664
    guint       is_unused : 1;
 
665
    guint       type : 4;
 
666
    GAllocator *last;
 
667
    GMemChunk  *mem_chunk;
 
668
    gpointer    free_list;
 
669
  } dummy = {
 
670
    "GAllocator is deprecated", 1, TRUE, 0, NULL, NULL, NULL,
 
671
  };
 
672
  /* some (broken) GAllocator uses depend on non-NULL allocators */
 
673
  return (void*) &dummy;
 
674
}
 
675
 
 
676
void
 
677
g_allocator_free (GAllocator *allocator)
 
678
{
 
679
}
 
680
 
 
681
#ifdef ENABLE_GC_FRIENDLY_DEFAULT
 
682
gboolean g_mem_gc_friendly = TRUE;
 
683
#else
 
684
gboolean g_mem_gc_friendly = FALSE;
 
685
#endif
 
686
 
 
687
static void
 
688
g_mem_init_nomessage (void)
 
689
{
 
690
  gchar buffer[1024];
 
691
  const gchar *val;
 
692
  static const GDebugKey keys[] = {
 
693
    { "gc-friendly", 1 },
 
694
  };
 
695
  gint flags;
 
696
  if (g_mem_initialized)
 
697
    return;
 
698
  /* don't use g_malloc/g_message here */
 
699
  val = _g_getenv_nomalloc ("G_DEBUG", buffer);
 
700
  flags = !val ? 0 : g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
 
701
  if (flags & 1)        /* gc-friendly */
 
702
    {
 
703
      g_mem_gc_friendly = TRUE;
 
704
    }
 
705
  g_mem_initialized = TRUE;
 
706
}
 
707
 
 
708
void
 
709
_g_mem_thread_init_noprivate_nomessage (void)
 
710
{
 
711
  /* we may only create mutexes here, locking/
 
712
   * unlocking a mutex does not yet work.
 
713
   */
 
714
  g_mem_init_nomessage();
 
715
#ifndef G_DISABLE_CHECKS
 
716
  gmem_profile_mutex = g_mutex_new ();
 
717
#endif
 
718
}
 
719
 
 
720
#define __G_MEM_C__
 
721
#include "galiasdef.c"