xref: /plan9/sys/src/cmd/gs/src/gsmemory.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1993, 1996, 1997, 1998, 1999, 2001 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: gsmemory.h,v 1.8 2004/08/04 19:36:12 stefan Exp $ */
18 /* Client interface for memory allocation */
19 
20 /*
21  * The allocator knows about two basic kinds of memory: objects, which are
22  * aligned and cannot have pointers to their interior, and strings, which
23  * are not aligned and which can have interior references.
24  *
25  * Note: OBJECTS ARE NOT GUARANTEED to be aligned any more strictly than
26  * required by the hardware, regardless of the value of obj_align_mod.  In
27  * other words, whether ALIGNMENT_MOD(ptr, obj_align_mod) will be zero
28  * depends on the alignment provided by the underlying allocator.
29  * Most systems ensure this, but Microsoft VC 6 in particular does not.
30  * See gsmemraw.h for more information about this.
31  *
32  * The standard allocator is designed to interface to a garbage collector,
33  * although it does not include or call one.  The allocator API recognizes
34  * that the garbage collector may move objects, relocating pointers to them;
35  * the API provides for allocating both movable (the default) and immovable
36  * objects.  Clients must not attempt to resize immovable objects, and must
37  * not create references to substrings of immovable strings.
38  */
39 
40 #ifndef gsmemory_INCLUDED
41 #  define gsmemory_INCLUDED
42 
43 #include "gstypes.h"		/* for gs_bytestring */
44 #include "gslibctx.h"
45 
46 /* Define the opaque type for a structure descriptor. */
47 typedef struct gs_memory_struct_type_s gs_memory_struct_type_t;
48 typedef const gs_memory_struct_type_t *gs_memory_type_ptr_t;
49 
50 /* Define the opaque type for an allocator. */
51 /* (The actual structure is defined later in this file.) */
52 #ifndef gs_memory_DEFINED
53 #  define gs_memory_DEFINED
54 typedef struct gs_memory_s gs_memory_t;
55 #endif
56 
57 /* Define the opaque type for a pointer type. */
58 typedef struct gs_ptr_procs_s gs_ptr_procs_t;
59 typedef const gs_ptr_procs_t *gs_ptr_type_t;
60 
61 /* Define the opaque type for a GC root. */
62 typedef struct gs_gc_root_s gs_gc_root_t;
63 
64 	/* Accessors for structure types. */
65 
66 typedef client_name_t struct_name_t;
67 
68 /* Get the size of a structure from the descriptor. */
69 uint gs_struct_type_size(gs_memory_type_ptr_t);
70 
71 /* Get the name of a structure from the descriptor. */
72 struct_name_t gs_struct_type_name(gs_memory_type_ptr_t);
73 
74 #define gs_struct_type_name_string(styp)\
75   ((const char *)gs_struct_type_name(styp))
76 
77 /*
78  * Define the structure for reporting memory manager statistics.
79  */
80 typedef struct gs_memory_status_s {
81     /*
82      * "Allocated" space is the total amount of space acquired from
83      * the parent of the memory manager.  It includes space used for
84      * allocated data, space available for allocation, and overhead.
85      */
86     ulong allocated;
87     /*
88      * "Used" space is the amount of space used by allocated data
89      * plus overhead.
90      */
91     ulong used;
92 } gs_memory_status_t;
93 
94 		/*
95 		 * Allocate bytes.  The bytes are always aligned maximally
96 		 * if the processor requires alignment.
97 		 *
98 		 * Note that the object memory level can allocate bytes as
99 		 * either movable or immovable: raw memory blocks are
100 		 * always immovable.
101 		 */
102 
103 #define gs_memory_t_proc_alloc_bytes(proc, mem_t)\
104   byte *proc(mem_t *mem, uint nbytes, client_name_t cname)
105 
106 #define gs_alloc_bytes_immovable(mem, nbytes, cname)\
107   ((mem)->procs.alloc_bytes_immovable(mem, nbytes, cname))
108 
109 		/*
110 		 * Resize an object to a new number of elements.  At the raw
111 		 * memory level, the "element" is a byte; for object memory
112 		 * (gsmemory.h), the object may be an an array of either
113 		 * bytes or structures.  The new size may be larger than,
114 		 * the same as, or smaller than the old.  If the new size is
115 		 * the same as the old, resize_object returns the same
116 		 * object; otherwise, it preserves the first min(old_size,
117 		 * new_size) bytes of the object's contents.
118 		 */
119 
120 #define gs_memory_t_proc_resize_object(proc, mem_t)\
121   void *proc(mem_t *mem, void *obj, uint new_num_elements,\
122 	     client_name_t cname)
123 
124 #define gs_resize_object(mem, obj, newn, cname)\
125   ((mem)->procs.resize_object(mem, obj, newn, cname))
126 
127 		/*
128 		 * Free an object (at the object memory level, this includes
129 		 * everything except strings).  Note: data == 0 must be
130 		 * allowed, and must be a no-op.
131 		 */
132 
133 #define gs_memory_t_proc_free_object(proc, mem_t)\
134   void proc(mem_t *mem, void *data, client_name_t cname)
135 
136 #define gs_free_object(mem, data, cname)\
137   ((mem)->procs.free_object(mem, data, cname))
138 
139 		/*
140 		 * Report status (assigned, used).
141 		 */
142 
143 #define gs_memory_t_proc_status(proc, mem_t)\
144   void proc(mem_t *mem, gs_memory_status_t *status)
145 
146 #define gs_memory_status(mem, pst)\
147   ((mem)->procs.status(mem, pst))
148 
149 		/*
150 		 * Return the stable allocator for this allocator.  The
151 		 * stable allocator allocates from the same heap and in
152 		 * the same VM space, but is not subject to save and restore.
153 		 * (It is the client's responsibility to avoid creating
154 		 * dangling pointers.)
155 		 *
156 		 * Note that the stable allocator may be the same allocator
157 		 * as this one.
158 		 */
159 
160 #define gs_memory_t_proc_stable(proc, mem_t)\
161   mem_t *proc(mem_t *mem)
162 
163 #define gs_memory_stable(mem)\
164   ((mem)->procs.stable(mem))
165 
166 		/*
167 		 * Free one or more of: data memory acquired by the allocator
168 		 * (FREE_ALL_DATA), overhead structures other than the
169 		 * allocator itself (FREE_ALL_STRUCTURES), and the allocator
170 		 * itself (FREE_ALL_ALLOCATOR).  Note that this requires
171 		 * allocators to keep track of all the memory they have ever
172 		 * acquired, and where they acquired it.  Note that this
173 		 * operation propagates to the stable allocator (if
174 		 * different).
175 		 */
176 
177 #define FREE_ALL_DATA 1
178 #define FREE_ALL_STRUCTURES 2
179 #define FREE_ALL_ALLOCATOR 4
180 #define FREE_ALL_EVERYTHING\
181   (FREE_ALL_DATA | FREE_ALL_STRUCTURES | FREE_ALL_ALLOCATOR)
182 
183 #define gs_memory_t_proc_free_all(proc, mem_t)\
184   void proc(mem_t *mem, uint free_mask, client_name_t cname)
185 
186 #define gs_memory_free_all(mem, free_mask, cname)\
187   ((mem)->procs.free_all(mem, free_mask, cname))
188 /* Backward compatibility */
189 #define gs_free_all(mem)\
190   gs_memory_free_all(mem, FREE_ALL_DATA, "(free_all)")
191 
192 		/*
193 		 * Consolidate free space.  This may be used as part of (or
194 		 * as an alternative to) garbage collection, or before
195 		 * giving up on an attempt to allocate.
196 		 */
197 
198 #define gs_memory_t_proc_consolidate_free(proc, mem_t)\
199   void proc(mem_t *mem)
200 
201 #define gs_consolidate_free(mem)\
202   ((mem)->procs.consolidate_free(mem))
203 
204 /* Define the members of the procedure structure. */
205 #define gs_raw_memory_procs(mem_t)\
206     gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\
207     gs_memory_t_proc_resize_object((*resize_object), mem_t);\
208     gs_memory_t_proc_free_object((*free_object), mem_t);\
209     gs_memory_t_proc_stable((*stable), mem_t);\
210     gs_memory_t_proc_status((*status), mem_t);\
211     gs_memory_t_proc_free_all((*free_all), mem_t);\
212     gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t)
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 /*
223  * Define the memory manager procedural interface.
224  */
225 typedef struct gs_memory_procs_s {
226 
227     gs_raw_memory_procs(gs_memory_t);
228 
229     /* Redefine inherited procedures with the new allocator type. */
230 
231 #define gs_memory_proc_alloc_bytes(proc)\
232   gs_memory_t_proc_alloc_bytes(proc, gs_memory_t)
233 #define gs_memory_proc_resize_object(proc)\
234   gs_memory_t_proc_resize_object(proc, gs_memory_t)
235 #define gs_memory_proc_free_object(proc)\
236   gs_memory_t_proc_free_object(proc, gs_memory_t)
237 #define gs_memory_proc_stable(proc)\
238   gs_memory_t_proc_stable(proc, gs_memory_t)
239 #define gs_memory_proc_status(proc)\
240   gs_memory_t_proc_status(proc, gs_memory_t)
241 #define gs_memory_proc_free_all(proc)\
242   gs_memory_t_proc_free_all(proc, gs_memory_t)
243 #define gs_memory_proc_consolidate_free(proc)\
244   gs_memory_t_proc_consolidate_free(proc, gs_memory_t)
245 
246     /*
247      * Allocate possibly movable bytes.  (We inherit allocating immovable
248      * bytes from the raw memory allocator.)
249      */
250 
251 #define gs_alloc_bytes(mem, nbytes, cname)\
252   (*(mem)->procs.alloc_bytes)(mem, nbytes, cname)
253     gs_memory_proc_alloc_bytes((*alloc_bytes));
254 
255     /*
256      * Allocate a structure.
257      */
258 
259 #define gs_memory_proc_alloc_struct(proc)\
260   void *proc(gs_memory_t *mem, gs_memory_type_ptr_t pstype,\
261     client_name_t cname)
262 #define gs_alloc_struct(mem, typ, pstype, cname)\
263   (typ *)(*(mem)->procs.alloc_struct)(mem, pstype, cname)
264     gs_memory_proc_alloc_struct((*alloc_struct));
265 #define gs_alloc_struct_immovable(mem, typ, pstype, cname)\
266   (typ *)(*(mem)->procs.alloc_struct_immovable)(mem, pstype, cname)
267     gs_memory_proc_alloc_struct((*alloc_struct_immovable));
268 
269     /*
270      * Allocate an array of bytes.
271      */
272 
273 #define gs_memory_proc_alloc_byte_array(proc)\
274   byte *proc(gs_memory_t *mem, uint num_elements, uint elt_size,\
275     client_name_t cname)
276 #define gs_alloc_byte_array(mem, nelts, esize, cname)\
277   (*(mem)->procs.alloc_byte_array)(mem, nelts, esize, cname)
278     gs_memory_proc_alloc_byte_array((*alloc_byte_array));
279 #define gs_alloc_byte_array_immovable(mem, nelts, esize, cname)\
280   (*(mem)->procs.alloc_byte_array_immovable)(mem, nelts, esize, cname)
281     gs_memory_proc_alloc_byte_array((*alloc_byte_array_immovable));
282 
283     /*
284      * Allocate an array of structures.
285      */
286 
287 #define gs_memory_proc_alloc_struct_array(proc)\
288   void *proc(gs_memory_t *mem, uint num_elements,\
289     gs_memory_type_ptr_t pstype, client_name_t cname)
290 #define gs_alloc_struct_array(mem, nelts, typ, pstype, cname)\
291   (typ *)(*(mem)->procs.alloc_struct_array)(mem, nelts, pstype, cname)
292     gs_memory_proc_alloc_struct_array((*alloc_struct_array));
293 #define gs_alloc_struct_array_immovable(mem, nelts, typ, pstype, cname)\
294  (typ *)(*(mem)->procs.alloc_struct_array_immovable)(mem, nelts, pstype, cname)
295     gs_memory_proc_alloc_struct_array((*alloc_struct_array_immovable));
296 
297     /*
298      * Get the size of an object (anything except a string).
299      */
300 
301 #define gs_memory_proc_object_size(proc)\
302   uint proc(gs_memory_t *mem, const void *obj)
303 #define gs_object_size(mem, obj)\
304   (*(mem)->procs.object_size)(mem, obj)
305     gs_memory_proc_object_size((*object_size));
306 
307     /*
308      * Get the type of an object (anything except a string).
309      * The value returned for byte objects is useful only for
310      * printing.
311      */
312 
313 #define gs_memory_proc_object_type(proc)\
314   gs_memory_type_ptr_t proc(gs_memory_t *mem, const void *obj)
315 #define gs_object_type(mem, obj)\
316   (*(mem)->procs.object_type)(mem, obj)
317     gs_memory_proc_object_type((*object_type));
318 
319     /*
320      * Allocate a string (unaligned bytes).
321      */
322 
323 #define gs_memory_proc_alloc_string(proc)\
324   byte *proc(gs_memory_t *mem, uint nbytes, client_name_t cname)
325 #define gs_alloc_string(mem, nbytes, cname)\
326   (*(mem)->procs.alloc_string)(mem, nbytes, cname)
327     gs_memory_proc_alloc_string((*alloc_string));
328 #define gs_alloc_string_immovable(mem, nbytes, cname)\
329   (*(mem)->procs.alloc_string_immovable)(mem, nbytes, cname)
330     gs_memory_proc_alloc_string((*alloc_string_immovable));
331 
332     /*
333      * Resize a string.  The specification is the same as resize_object
334      * except that the element size is always a byte.
335      */
336 
337 #define gs_memory_proc_resize_string(proc)\
338   byte *proc(gs_memory_t *mem, byte *data, uint old_num, uint new_num,\
339     client_name_t cname)
340 #define gs_resize_string(mem, data, oldn, newn, cname)\
341   (*(mem)->procs.resize_string)(mem, data, oldn, newn, cname)
342     gs_memory_proc_resize_string((*resize_string));
343 
344     /*
345      * Free a string.
346      */
347 
348 #define gs_memory_proc_free_string(proc)\
349   void proc(gs_memory_t *mem, byte *data, uint nbytes,\
350     client_name_t cname)
351 #define gs_free_string(mem, data, nbytes, cname)\
352   (*(mem)->procs.free_string)(mem, data, nbytes, cname)
353     gs_memory_proc_free_string((*free_string));
354 
355     /*
356      * Register a root for the garbage collector.  root = NULL
357      * asks the memory manager to allocate the root object
358      * itself (immovable, in the manager's parent): this is the usual
359      * way to call this procedure.
360      */
361 
362 #define gs_memory_proc_register_root(proc)\
363   int proc(gs_memory_t *mem, gs_gc_root_t *root, gs_ptr_type_t ptype,\
364     void **pp, client_name_t cname)
365 #define gs_register_root(mem, root, ptype, pp, cname)\
366   (*(mem)->procs.register_root)(mem, root, ptype, pp, cname)
367     gs_memory_proc_register_root((*register_root));
368 
369     /*
370      * Unregister a root.  The root object itself will be freed iff
371      * it was allocated by gs_register_root.
372      */
373 
374 #define gs_memory_proc_unregister_root(proc)\
375   void proc(gs_memory_t *mem, gs_gc_root_t *root, client_name_t cname)
376 #define gs_unregister_root(mem, root, cname)\
377   (*(mem)->procs.unregister_root)(mem, root, cname)
378     gs_memory_proc_unregister_root((*unregister_root));
379 
380     /*
381      * Enable or disable the freeing operations: when disabled,
382      * these operations return normally but do nothing.  The
383      * garbage collector and the PostScript interpreter
384      * 'restore' operator need to temporarily disable the
385      * freeing functions of (an) allocator(s) while running
386      * finalization procedures.
387      */
388 
389 #define gs_memory_proc_enable_free(proc)\
390   void proc(gs_memory_t *mem, bool enable)
391 #define gs_enable_free(mem, enable)\
392   (*(mem)->procs.enable_free)(mem, enable)
393     gs_memory_proc_enable_free((*enable_free));
394 
395 } gs_memory_procs_t;
396 
397 /*
398  * Define versions of the freeing procedures that are applicable even if the
399  * pointer is declared as const T *.  These are intended for use where a
400  * structure contains a pointer member whose referent is declared as const
401  * because it is const for all ordinary clients.
402  */
403 void gs_free_const_object(gs_memory_t *mem, const void *data,
404 			  client_name_t cname);
405 void gs_free_const_string(gs_memory_t *mem, const byte *data, uint nbytes,
406 			  client_name_t cname);
407 
408 /*
409  * Free a [const] bytestring.  Note that this is *not* a member procedure of
410  * the allocator: it calls the free_object or free_string procedure.
411  */
412 void gs_free_bytestring(gs_memory_t *mem, gs_bytestring *pbs,
413 			client_name_t cname);
414 void gs_free_const_bytestring(gs_memory_t *mem, gs_const_bytestring *pbs,
415 			      client_name_t cname);
416 
417 /*
418  * Either allocate (if obj == 0) or resize (if obj != 0) a structure array.
419  * If obj != 0, pstype is used only for checking (in DEBUG configurations).
420  */
421 void *gs_resize_struct_array(gs_memory_t *mem, void *obj, uint num_elements,
422 			     gs_memory_type_ptr_t pstype,
423 			     client_name_t cname);
424 
425 /* Register a structure root.  This just calls gs_register_root. */
426 int gs_register_struct_root(gs_memory_t *mem, gs_gc_root_t *root,
427 			    void **pp, client_name_t cname);
428 
429 /* Define no-op freeing procedures for use by enable_free. */
430 gs_memory_proc_free_object(gs_ignore_free_object);
431 gs_memory_proc_free_string(gs_ignore_free_string);
432 
433 /* Define a no-op consolidation procedure. */
434 gs_memory_proc_consolidate_free(gs_ignore_consolidate_free);
435 
436 /*
437  * Allocate a structure using a "raw memory" allocator.  Note that this does
438  * not retain the identity of the structure.  Note also that it returns a
439  * void *, and does not take the type of the returned pointer as a
440  * parameter.
441  */
442 void *gs_raw_alloc_struct_immovable(gs_memory_t * rmem,
443 				    gs_memory_type_ptr_t pstype,
444 				    client_name_t cname);
445 
446 typedef struct pl_mem_node_s pl_mem_node_t;
447 
448 /*
449  * Define an abstract allocator instance.
450  * Subclasses may have state as well
451  *
452  * stable_memory: no save or restore, maybe gc-ed
453  *                non-gc allocators stable_memory == this
454  *
455  * gs_lib_ctx: pointer to a library context
456  *
457  * head: is only used by pl_alloc in a pcl/pxl only system to track memory
458  *
459  * non_gc_memory: a garabge collecting allocator requires a "parent" who doesn't gc
460  *                non-gc allocators non_gc_memory == this
461  */
462 #define gs_memory_common\
463 	gs_memory_t *stable_memory;\
464 	gs_memory_procs_t procs;\
465         gs_lib_ctx_t *gs_lib_ctx;\
466         pl_mem_node_t *head;\
467         gs_memory_t *non_gc_memory
468 
469 
470 
471 struct gs_memory_s {
472     gs_memory_common;
473 };
474 
475 #endif /* gsmemory_INCLUDED */
476