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