xref: /plan9/sys/src/cmd/gs/src/gsmemraw.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1998, 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: gsmemraw.h,v 1.8 2004/08/04 19:36:12 stefan Exp $ */
18 /* Client interface for "raw memory" allocator */
19 
20 /* Initial version 02/03/1998 by John Desrosiers (soho@crl.com) */
21 /* Completely rewritten 6/26/1998 by L. Peter Deutsch <ghost@aladdin.com> */
22 
23 #ifndef gsmemraw_INCLUDED
24 #  define gsmemraw_INCLUDED
25 
26 #if 0
27 
28 /* gsmemraw was an abstract base class.
29  * it is no longer in use, instead use the concrete base class is gs_memory_t
30  * since gs_memory_t contains interfaces that must be availiable throughout the system
31  * is is unadvisable to have a class below it without these.
32  */
33 
34 
35 /*
36  * This interface provides minimal memory allocation and freeing capability.
37  * It is meant to be used for "wholesale" allocation of blocks -- typically,
38  * but not only, via malloc -- which are then divided up into "retail"
39  * objects.  However, since it is a subset (superclass) of the "retail"
40  * interface defined in gsmemory.h, retail allocators implement it as
41  * well, and in fact the malloc interface defined in gsmalloc.h is used for
42  * both wholesale and retail allocation.
43  */
44 
45 /*
46  * Define the structure for reporting memory manager statistics.
47  */
48 typedef struct gs_memory_status_s {
49     /*
50      * "Allocated" space is the total amount of space acquired from
51      * the parent of the memory manager.  It includes space used for
52      * allocated data, space available for allocation, and overhead.
53      */
54     ulong allocated;
55     /*
56      * "Used" space is the amount of space used by allocated data
57      * plus overhead.
58      */
59     ulong used;
60 } gs_memory_status_t;
61 
62 /* Define the abstract type for the memory manager. */
63 #ifndef gs_raw_memory_t_DEFINED
64 #define gs_raw_memory_t_DEFINED
65 typedef struct gs_raw_memory_s gs_raw_memory_t;
66 #endif
67 
68 /* Define the procedures for raw memory management.  Memory managers have no
69  * standard constructor: each implementation defines its own, and is
70  * responsible for calling its superclass' initialization code first.
71  * Similarly, each implementation's destructor (release) must first take
72  * care of its own cleanup and then call the superclass' release.
73  *
74  * The allocation procedures must align objects as strictly as malloc.
75  * Formerly, the procedures were required to align objects as strictly
76  * as the compiler aligned structure members.  However, the ANSI C standard
77  * does not require this -- it only requires malloc to align blocks
78  * strictly enough to prevent hardware access faults.  Thus, for example,
79  * on the x86, malloc need not align blocks at all.  And in fact, we have
80  * found one compiler (Microsoft VC 6) that 8-byte aligns 'double' members
81  * of structures, but whose malloc only 4-byte aligns its blocks.
82  * Ghostscript allocators could enforce the stricter alignment, but the
83  * few dozen lines of code required to implement this were rejected during
84  * code review as introducing too much risk for too little payoff.  As a
85  * consequence of this,
86  *
87  *	CLIENTS CANNOT ASSUME THAT BLOCKS RETURNED BY ANY OF THE ALLOCATION
88  *	PROCEDURES ARE ALIGNED ANY MORE STRICTLY THAN IS REQUIRED BY THE
89  *	HARDWARE.
90  *
91  * In particular, clients cannot assume that blocks returned by an allocator
92  * can be processed efficiently in any unit larger than a single byte: there
93  * is no guarantee that accessing any larger quantity will not require two
94  * memory accesses at the hardware level.  Clients that want to process data
95  * efficiently in larger units must use ALIGNMENT_MOD to determine the
96  * actual alignment of the data in memory.
97  */
98 
99 		/*
100 		 * Allocate bytes.  The bytes are always aligned maximally
101 		 * if the processor requires alignment.
102 		 *
103 		 * Note that the object memory level can allocate bytes as
104 		 * either movable or immovable: raw memory blocks are
105 		 * always immovable.
106 		 */
107 
108 #define gs_memory_t_proc_alloc_bytes(proc, mem_t)\
109   byte *proc(mem_t *mem, uint nbytes, client_name_t cname)
110 
111 #define gs_alloc_bytes_immovable(mem, nbytes, cname)\
112   ((mem)->procs.alloc_bytes_immovable(mem, nbytes, cname))
113 
114 		/*
115 		 * Resize an object to a new number of elements.  At the raw
116 		 * memory level, the "element" is a byte; for object memory
117 		 * (gsmemory.h), the object may be an an array of either
118 		 * bytes or structures.  The new size may be larger than,
119 		 * the same as, or smaller than the old.  If the new size is
120 		 * the same as the old, resize_object returns the same
121 		 * object; otherwise, it preserves the first min(old_size,
122 		 * new_size) bytes of the object's contents.
123 		 */
124 
125 #define gs_memory_t_proc_resize_object(proc, mem_t)\
126   void *proc(mem_t *mem, void *obj, uint new_num_elements,\
127 	     client_name_t cname)
128 
129 #define gs_resize_object(mem, obj, newn, cname)\
130   ((mem)->procs.resize_object(mem, obj, newn, cname))
131 
132 		/*
133 		 * Free an object (at the object memory level, this includes
134 		 * everything except strings).  Note: data == 0 must be
135 		 * allowed, and must be a no-op.
136 		 */
137 
138 #define gs_memory_t_proc_free_object(proc, mem_t)\
139   void proc(mem_t *mem, void *data, client_name_t cname)
140 
141 #define gs_free_object(mem, data, cname)\
142   ((mem)->procs.free_object(mem, data, cname))
143 
144 		/*
145 		 * Report status (assigned, used).
146 		 */
147 
148 #define gs_memory_t_proc_status(proc, mem_t)\
149   void proc(mem_t *mem, gs_memory_status_t *status)
150 
151 #define gs_memory_status(mem, pst)\
152   ((mem)->procs.status(mem, pst))
153 
154 		/*
155 		 * Return the stable allocator for this allocator.  The
156 		 * stable allocator allocates from the same heap and in
157 		 * the same VM space, but is not subject to save and restore.
158 		 * (It is the client's responsibility to avoid creating
159 		 * dangling pointers.)
160 		 *
161 		 * Note that the stable allocator may be the same allocator
162 		 * as this one.
163 		 */
164 
165 #define gs_memory_t_proc_stable(proc, mem_t)\
166   mem_t *proc(mem_t *mem)
167 
168 #define gs_memory_stable(mem)\
169   ((mem)->procs.stable(mem))
170 
171 		/*
172 		 * Free one or more of: data memory acquired by the allocator
173 		 * (FREE_ALL_DATA), overhead structures other than the
174 		 * allocator itself (FREE_ALL_STRUCTURES), and the allocator
175 		 * itself (FREE_ALL_ALLOCATOR).  Note that this requires
176 		 * allocators to keep track of all the memory they have ever
177 		 * acquired, and where they acquired it.  Note that this
178 		 * operation propagates to the stable allocator (if
179 		 * different).
180 		 */
181 
182 #define FREE_ALL_DATA 1
183 #define FREE_ALL_STRUCTURES 2
184 #define FREE_ALL_ALLOCATOR 4
185 #define FREE_ALL_EVERYTHING\
186   (FREE_ALL_DATA | FREE_ALL_STRUCTURES | FREE_ALL_ALLOCATOR)
187 
188 #define gs_memory_t_proc_free_all(proc, mem_t)\
189   void proc(mem_t *mem, uint free_mask, client_name_t cname)
190 
191 #define gs_memory_free_all(mem, free_mask, cname)\
192   ((mem)->procs.free_all(mem, free_mask, cname))
193 /* Backward compatibility */
194 #define gs_free_all(mem)\
195   gs_memory_free_all(mem, FREE_ALL_DATA, "(free_all)")
196 
197 		/*
198 		 * Consolidate free space.  This may be used as part of (or
199 		 * as an alternative to) garbage collection, or before
200 		 * giving up on an attempt to allocate.
201 		 */
202 
203 #define gs_memory_t_proc_consolidate_free(proc, mem_t)\
204   void proc(mem_t *mem)
205 
206 #define gs_consolidate_free(mem)\
207   ((mem)->procs.consolidate_free(mem))
208 
209 /* Define the members of the procedure structure. */
210 #define gs_raw_memory_procs(mem_t)\
211     gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\
212     gs_memory_t_proc_resize_object((*resize_object), mem_t);\
213     gs_memory_t_proc_free_object((*free_object), mem_t);\
214     gs_memory_t_proc_stable((*stable), mem_t);\
215     gs_memory_t_proc_status((*status), mem_t);\
216     gs_memory_t_proc_free_all((*free_all), mem_t);\
217     gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t)
218 
219 /*
220  * Define an abstract raw-memory allocator instance.
221  * Subclasses may have additional state.
222  */
223 typedef struct gs_raw_memory_procs_s {
224     gs_raw_memory_procs(gs_raw_memory_t);
225 } gs_raw_memory_procs_t;
226 
227 
228 
229 struct gs_raw_memory_s {
230     gs_raw_memory_t *stable_memory;	/* cache the stable allocator */
231     gs_raw_memory_procs_t procs;
232 };
233 
234 #endif /* 0 */
235 #endif /* gsmemraw_INCLUDED */
236