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