~ubuntu-branches/debian/squeeze/ghostscript/squeeze

« back to all changes in this revision

Viewing changes to src/gsmalloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Masayuki Hatta (mhatta)
  • Date: 2009-01-04 12:09:59 UTC
  • mfrom: (16.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090104120959-m9lbagj775ucg0h3
Tags: 8.63.dfsg.1-2
libgs-dev: put versioned dependency on libgs8 - closes: #510691

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: gsmalloc.c 8250 2007-09-25 13:31:24Z giles $ */
 
14
/* $Id: gsmalloc.c 8721 2008-05-09 02:18:14Z ray $ */
15
15
/* C heap allocator */
16
16
#include "malloc_.h"
17
17
#include "gdebug.h"
22
22
#include "gsmdebug.h"
23
23
#include "gsstruct.h"           /* for st_bytes */
24
24
#include "gsmalloc.h"
25
 
#include "gsmemlok.h"           /* locking (multithreading) wrapper */
26
25
#include "gsmemret.h"           /* retrying wrapper */
27
26
 
28
27
 
118
117
    mem->max_used = 0;
119
118
    mem->gs_lib_ctx = 0;
120
119
    mem->non_gc_memory = (gs_memory_t *)mem;
 
120
    /* Allocate a monitor to serialize access to structures within */
 
121
    mem->monitor = NULL;        /* prevent use during initial allocation */
 
122
    mem->monitor = gx_monitor_alloc((gs_memory_t *)mem);
121
123
 
122
124
    return mem;
123
125
}
163
165
#  define set_msg(str) DO_NOTHING
164
166
#endif
165
167
 
 
168
        /* Exclusive acces so our decisions and changes are 'atomic' */
 
169
    if (mmem->monitor)
 
170
        gx_monitor_enter(mmem->monitor);
166
171
    if (size > mmem->limit - sizeof(gs_malloc_block_t)) {
167
172
        /* Definitely too large to allocate; also avoids overflow. */
168
173
        set_msg("exceeded limit");
192
197
            bp->cname = cname;
193
198
            mmem->allocated = bp;
194
199
            ptr = (byte *) (bp + 1);
195
 
            gs_alloc_fill(ptr, gs_alloc_fill_alloc, size);
196
200
            mmem->used += size + sizeof(gs_malloc_block_t);
197
201
            if (mmem->used > mmem->max_used)
198
202
                mmem->max_used = mmem->used;
199
203
        }
200
204
    }
 
205
    if (mmem->monitor)
 
206
        gx_monitor_leave(mmem->monitor);        /* Done with exclusive access */
 
207
    /* We don't want to 'fill' under mutex to keep the window smaller */
 
208
    if (ptr)
 
209
        gs_alloc_fill(ptr, gs_alloc_fill_alloc, size);
201
210
#ifdef DEBUG
202
211
    if (gs_debug_c('a') || msg != ok_msg)
203
212
        dlprintf4("[a+]gs_malloc(%s)(%u) = 0x%lx: %s\n",
256
265
 
257
266
    if (new_size == old_size)
258
267
        return obj;
 
268
    if (mmem->monitor)
 
269
        gx_monitor_enter(mmem->monitor);        /* Exclusive access */
259
270
    new_ptr = (gs_malloc_block_t *) gs_realloc(ptr, old_size, new_size);
260
271
    if (new_ptr == 0)
261
272
        return 0;
268
279
    new_ptr->size = new_size - sizeof(gs_malloc_block_t);
269
280
    mmem->used -= old_size;
270
281
    mmem->used += new_size;
 
282
    if (mmem->monitor)
 
283
        gx_monitor_leave(mmem->monitor);        /* Done with exclusive access */
271
284
    if (new_size > old_size)
272
285
        gs_alloc_fill((byte *) new_ptr + old_size,
273
286
                      gs_alloc_fill_alloc, new_size - old_size);
304
317
                  (ulong) ptr, client_name_string(cname));
305
318
        (*finalize) (ptr);
306
319
    }
 
320
    if (mmem->monitor)
 
321
        gx_monitor_enter(mmem->monitor);        /* Exclusive access */
307
322
    bp = mmem->allocated; /* If 'finalize' releases a memory,
308
323
                             this function could be called recursively and
309
324
                             change mmem->allocated. */
313
328
 
314
329
        if (mmem->allocated)
315
330
            mmem->allocated->prev = 0;
 
331
        if (mmem->monitor)
 
332
            gx_monitor_leave(mmem->monitor);    /* Done with exclusive access */
316
333
        gs_alloc_fill(bp, gs_alloc_fill_free,
317
334
                      bp->size + sizeof(gs_malloc_block_t));
