1 /*@z31.c:Memory Allocator:DebugMemory()@**************************************/
2 /* */
3 /* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39) */
4 /* COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston */
5 /* */
6 /* Jeffrey H. Kingston (jeff@it.usyd.edu.au) */
7 /* School of Information Technologies */
8 /* The University of Sydney 2006 */
9 /* AUSTRALIA */
10 /* */
11 /* This program is free software; you can redistribute it and/or modify */
12 /* it under the terms of the GNU General Public License as published by */
13 /* the Free Software Foundation; either Version 3, or (at your option) */
14 /* any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */
24 /* */
25 /* FILE: z31.c */
26 /* MODULE: Memory Allocator */
27 /* EXTERNS: DebugMemory(), zz_free[], MemInit(), GetMemory() */
28 /* */
29 /*****************************************************************************/
30 #include "externs.h"
31
32 #define MEM_CHUNK 1020 /* how many ALIGNs to get from sys */
33
34
35 #if DEBUG_ON
36 static int no_of_calls = 0; /* number of calls to calloc() */
37 static int recs_created = 0; /* number of records created */
38 static int bytes_created = 0; /* number of bytes in created recs */
39 int zz_newcount = 0; /* number of calls to New() */
40 int zz_disposecount = 0; /* number of calls to Dispose() */
41 int zz_listcount = 0; /* number of elements in zz_free[] */
42
43 static int usage_nums[MEM_USAGE_MAX] = { 0 };
44 static int usage_bytes[MEM_USAGE_MAX] = { 0 };
45 static int max_usage_bytes[MEM_USAGE_MAX] = { 0 };
46 static int curr_total_bytes, max_total_bytes = 0;
47 static char *usage_strings[] = {
48 "lout binary",
49 "object memory chunks",
50 "font tables",
51 "lex buffers",
52 "file tables",
53 "cross reference tables",
54 "plain text output grids",
55 "database check tables",
56 "hyphenation pattern tables",
57 "character mappings",
58 "colour tables",
59 "texture tables",
60 "language tables",
61 };
62
63 /*****************************************************************************/
64 /* */
65 /* DebugRegisterUsage(typ, delta_num, delta_size) */
66 /* */
67 /* Register a change in the number of things of type typ that */
68 /* have been allocated memory, and the change in the number of bytes. */
69 /* */
70 /*****************************************************************************/
71
DebugRegisterUsage(int typ,int delta_num,int delta_size)72 void DebugRegisterUsage(int typ, int delta_num, int delta_size)
73 { int i;
74 assert(0 <= typ && typ < MEM_USAGE_MAX, "DebugRegisterUsage!");
75 usage_nums[typ] += delta_num;
76 usage_bytes[typ] += delta_size;
77 curr_total_bytes += delta_size;
78 if( curr_total_bytes > max_total_bytes )
79 { max_total_bytes = curr_total_bytes;
80 for( i = 0; i < MEM_USAGE_MAX; i++ )
81 max_usage_bytes[i] = usage_bytes[i];
82 }
83 } /* end DebugRegisterUsage */
84
85
86 /*****************************************************************************/
87 /* */
88 /* DebugMemory() */
89 /* */
90 /* Print memory usage. */
91 /* */
92 /*****************************************************************************/
93
DebugMemory(void)94 void DebugMemory(void)
95 { int i, j; OBJECT p; int recs_free, bytes_free;
96
97 recs_free = bytes_free = 0;
98 for( i = 0; i < MAX_OBJECT_REC; i++ )
99 { if( zz_free[i] != nilobj )
100 { j = 0;
101 for( p = zz_free[i]; p != nilobj; p = pred(p, CHILD) ) j++;
102 debug3(DMA, DD, "zz_free[%2d]: %5d (%d bytes)", i, j,
103 i * j * sizeof(ALIGN));
104 recs_free += j;
105 bytes_free += i* j * sizeof(ALIGN);
106 }
107 }
108
109 debug4(DMA, D, "%-35s %8s %8s %8s",
110 "Summary of malloc() memory usage", "Quantity", "Bytes", "At max.");
111
112 for( i = 1; i < MEM_USAGE_MAX; i++ )
113 {
114 debug4(DMA, D, "%-35s %8d %8d %8d", usage_strings[i], usage_nums[i],
115 usage_bytes[i], max_usage_bytes[i]);
116 }
117 debug4(DMA, D, "%-35s %8s %8s %8s", "", "", "--------", "--------");
118 debug4(DMA, D, "%-35s %8s %8d %8d", "","",curr_total_bytes,max_total_bytes);
119
120
121 /***
122 debug3(DMA, D, "%-12s %8s %8s", "", "records", "bytes");
123 debug4(DMA, D, "%-12s %8s %8d (%d calls)", "calloc", "-",
124 no_of_calls * MEM_CHUNK * sizeof(ALIGN), no_of_calls);
125 debug3(DMA, D, "%-12s %8d %8d", "created", recs_created, bytes_created);
126 debug3(DMA, D, "%-12s %8d %8d", "free (count)", recs_free, bytes_free);
127 debug3(DMA, D, "%-12s %8d %8s", "free (var)", zz_listcount, "-");
128 debug3(DMA, D, "%-12s %8d %8s", "new-dispose",
129 zz_newcount - zz_disposecount, "-");
130 debug3(DMA, D, "%-12s %8d %8s", "created-free",
131 recs_created - recs_free, "-");
132 debug2(DMA, D, "newcount %d, disposecount %d", zz_newcount, zz_disposecount);
133 *** */
134
135 debug0(DMA, D, "");
136
137 } /* end DebugMemory */
138 #endif
139
140
141 /*@::zz_free[], zz_lengths[], MemInit()@**************************************/
142 /* */
143 /* OBJECT zz_free[], zz_hold, zz_tmp, zz_res */
144 /* int zz_size */
145 /* unsigned char zz_lengths[] */
146 /* */
147 /* zz_free[i]: free records of size i*sizeof(ALIGN). */
148 /* zz_lengths[i]: the number of ALIGNs in a record of type i. */
149 /* These variables are used only within the New() and Dispose() macros, */
150 /* and the list handling macros. */
151 /* */
152 /*****************************************************************************/
153
154 OBJECT zz_free[MAX_OBJECT_REC], zz_hold, zz_tmp, zz_res;
155 int zz_size;
156 unsigned char zz_lengths[DISPOSED]; /* DISPOSED is 1 + max type */
157 OBJECT xx_link, xx_tmp, xx_res, xx_hold;
158
159
160 /*****************************************************************************/
161 /* */
162 /* MemInit() */
163 /* */
164 /* Initialise memory allocator. */
165 /* */
166 /*****************************************************************************/
167
MemInit(void)168 void MemInit(void)
169 {
170 zz_lengths[ WORD ] = 0;
171 zz_lengths[ QWORD ] = 0;
172 zz_lengths[ LINK ] = ceiling(sizeof(struct link_type), sizeof(ALIGN));
173
174 /* object types, except closure NB have actual() field in token phase! */
175 zz_lengths[ CLOSURE ] =
176 zz_lengths[ NULL_CLOS ] =
177 zz_lengths[ PAGE_LABEL ] =
178 zz_lengths[ UNDER_REC ] =
179 zz_lengths[ CROSS ] =
180 zz_lengths[ FORCE_CROSS ] =
181 zz_lengths[ SPLIT ] =
182 zz_lengths[ PAR ] =
183 zz_lengths[ ROW_THR ] =
184 zz_lengths[ COL_THR ] =
185 zz_lengths[ HSPANNER ] =
186 zz_lengths[ VSPANNER ] =
187 zz_lengths[ ACAT ] =
188 zz_lengths[ HCAT ] =
189 zz_lengths[ VCAT ] =
190 zz_lengths[ BEGIN_HEADER ] =
191 zz_lengths[ END_HEADER ] =
192 zz_lengths[ SET_HEADER ] =
193 zz_lengths[ CLEAR_HEADER ] =
194 zz_lengths[ ONE_COL ] =
195 zz_lengths[ ONE_ROW ] =
196 zz_lengths[ WIDE ] =
197 zz_lengths[ HIGH ] =
198 zz_lengths[ HSHIFT ] =
199 zz_lengths[ VSHIFT ] =
200 zz_lengths[ HMIRROR ] =
201 zz_lengths[ VMIRROR ] =
202 zz_lengths[ HSCALE ] =
203 zz_lengths[ VSCALE ] =
204 zz_lengths[ HCOVER ] =
205 zz_lengths[ VCOVER ] =
206 zz_lengths[ SCALE ] =
207 zz_lengths[ KERN_SHRINK ] =
208 zz_lengths[ HCONTRACT ] =
209 zz_lengths[ VCONTRACT ] =
210 zz_lengths[ HLIMITED ] =
211 zz_lengths[ VLIMITED ] =
212 zz_lengths[ HEXPAND ] =
213 zz_lengths[ VEXPAND ] =
214 zz_lengths[ START_HVSPAN ] =
215 zz_lengths[ START_HSPAN ] =
216 zz_lengths[ START_VSPAN ] =
217 zz_lengths[ HSPAN ] =
218 zz_lengths[ VSPAN ] =
219 zz_lengths[ PADJUST ] =
220 zz_lengths[ HADJUST ] =
221 zz_lengths[ VADJUST ] =
222 zz_lengths[ ROTATE ] =
223 zz_lengths[ BACKGROUND ] =
224 zz_lengths[ VERBATIM ] =
225 zz_lengths[ RAW_VERBATIM ] =
226 zz_lengths[ CASE ] =
227 zz_lengths[ YIELD ] =
228 zz_lengths[ BACKEND ] =
229 zz_lengths[ FILTERED ] =
230 zz_lengths[ XCHAR ] =
231 zz_lengths[ FONT ] =
232 zz_lengths[ SPACE ] =
233 zz_lengths[ YUNIT ] =
234 zz_lengths[ ZUNIT ] =
235 zz_lengths[ BREAK ] =
236 zz_lengths[ UNDERLINE ] =
237 zz_lengths[ UNDERLINE_COLOUR ] =
238 zz_lengths[ COLOUR ] =
239 zz_lengths[ TEXTURE ] =
240 zz_lengths[ OUTLINE ] =
241 zz_lengths[ LANGUAGE ] =
242 zz_lengths[ CURR_LANG ] =
243 zz_lengths[ CURR_FAMILY ] =
244 zz_lengths[ CURR_FACE ] =
245 zz_lengths[ CURR_YUNIT ] =
246 zz_lengths[ CURR_ZUNIT ] =
247 zz_lengths[ GET_CONTEXT ] =
248 zz_lengths[ SET_CONTEXT ] =
249 zz_lengths[ COMMON ] =
250 zz_lengths[ RUMP ] =
251 zz_lengths[ MELD ] =
252 zz_lengths[ INSERT ] =
253 zz_lengths[ ONE_OF ] =
254 zz_lengths[ NEXT ] =
255 zz_lengths[ PLUS ] =
256 zz_lengths[ MINUS ] =
257 zz_lengths[ ENV_OBJ ] =
258 zz_lengths[ ENV ] =
259 zz_lengths[ ENVA ] =
260 zz_lengths[ ENVB ] =
261 zz_lengths[ ENVC ] =
262 zz_lengths[ ENVD ] =
263 zz_lengths[ CENV ] =
264 zz_lengths[ CLOS ] =
265 zz_lengths[ LVIS ] =
266 zz_lengths[ LUSE ] =
267 zz_lengths[ LEO ] =
268 zz_lengths[ OPEN ] =
269 zz_lengths[ TAGGED ] =
270 zz_lengths[ INCGRAPHIC ] =
271 zz_lengths[ SINCGRAPHIC ] =
272 zz_lengths[ PLAIN_GRAPHIC] =
273 zz_lengths[ GRAPHIC ] =
274 zz_lengths[ LINK_SOURCE ] =
275 zz_lengths[ LINK_DEST ] =
276 zz_lengths[ LINK_DEST_NULL] =
277 zz_lengths[ LINK_URL ] =
278 ceiling(sizeof(struct closure_type), sizeof(ALIGN));
279
280 zz_lengths[ HEAD ] =
281 ceiling(sizeof(struct head_type), sizeof(ALIGN));
282
283 zz_lengths[ LBR ] =
284 zz_lengths[ RBR ] =
285 zz_lengths[ BEGIN ] =
286 zz_lengths[ END ] =
287 zz_lengths[ USE ] =
288 zz_lengths[ NOT_REVEALED ] =
289 zz_lengths[ GSTUB_NONE ] =
290 zz_lengths[ GSTUB_INT ] =
291 zz_lengths[ GSTUB_EXT ] =
292 zz_lengths[ UNEXPECTED_EOF] =
293 zz_lengths[ INCG_REPEATED ] =
294 zz_lengths[ SINCG_REPEATED] =
295 zz_lengths[ PREPEND ] =
296 zz_lengths[ SYS_PREPEND ] =
297 zz_lengths[ DATABASE ] =
298 zz_lengths[ SYS_DATABASE ] =
299 zz_lengths[ DEAD ] =
300 zz_lengths[ UNATTACHED ] =
301 zz_lengths[ RECEPTIVE ] =
302 zz_lengths[ RECEIVING ] =
303 zz_lengths[ RECURSIVE ] =
304 zz_lengths[ PRECEDES ] =
305 zz_lengths[ FOLLOWS ] =
306 zz_lengths[ CROSS_FOLL ] =
307 zz_lengths[ CROSS_FOLL_OR_PREC] =
308 zz_lengths[ GALL_FOLL ] =
309 zz_lengths[ GALL_FOLL_OR_PREC ] =
310 zz_lengths[ CROSS_TARG ] =
311 zz_lengths[ GALL_TARG ] =
312 zz_lengths[ GALL_PREC ] =
313 zz_lengths[ CROSS_PREC ] =
314 zz_lengths[ PAGE_LABEL_IND] =
315 zz_lengths[ SCALE_IND ] =
316 zz_lengths[ COVER_IND ] =
317 zz_lengths[ EXPAND_IND ] =
318 zz_lengths[ THREAD ] =
319 zz_lengths[ CR_LIST ] =
320 zz_lengths[ SCOPE_SNAPSHOT] =
321 ceiling(sizeof(struct closure_type), sizeof(ALIGN));
322
323 /* symbol types */
324 zz_lengths[ MACRO ] =
325 zz_lengths[ LOCAL ] =
326 zz_lengths[ LPAR ] =
327 zz_lengths[ RPAR ] =
328 zz_lengths[ NPAR ] =
329 ceiling(sizeof(struct symbol_type), sizeof(ALIGN));
330
331 /* gap objects */
332 zz_lengths[ TSPACE ] =
333 zz_lengths[ TJUXTA ] =
334 zz_lengths[ GAP_OBJ ] =
335 ceiling(sizeof(struct gapobj_type), sizeof(ALIGN));
336
337 /* cross-reference and data base types */
338 zz_lengths[ CROSS_SYM ] =
339 zz_lengths[ CR_ROOT ] = ceiling(sizeof(struct cr_type) , sizeof(ALIGN));
340
341 /* external galley record */
342 zz_lengths[ EXT_GALL ] = ceiling(sizeof(struct ext_gall_type),sizeof(ALIGN));
343
344 } /* end MemInit() */
345
346
347 /*@::GetMemory()@*************************************************************/
348 /* */
349 /* OBJECT GetMemory(siz, pos) */
350 /* */
351 /* Return a pointer to siz ALIGNs of memory (0 < siz < MAX_OBJECT_REC). */
352 /* */
353 /*****************************************************************************/
354
GetMemory(int siz,FILE_POS * pos)355 OBJECT GetMemory(int siz, FILE_POS *pos)
356 { static ALIGN *next_free = (ALIGN *) nilobj;
357 static ALIGN *top_free = (ALIGN *) nilobj;
358 OBJECT res;
359
360 debug1(DMA, DDD, "GetMemory( %d )", siz);
361
362 /* get memory from operating system, if not enough left here */
363 if( &next_free[siz] > top_free )
364 {
365 #if DEBUG_ON
366 DebugRegisterUsage(MEM_OBJECTS, 1, MEM_CHUNK * sizeof(ALIGN));
367 #endif
368 next_free = (ALIGN *) calloc(MEM_CHUNK, sizeof(ALIGN));
369 ifdebug(DMA, D, no_of_calls++; )
370 if( next_free == NULL )
371 Error(31, 1, "exiting now (run out of memory)", FATAL, pos);
372 top_free = &next_free[MEM_CHUNK];
373 debug2(DMA, DD, "GetMemory: calloc returned %ld - %ld",
374 (long) next_free, (long) top_free);
375 }
376
377 res = (OBJECT) next_free;
378 next_free = &next_free[siz];
379 #if DEBUG_ON
380 recs_created++; bytes_created += siz * sizeof(ALIGN);
381 #endif
382 debug3(DMA, DDD, "GetMemory returning @%ld (next_free = @%ld, top_free = @%ld",
383 (long) res, (long) next_free, (long) top_free);
384 return res;
385 } /* end GetMemory */
386