1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gsmemlok.c 8721 2008-05-09 02:18:14Z ray $ */
15
/* Monitor-locked heap memory allocator */
17
/* Initial version 2/1/98 by John Desrosiers (soho@crl.com) */
18
/* Revised 8/6/98 by L. Peter Deutsch (ghost@aladdin.com) for changes */
19
/* in memory manager API */
20
/* Edited 3/23/1999 by L. Peter Deutsch to remove compiler warnings. */
26
/* Raw memory procedures */
27
static gs_memory_proc_alloc_bytes(gs_locked_alloc_bytes_immovable);
28
static gs_memory_proc_resize_object(gs_locked_resize_object);
29
static gs_memory_proc_free_object(gs_locked_free_object);
30
static gs_memory_proc_stable(gs_locked_stable);
31
static gs_memory_proc_status(gs_locked_status);
32
static gs_memory_proc_free_all(gs_locked_free_all);
33
static gs_memory_proc_consolidate_free(gs_locked_consolidate_free);
35
/* Object memory procedures */
36
static gs_memory_proc_alloc_bytes(gs_locked_alloc_bytes);
37
static gs_memory_proc_alloc_struct(gs_locked_alloc_struct);
38
static gs_memory_proc_alloc_struct(gs_locked_alloc_struct_immovable);
39
static gs_memory_proc_alloc_byte_array(gs_locked_alloc_byte_array);
40
static gs_memory_proc_alloc_byte_array(gs_locked_alloc_byte_array_immovable);
41
static gs_memory_proc_alloc_struct_array(gs_locked_alloc_struct_array);
42
static gs_memory_proc_alloc_struct_array(gs_locked_alloc_struct_array_immovable);
43
static gs_memory_proc_object_size(gs_locked_object_size);
44
static gs_memory_proc_object_type(gs_locked_object_type);
45
static gs_memory_proc_alloc_string(gs_locked_alloc_string);
46
static gs_memory_proc_alloc_string(gs_locked_alloc_string_immovable);
47
static gs_memory_proc_resize_string(gs_locked_resize_string);
48
static gs_memory_proc_free_string(gs_locked_free_string);
49
static gs_memory_proc_register_root(gs_locked_register_root);
50
static gs_memory_proc_unregister_root(gs_locked_unregister_root);
51
static gs_memory_proc_enable_free(gs_locked_enable_free);
52
static const gs_memory_procs_t locked_procs =
54
/* Raw memory procedures */
55
gs_locked_alloc_bytes_immovable,
56
gs_locked_resize_object,
57
gs_locked_free_object,
61
gs_locked_consolidate_free,
62
/* Object memory procedures */
63
gs_locked_alloc_bytes,
64
gs_locked_alloc_struct,
65
gs_locked_alloc_struct_immovable,
66
gs_locked_alloc_byte_array,
67
gs_locked_alloc_byte_array_immovable,
68
gs_locked_alloc_struct_array,
69
gs_locked_alloc_struct_array_immovable,
70
gs_locked_object_size,
71
gs_locked_object_type,
72
gs_locked_alloc_string,
73
gs_locked_alloc_string_immovable,
74
gs_locked_resize_string,
75
gs_locked_free_string,
76
gs_locked_register_root,
77
gs_locked_unregister_root,
81
/* ---------- Public constructors/destructors ---------- */
83
/* Initialize a gs_memory_locked_t */
84
int /* -ve error code or 0 */
85
gs_memory_locked_init(
86
gs_memory_locked_t * lmem, /* allocator to init */
87
gs_memory_t * target /* allocator to monitor lock */
90
lmem->stable_memory = 0;
91
lmem->procs = locked_procs;
92
lmem->target = target;
93
lmem->gs_lib_ctx = target->gs_lib_ctx;
94
lmem->non_gc_memory = (gs_memory_t *)lmem;
96
/* Allocate a monitor to serialize access to structures within */
97
lmem->monitor = gx_monitor_alloc(target);
98
return (lmem->monitor ? 0 : gs_note_error(gs_error_VMerror));
101
/* Release a locked memory manager. */
102
/* Note that this has no effect on the target. */
104
gs_memory_locked_release(gs_memory_locked_t *lmem)
106
gs_memory_free_all((gs_memory_t *)lmem, FREE_ALL_STRUCTURES,
107
"gs_memory_locked_release");
108
gx_monitor_free(lmem->monitor);
111
/* ---------- Accessors ------------- */
113
/* Retrieve this allocator's target */
115
gs_memory_locked_target(const gs_memory_locked_t *lmem)
120
/* -------- Private members just wrap a monitor around a gs_memory_heap --- */
123
* Contrary to our usual practice, we don't use BEGIN/END here, because
124
* that causes some compilers to give bogus error messages.
127
#define DO_MONITORED(call_target)\
128
gs_memory_locked_t * const lmem = (gs_memory_locked_t *)mem;\
130
gx_monitor_enter(lmem->monitor);\
132
gx_monitor_leave(lmem->monitor)
134
#define RETURN_MONITORED(result_type, call_target)\
135
gs_memory_locked_t * const lmem = (gs_memory_locked_t *)mem;\
138
gx_monitor_enter(lmem->monitor);\
140
gx_monitor_leave(lmem->monitor);\
145
gs_locked_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
147
gs_memory_locked_t * const lmem = (gs_memory_locked_t *)mem;
148
gs_memory_t * const target = lmem->target;
150
/* Only free the structures and the allocator itself. */
151
if (mem->stable_memory) {
152
if (mem->stable_memory != mem)
153
gs_memory_free_all(mem->stable_memory, free_mask, cname);
154
if (free_mask & FREE_ALL_ALLOCATOR)
155
mem->stable_memory = 0;
157
if (free_mask & FREE_ALL_STRUCTURES) {
159
* Check for monitor == 0, in case this is called after a
160
* failure during initialization.
163
gx_monitor_free(lmem->monitor);
167
if (free_mask & FREE_ALL_ALLOCATOR)
168
gs_free_object(target, lmem, cname);
171
gs_locked_consolidate_free(gs_memory_t * mem)
174
(*lmem->target->procs.consolidate_free)(lmem->target)
178
gs_locked_alloc_bytes(gs_memory_t * mem, uint size, client_name_t cname)
182
(*lmem->target->procs.alloc_bytes)
183
(lmem->target, size, cname)
187
gs_locked_alloc_bytes_immovable(gs_memory_t * mem, uint size,
192
(*lmem->target->procs.alloc_bytes_immovable)
193
(lmem->target, size, cname)
197
gs_locked_alloc_struct(gs_memory_t * mem, gs_memory_type_ptr_t pstype,
202
(*lmem->target->procs.alloc_struct)
203
(lmem->target, pstype, cname)
207
gs_locked_alloc_struct_immovable(gs_memory_t * mem,
208
gs_memory_type_ptr_t pstype, client_name_t cname)
212
(*lmem->target->procs.alloc_struct_immovable)
213
(lmem->target, pstype, cname)
217
gs_locked_alloc_byte_array(gs_memory_t * mem, uint num_elements, uint elt_size,
222
(*lmem->target->procs.alloc_byte_array)
223
(lmem->target, num_elements, elt_size, cname)
227
gs_locked_alloc_byte_array_immovable(gs_memory_t * mem, uint num_elements,
228
uint elt_size, client_name_t cname)
232
(*lmem->target->procs.alloc_byte_array_immovable)
233
(lmem->target, num_elements, elt_size, cname)
237
gs_locked_alloc_struct_array(gs_memory_t * mem, uint num_elements,
238
gs_memory_type_ptr_t pstype, client_name_t cname)
242
(*lmem->target->procs.alloc_struct_array)
243
(lmem->target, num_elements, pstype, cname)
247
gs_locked_alloc_struct_array_immovable(gs_memory_t * mem, uint num_elements,
248
gs_memory_type_ptr_t pstype, client_name_t cname)
252
(*lmem->target->procs.alloc_struct_array_immovable)
253
(lmem->target, num_elements, pstype, cname)
257
gs_locked_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements,
262
(*lmem->target->procs.resize_object)
263
(lmem->target, obj, new_num_elements, cname)
267
gs_locked_object_size(gs_memory_t * mem, const void *ptr)
271
(*lmem->target->procs.object_size)
275
static gs_memory_type_ptr_t
276
gs_locked_object_type(const gs_memory_t * mem, const void *ptr)
279
gs_memory_type_ptr_t,
280
(*lmem->target->procs.object_type)
285
gs_locked_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
288
(*lmem->target->procs.free_object)
289
(lmem->target, ptr, cname)
293
gs_locked_alloc_string(gs_memory_t * mem, uint nbytes, client_name_t cname)
297
(*lmem->target->procs.alloc_string)
298
(lmem->target, nbytes, cname)
302
gs_locked_alloc_string_immovable(gs_memory_t * mem, uint nbytes,
307
(*lmem->target->procs.alloc_string_immovable)
308
(lmem->target, nbytes, cname)
312
gs_locked_resize_string(gs_memory_t * mem, byte * data, uint old_num,
318
(*lmem->target->procs.resize_string)
319
(lmem->target, data, old_num, new_num, cname)
323
gs_locked_free_string(gs_memory_t * mem, byte * data, uint nbytes,
327
(*lmem->target->procs.free_string)
328
(lmem->target, data, nbytes, cname)
332
gs_locked_register_root(gs_memory_t * mem, gs_gc_root_t * rp,
333
gs_ptr_type_t ptype, void **up, client_name_t cname)
337
(*lmem->target->procs.register_root)
338
(lmem->target, rp, ptype, up, cname)
342
gs_locked_unregister_root(gs_memory_t * mem, gs_gc_root_t * rp,
346
(*lmem->target->procs.unregister_root)
347
(lmem->target, rp, cname)
351
gs_locked_stable(gs_memory_t * mem)
353
if (!mem->stable_memory) {
354
gs_memory_locked_t * const lmem = (gs_memory_locked_t *)mem;
357
gx_monitor_enter(lmem->monitor);
358
stable = gs_memory_stable(lmem->target);
359
if (stable == lmem->target)
360
mem->stable_memory = mem;
362
gs_memory_locked_t *locked_stable = (gs_memory_locked_t *)
363
gs_alloc_bytes(stable, sizeof(*lmem), "gs_locked_stable");
366
int code = gs_memory_locked_init(locked_stable, stable);
369
gs_free_object(stable, locked_stable, "gs_locked_stable");
371
mem->stable_memory = (gs_memory_t *)locked_stable;
374
gx_monitor_leave(lmem->monitor);
376
return mem->stable_memory;
379
gs_locked_status(gs_memory_t * mem, gs_memory_status_t * pstat)
382
(*lmem->target->procs.status)(lmem->target, pstat)
386
gs_locked_enable_free(gs_memory_t * mem, bool enable)
389
(*lmem->target->procs.enable_free)(lmem->target, enable)