Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gsmemret.c,v 1.5 2004/08/04 19:36:12 stefan Exp $ */
18
/* Retrying memory allocator */
19
 
20
#include "gx.h"
21
#include "gsmemret.h"
22
#include "gserrors.h"
23
 
24
/* Raw memory procedures */
25
private gs_memory_proc_alloc_bytes(gs_retrying_alloc_bytes_immovable);
26
private gs_memory_proc_resize_object(gs_retrying_resize_object);
27
private gs_memory_proc_free_object(gs_forward_free_object);
28
private gs_memory_proc_stable(gs_retrying_stable);
29
private gs_memory_proc_status(gs_forward_status);
30
private gs_memory_proc_free_all(gs_forward_free_all);
31
private gs_memory_proc_consolidate_free(gs_forward_consolidate_free);
32
 
33
/* Object memory procedures */
34
private gs_memory_proc_alloc_bytes(gs_retrying_alloc_bytes);
35
private gs_memory_proc_alloc_struct(gs_retrying_alloc_struct);
36
private gs_memory_proc_alloc_struct(gs_retrying_alloc_struct_immovable);
37
private gs_memory_proc_alloc_byte_array(gs_retrying_alloc_byte_array);
38
private gs_memory_proc_alloc_byte_array(gs_retrying_alloc_byte_array_immovable);
39
private gs_memory_proc_alloc_struct_array(gs_retrying_alloc_struct_array);
40
private gs_memory_proc_alloc_struct_array(gs_retrying_alloc_struct_array_immovable);
41
private gs_memory_proc_object_size(gs_forward_object_size);
42
private gs_memory_proc_object_type(gs_forward_object_type);
43
private gs_memory_proc_alloc_string(gs_retrying_alloc_string);
44
private gs_memory_proc_alloc_string(gs_retrying_alloc_string_immovable);
45
private gs_memory_proc_resize_string(gs_retrying_resize_string);
46
private gs_memory_proc_free_string(gs_forward_free_string);
47
private gs_memory_proc_register_root(gs_retrying_register_root);
48
private gs_memory_proc_unregister_root(gs_forward_unregister_root);
49
private gs_memory_proc_enable_free(gs_forward_enable_free);
50
private const gs_memory_procs_t retrying_procs = {
51
    /* Raw memory procedures */
52
    gs_retrying_alloc_bytes_immovable,
53
    gs_retrying_resize_object,
54
    gs_forward_free_object,
55
    gs_retrying_stable,
56
    gs_forward_status,
57
    gs_forward_free_all,
58
    gs_forward_consolidate_free,
59
    /* Object memory procedures */
60
    gs_retrying_alloc_bytes,
61
    gs_retrying_alloc_struct,
62
    gs_retrying_alloc_struct_immovable,
63
    gs_retrying_alloc_byte_array,
64
    gs_retrying_alloc_byte_array_immovable,
65
    gs_retrying_alloc_struct_array,
66
    gs_retrying_alloc_struct_array_immovable,
67
    gs_forward_object_size,
68
    gs_forward_object_type,
69
    gs_retrying_alloc_string,
70
    gs_retrying_alloc_string_immovable,
71
    gs_retrying_resize_string,
72
    gs_forward_free_string,
73
    gs_retrying_register_root,
74
    gs_forward_unregister_root,
75
    gs_forward_enable_free
76
};
77
 
78
/* Define a vacuous recovery procedure. */
79
private gs_memory_recover_status_t
80
no_recover_proc(gs_memory_retrying_t *rmem, void *proc_data)
81
{
82
    return RECOVER_STATUS_NO_RETRY;
83
}
84
 
85
/* ---------- Public constructors/destructors ---------- */
86
 
87
/* Initialize a gs_memory_retrying_t */
88
int				/* -ve error code or 0 */
89
gs_memory_retrying_init(
90
		      gs_memory_retrying_t * rmem,	/* allocator to init */
91
		      gs_memory_t * target	/* allocator to wrap */
92
)
93
{
94
    rmem->stable_memory = 0;
95
    rmem->procs = retrying_procs;
96
    rmem->target = target;
97
    rmem->gs_lib_ctx = target->gs_lib_ctx;
98
    rmem->non_gc_memory = (gs_memory_t *)rmem;
99
    gs_memory_retrying_set_recover(rmem, no_recover_proc, NULL);
100
    return 0;
101
}
102
 
103
/* Set the recovery closure of a retrying memory manager. */
104
void
105
gs_memory_retrying_set_recover(gs_memory_retrying_t *rmem,
106
			       gs_memory_recover_proc_t recover_proc,
107
			       void *recover_proc_data)
