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