318
335
        free(bp);
330
347
                    if (np->next)
331
348
                        np->next->prev = bp;
332
349
                    mmem->used -= np->size + sizeof(gs_malloc_block_t);
 
350
                    if (mmem->monitor)
 
351
                        gx_monitor_leave(mmem->monitor);        /* Done with exclusive access */
333
352
                    gs_alloc_fill(np, gs_alloc_fill_free,
334
353
                                  np->size + sizeof(gs_malloc_block_t));
335
354
                    free(np);
337
356
                }
338
357
            }
339
358
        }
 
359
        if (mmem->monitor)
 
360
            gx_monitor_leave(mmem->monitor);    /* Done with exclusive access */
340
361
        lprintf2("%s: free 0x%lx not found!\n",
341
362
                 client_name_string(cname), (ulong) ptr);
342
363
        free((char *)((gs_malloc_block_t *) ptr - 1));
379
400
{
380
401
    return mem;                 /* heap memory is stable */
381
402
}
 
403
 
 
404
/*
 
405
 * NB: In a multi-threaded application, this is only a 'snapshot'
 
406
 *     since other threads may change the heap_status. The heap_available()
 
407
 *     probe is just an approximation anyway.
 
408
 */
382
409
static void
383
410
gs_heap_status(gs_memory_t * mem, gs_memory_status_t * pstat)
384
411
{
403
430
gs_heap_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
404
431
{
405
432
    gs_malloc_memory_t *const mmem = (gs_malloc_memory_t *) mem;
 
433
    gx_monitor_t *mon = mmem->monitor;
406
434
 
 
435
    /*
 
436
     * We don't perform locking during this process since the 'monitor'
 
437
     * is contained in this allocator, and will get freed along the way.
 
438
     * It is only called at exit, and there better not be any threads
 
439
     * accessing this allocator.
 
440
     */
 
441
    mmem->monitor = NULL;       /* delete reference to this monitor */
 
442
    gx_monitor_free(mon);       /* free the monitor */
407
443
    if (free_mask & FREE_ALL_DATA) {
408
444
        gs_malloc_block_t *bp = mmem->allocated;
409
445
        gs_malloc_block_t *np;
427
463
int
428
464
gs_malloc_wrap(gs_memory_t **wrapped, gs_malloc_memory_t *contents)
429
465
{
430
 
#ifdef USE_RETRY_AND_LOCKING_MEMORY_WRAPPERS
431
 
    gs_memory_t *cmem = (gs_memory_t *)contents;
432
 
    gs_memory_locked_t *lmem = (gs_memory_locked_t *)
433
 
        gs_alloc_bytes_immovable(cmem, sizeof(gs_memory_locked_t),
434
 
                                 "gs_malloc_wrap(locked)");
435
 
    gs_memory_retrying_t *rmem;
436
 
    int code;
437
 
 
438
 
    if (lmem == 0)
439
 
        return_error(gs_error_VMerror);
440
 
    code = gs_memory_locked_init(lmem, cmem);
441
 
    if (code < 0) {
442
 
        gs_free_object(cmem, lmem, "gs_malloc_wrap(locked)");
443
 
        return code;
444
 
    }
445
 
 
446
 
    rmem = (gs_memory_retrying_t *)
447
 
        gs_alloc_bytes_immovable((gs_memory_t *)lmem,
448
 
                                 sizeof(gs_memory_retrying_t),
449
 
                                 "gs_malloc_wrap(retrying)");
450
 
    if (rmem == 0) {
451
 
        gs_memory_locked_release(lmem);
452
 
        gs_free_object(cmem, lmem, "gs_malloc_wrap(locked)");
453
 
        return_error(gs_error_VMerror);
454
 
    }
455
 
    code = gs_memory_retrying_init(rmem, (gs_memory_t *)lmem);
456
 
    if (code < 0) {
457
 
        gs_free_object((gs_memory_t *)lmem, rmem, "gs_malloc_wrap(retrying)");
458
 
        gs_memory_locked_release(lmem);
459
 
        gs_free_object(cmem, lmem, "gs_malloc_wrap(locked)");
460
 
        return code;
461
 
    }
462
 
 
463
 
    *wrapped = (gs_memory_t *)rmem;
464
 
#endif 
 
466
#  ifdef USE_RETRY_MEMORY_WRAPPER
 
467
    /*
 
468
     * This is deprecated since 'retry' for clist reversion/cycling
 
469
     * will ONLY work for monochrome, simple PS or PCL, not for a
 
470
     * color device and not for PDF or XPS with transparency
 
471
     */
 
472
    {
 
473
        gs_memory_retrying_t *rmem;
 
474
        rmem = (gs_memory_retrying_t *)
 
475
            gs_alloc_bytes_immovable((gs_memory_t *)lmem,
 
476
                                     sizeof(gs_memory_retrying_t),
 
477
                                     "gs_malloc_wrap(retrying)");
 
478
        if (rmem == 0) {
 
479
            gs_memory_locked_release(lmem);
 
480
            gs_free_object(cmem, lmem, "gs_malloc_wrap(locked)");
 
481
            return_error(gs_error_VMerror);
 
482
        }
 
483
        code = gs_memory_retrying_init(rmem, (gs_memory_t *)lmem);
 
484
        if (code < 0) {
 
485
            gs_free_object((gs_memory_t *)lmem, rmem, "gs_malloc_wrap(retrying)");
 
486
            gs_memory_locked_release(lmem);
 
487
            gs_free_object(cmem, lmem, "gs_malloc_wrap(locked)");
 
488
            return code;
 
489
        }
 
490
 
 
491
        *wrapped = (gs_memory_t *)rmem;
 
492
    }
 
493
#  endif /* retrying */
465
494
    return 0;
466
495
}
467
496
 
469
498
gs_malloc_memory_t *
470
499
gs_malloc_wrapped_contents(gs_memory_t *wrapped)
471
500
{
472
 
#ifdef USE_RETRY_AND_LOCKING_MEMORY_WRAPPERS
 
501
#ifdef USE_RETRY_MEMORY_WRAPPER
473
502
    gs_memory_retrying_t *rmem = (gs_memory_retrying_t *)wrapped;
474
 
    gs_memory_locked_t *lmem =
475
 
        (gs_memory_locked_t *)gs_memory_retrying_target(rmem);
476
 
    if (lmem) 
477
 
        return (gs_malloc_memory_t *)gs_memory_locked_target(lmem);
478
 
    return (gs_malloc_memory_t *) wrapped;
479
 
#else
 
503
 
 
504
    return (gs_malloc_memory_t *)gs_memory_retrying_target(rmem);
 
505
#else /* retrying */
480
506
    return (gs_malloc_memory_t *)wrapped;
481
 
#endif 
 
507
#endif /* retrying */
482
508
}
483
509
 
484
510
/* Free the wrapper, and return the wrapped contents. */
485
511
gs_malloc_memory_t *
486
512
gs_malloc_unwrap(gs_memory_t *wrapped)
487
513
{
488
 
#ifdef USE_RETRY_AND_LOCKING_MEMORY_WRAPPERS
 
514
#ifdef USE_RETRY_MEMORY_WRAPPER
489
515
    gs_memory_retrying_t *rmem = (gs_memory_retrying_t *)wrapped;
490
 
    gs_memory_locked_t *lmem =
491
 
        (gs_memory_locked_t *)gs_memory_retrying_target(rmem);
492
 
    gs_memory_t *contents = gs_memory_locked_target(lmem);
 
516
    gs_memory_t *contents = gs_memory_retrying_target(rmem);
493
517
 
494
 
    gs_free_object((gs_memory_t *)lmem, rmem, "gs_malloc_unwrap(retrying)");
495
 
    gs_memory_locked_release(lmem);
496
 
    gs_free_object(contents, lmem, "gs_malloc_unwrap(locked)");
 
518
    gs_free_object(wrapped rmem, "gs_malloc_unwrap(retrying)");
497
519
    return (gs_malloc_memory_t *)contents;
498
520
#else
499
521
    return (gs_malloc_memory_t *)wrapped;
500
 
#endif 
 
522
#endif
501
523
}
502
524
 
503
525
 
513
535
    else 
514
536
        gs_lib_ctx_init((gs_memory_t *)malloc_memory_default);
515
537
 
516
 
#ifdef USE_RETRY_AND_LOCKING_MEMORY_WRAPPERS
 
538
#if defined(USE_RETRY_MEMORY_WRAPPER)
517
539
    gs_malloc_wrap(&memory_t_default, malloc_memory_default);
518
540
#else
519
541
    memory_t_default = (gs_memory_t *)malloc_memory_default;
526
548
void
527
549
gs_malloc_release(gs_memory_t *mem)
528
550
{
529
 
#ifdef USE_RETRY_AND_LOCKING_MEMORY_WRAPPERS
 
551
#ifdef USE_RETRY_MEMORY_WRAPPER 
530
552
    gs_malloc_memory_t * malloc_memory_default = gs_malloc_unwrap(mem);
531
553
#else
532
554
    gs_malloc_memory_t * malloc_memory_default = (gs_malloc_memory_t *)mem;