108
{
109
    rmem->recover_proc = recover_proc;
110
    rmem->recover_proc_data = recover_proc_data;
111
}
112
 
113
/* Release a retrying memory manager. */
114
/* Note that this has no effect on the target. */
115
void
116
gs_memory_retrying_release(gs_memory_retrying_t *rmem)
117
{
118
    gs_memory_free_all((gs_memory_t *)rmem, FREE_ALL_STRUCTURES,
119
		       "gs_memory_retrying_release");
120
}
121
 
122
/* ---------- Accessors ------------- */
123
 
124
/* Retrieve this allocator's target */
125
gs_memory_t *
126
gs_memory_retrying_target(const gs_memory_retrying_t *rmem)
127
{
128
    return rmem->target;
129
}
130
 
131
/* -------- Private members just wrap retrying around a gs_memory --- */
132
 
133
/*
134
 * Contrary to our usual practice, we don't use BEGIN/END here, because
135
 * that causes some compilers to give bogus error messages.
136
 */
137
 
138
#define DO_FORWARD(call_target)\
139
	gs_memory_retrying_t * const rmem = (gs_memory_retrying_t *)mem;\
140
	gs_memory_t *const target = rmem->target;\
141
\
142
	call_target
143
 
144
#define RETURN_RETRYING(result_type, call_target)\
145
	gs_memory_retrying_t * const rmem = (gs_memory_retrying_t *)mem;\
146
	gs_memory_t *const target = rmem->target;\
147
	result_type temp;\
148
	gs_memory_recover_status_t retry = RECOVER_STATUS_RETRY_OK;\
149
\
150
	for (;;) {\
151
	    temp = call_target;\
152
	    if (temp != 0 || retry != RECOVER_STATUS_RETRY_OK)\
153
		break;\
154
	    retry = rmem->recover_proc(rmem, rmem->recover_proc_data);\
155
	}\
156
	return temp
157
 
158
/* Procedures */
159
private void
160
gs_forward_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
161
{
162
    gs_memory_retrying_t * const rmem = (gs_memory_retrying_t *)mem;
163
    gs_memory_t * const target = rmem->target;
164
 
165
    /* Only free the structures and the allocator itself. */
166
    rmem->target = 0;
167
    if (free_mask & FREE_ALL_ALLOCATOR)
168
	gs_free_object(target, rmem, cname);
169
}
170
private void
171
gs_forward_consolidate_free(gs_memory_t * mem)
172
{
173
    DO_FORWARD(target->procs.consolidate_free(target));
174
}
175
private byte *
176
gs_retrying_alloc_bytes(gs_memory_t * mem, uint size, client_name_t cname)
177
{
178
    RETURN_RETRYING(
179
		    byte *,
180
		    target->procs.alloc_bytes(target, size, cname)
181
		    );
182
}
183
private byte *
184
gs_retrying_alloc_bytes_immovable(gs_memory_t * mem, uint size,
185
				client_name_t cname)
186
{
187
    RETURN_RETRYING(
188
		    byte *,
189
		    target->procs.alloc_bytes_immovable(target, size, cname)
190
		    );
191
}
192
private void *
193
gs_retrying_alloc_struct(gs_memory_t * mem, gs_memory_type_ptr_t pstype,
194
		       client_name_t cname)
195
{
196
    RETURN_RETRYING(
197
		    void *,
198
		    target->procs.alloc_struct(target, pstype, cname)
199
		    );
200
}
201
private void *
202
gs_retrying_alloc_struct_immovable(gs_memory_t * mem,
203
			   gs_memory_type_ptr_t pstype, client_name_t cname)
204
{
205
    RETURN_RETRYING(
206
		    void *,
207
		    target->procs.alloc_struct_immovable(target, pstype, cname)
208
		    );
209
}
210
private byte *
211
gs_retrying_alloc_byte_array(gs_memory_t * mem, uint num_elements, uint elt_size,
212
			   client_name_t cname)
213
{
214
    RETURN_RETRYING(
215
		    byte *,
216
		    target->procs.alloc_byte_array(target, num_elements,
217
						   elt_size, cname)
218
		    );
219
}
220
private byte *
221
gs_retrying_alloc_byte_array_immovable(gs_memory_t * mem, uint num_elements,
222
				     uint elt_size, client_name_t cname)
223
{
224
    RETURN_RETRYING(
225
		    byte *,
226
		    target->procs.alloc_byte_array_immovable(target,
227
							num_elements, elt_size,
228
							cname)
229
		    );
230
}
231
private void *
232
gs_retrying_alloc_struct_array(gs_memory_t * mem, uint num_elements,
233
			   gs_memory_type_ptr_t pstype, client_name_t cname)
234
{
235
    RETURN_RETRYING(
236
		    void *,
237
		    target->procs.alloc_struct_array(target, num_elements,
238
						     pstype, cname)
239
		    );
240
}
241
private void *
242
gs_retrying_alloc_struct_array_immovable(gs_memory_t * mem, uint num_elements,
243
			   gs_memory_type_ptr_t pstype, client_name_t cname)
244
{
245
    RETURN_RETRYING(
246
		    void *,
247
		    target->procs.alloc_struct_array_immovable(target,
248
							num_elements, pstype,
249
						        cname)
250
		    );
251
}
252
private void *
253
gs_retrying_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements,
254
			client_name_t cname)
255
{
256
    RETURN_RETRYING(
257
		    void *,
258
		    target->procs.resize_object(target, obj, new_num_elements,
259
						cname)
260
		    );
261
}
262
private uint
263
gs_forward_object_size(gs_memory_t * mem, const void *ptr)
264
{
265
    DO_FORWARD(return target->procs.object_size(target, ptr));
266
}
267
private gs_memory_type_ptr_t
268
gs_forward_object_type(gs_memory_t * mem, const void *ptr)
269
{
270
    DO_FORWARD(return target->procs.object_type(target, ptr));
271
}
272
private void
273
gs_forward_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
274
{
275
    DO_FORWARD(target->procs.free_object(target, ptr, cname));
276
}
277
private byte *
278
gs_retrying_alloc_string(gs_memory_t * mem, uint nbytes, client_name_t cname)
279
{
280
    RETURN_RETRYING(
281
		    byte *,
282
		    target->procs.alloc_string(target, nbytes, cname)
283
		    );
284
}
285
private byte *
286
gs_retrying_alloc_string_immovable(gs_memory_t * mem, uint nbytes,
287
				 client_name_t cname)
288
{
289
    RETURN_RETRYING(
290
		    byte *,
291
		    target->procs.alloc_string_immovable(target, nbytes, cname)
292
		    );
293
}
294
private byte *
295
gs_retrying_resize_string(gs_memory_t * mem, byte * data, uint old_num,
296
			uint new_num,
297
			client_name_t cname)
298
{
299
    RETURN_RETRYING(
300
		    byte *,
301
		    target->procs.resize_string(target, data, old_num, new_num,
302
						cname)
303
		    );
304
}
305
private void
306
gs_forward_free_string(gs_memory_t * mem, byte * data, uint nbytes,
307
		      client_name_t cname)
308
{
309
    DO_FORWARD(target->procs.free_string(target, data, nbytes, cname));
310
}
311
private int
312
gs_retrying_register_root(gs_memory_t * mem, gs_gc_root_t * rp,
313
			gs_ptr_type_t ptype, void **up, client_name_t cname)
314
{
315
    RETURN_RETRYING(
316
		    int,
317
		    target->procs.register_root(target, rp, ptype, up, cname)
318
		    );
319
}
320
private void
321
gs_forward_unregister_root(gs_memory_t * mem, gs_gc_root_t * rp,
322
			  client_name_t cname)
323
{
324
    DO_FORWARD(target->procs.unregister_root(target, rp, cname));
325
}
326
private gs_memory_t *
327
gs_retrying_stable(gs_memory_t * mem)
328
{
329
    if (!mem->stable_memory) {
330
	gs_memory_retrying_t * const rmem = (gs_memory_retrying_t *)mem;
331
	gs_memory_t *stable = gs_memory_stable(rmem->target);
332
 
333
	if (stable == rmem->target)
334
	    mem->stable_memory = mem;
335
	else {
336
	    gs_memory_retrying_t *retrying_stable = (gs_memory_retrying_t *)
337
		gs_alloc_bytes(stable, sizeof(*rmem), "gs_retrying_stable");
338
 
339
	    if (retrying_stable) {
340
		int code = gs_memory_retrying_init(retrying_stable, stable);
341
 
342
		if (code < 0)
343
		    gs_free_object(stable, retrying_stable, "gs_retrying_stable");
344
		else
345
		    mem->stable_memory = (gs_memory_t *)retrying_stable;
346
	    }
347
	}
348
    }
349
    return mem->stable_memory;
350
}
351
private void
352
gs_forward_status(gs_memory_t * mem, gs_memory_status_t * pstat)
353
{
354
    DO_FORWARD(target->procs.status(target, pstat));
355
}
356
private void
357
gs_forward_enable_free(gs_memory_t * mem, bool enable)
358
{
359
    DO_FORWARD(target->procs.enable_free(target, enable));
360
}