diff options
Diffstat (limited to 'z31.c')
-rw-r--r-- | z31.c | 364 |
1 files changed, 364 insertions, 0 deletions
@@ -0,0 +1,364 @@ +/*@z31.c:Memory Allocator:DebugMemory()@**************************************/ +/* */ +/* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.17) */ +/* COPYRIGHT (C) 1991, 1999 Jeffrey H. Kingston */ +/* */ +/* Jeffrey H. Kingston (jeff@cs.usyd.edu.au) */ +/* Basser Department of Computer Science */ +/* The University of Sydney 2006 */ +/* AUSTRALIA */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either Version 2, or (at your option) */ +/* any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */ +/* */ +/* FILE: z31.c */ +/* MODULE: Memory Allocator */ +/* EXTERNS: DebugMemory(), zz_free[], MemInit(), GetMemory() */ +/* */ +/*****************************************************************************/ +#include "externs.h" + +#define MEM_CHUNK 1020 /* how many ALIGNs to get from sys */ + + +#if DEBUG_ON +static int no_of_calls = 0; /* number of calls to calloc() */ +static int recs_created = 0; /* number of records created */ +static int bytes_created = 0; /* number of bytes in created recs */ + int zz_newcount = 0; /* number of calls to New() */ + int zz_disposecount = 0; /* number of calls to Dispose() */ + int zz_listcount = 0; /* number of elements in zz_free[] */ + +static int usage_nums[MEM_USAGE_MAX] = { 0 }; +static int usage_bytes[MEM_USAGE_MAX] = { 0 }; +static int max_usage_bytes[MEM_USAGE_MAX] = { 0 }; +static int curr_total_bytes, max_total_bytes = 0; +static char *usage_strings[] = { + "lout binary", + "object memory chunks", + "font tables", + "lex buffers", + "file tables", + "cross reference tables", + "plain text output grids", + "database check tables", + "hyphenation pattern tables", + "character mappings", + "colour tables", + "language tables", +}; + +/*****************************************************************************/ +/* */ +/* DebugRegisterUsage(typ, delta_num, delta_size) */ +/* */ +/* Register a change in the number of things of type typ that */ +/* have been allocated memory, and the change in the number of bytes. */ +/* */ +/*****************************************************************************/ + +void DebugRegisterUsage(int typ, int delta_num, int delta_size) +{ int i; + assert(0 <= typ && typ < MEM_USAGE_MAX, "DebugRegisterUsage!"); + usage_nums[typ] += delta_num; + usage_bytes[typ] += delta_size; + curr_total_bytes += delta_size; + if( curr_total_bytes > max_total_bytes ) + { max_total_bytes = curr_total_bytes; + for( i = 0; i < MEM_USAGE_MAX; i++ ) + max_usage_bytes[i] = usage_bytes[i]; + } +} /* end DebugRegisterUsage */ + + +/*****************************************************************************/ +/* */ +/* DebugMemory() */ +/* */ +/* Print memory usage. */ +/* */ +/*****************************************************************************/ + +void DebugMemory(void) +{ int i, j; OBJECT p; int recs_free, bytes_free; + + recs_free = bytes_free = 0; + for( i = 0; i < MAX_OBJECT_REC; i++ ) + { if( zz_free[i] != nilobj ) + { j = 0; + for( p = zz_free[i]; p != nilobj; p = pred(p, CHILD) ) j++; + debug3(DMA, DD, "zz_free[%2d]: %5d (%d bytes)", i, j, + i * j * sizeof(ALIGN)); + recs_free += j; + bytes_free += i* j * sizeof(ALIGN); + } + } + + debug4(DMA, D, "%-35s %8s %8s %8s", + "Summary of malloc() memory usage", "Quantity", "Bytes", "At max."); + + for( i = 1; i < MEM_USAGE_MAX; i++ ) + { + debug4(DMA, D, "%-35s %8d %8d %8d", usage_strings[i], usage_nums[i], + usage_bytes[i], max_usage_bytes[i]); + } + debug4(DMA, D, "%-35s %8s %8s %8s", "", "", "--------", "--------"); + debug4(DMA, D, "%-35s %8s %8d %8d", "","",curr_total_bytes,max_total_bytes); + + + /*** + debug3(DMA, D, "%-12s %8s %8s", "", "records", "bytes"); + debug4(DMA, D, "%-12s %8s %8d (%d calls)", "calloc", "-", + no_of_calls * MEM_CHUNK * sizeof(ALIGN), no_of_calls); + debug3(DMA, D, "%-12s %8d %8d", "created", recs_created, bytes_created); + debug3(DMA, D, "%-12s %8d %8d", "free (count)", recs_free, bytes_free); + debug3(DMA, D, "%-12s %8d %8s", "free (var)", zz_listcount, "-"); + debug3(DMA, D, "%-12s %8d %8s", "new-dispose", + zz_newcount - zz_disposecount, "-"); + debug3(DMA, D, "%-12s %8d %8s", "created-free", + recs_created - recs_free, "-"); + debug2(DMA, D, "newcount %d, disposecount %d", zz_newcount, zz_disposecount); + *** */ + + debug0(DMA, D, ""); + +} /* end DebugMemory */ +#endif + + +/*@::zz_free[], zz_lengths[], MemInit()@**************************************/ +/* */ +/* OBJECT zz_free[], zz_hold, zz_tmp, zz_res */ +/* int zz_size */ +/* unsigned char zz_lengths[] */ +/* */ +/* zz_free[i]: free records of size i*sizeof(ALIGN). */ +/* zz_lengths[i]: the number of ALIGNs in a record of type i. */ +/* These variables are used only within the New() and Dispose() macros, */ +/* and the list handling macros. */ +/* */ +/*****************************************************************************/ + +OBJECT zz_free[MAX_OBJECT_REC], zz_hold, zz_tmp, zz_res; +int zz_size; +unsigned char zz_lengths[DISPOSED]; /* DISPOSED is 1 + max type */ +OBJECT xx_link, xx_tmp, xx_res, xx_hold; + + +/*****************************************************************************/ +/* */ +/* MemInit() */ +/* */ +/* Initialise memory allocator. */ +/* */ +/*****************************************************************************/ + +void MemInit(void) +{ + zz_lengths[ WORD ] = 0; + zz_lengths[ QWORD ] = 0; + zz_lengths[ LINK ] = ceiling(sizeof(struct link_type), sizeof(ALIGN)); + + /* object types, except closure NB have actual() field in token phase! */ + zz_lengths[ CLOSURE ] = + zz_lengths[ NULL_CLOS ] = + zz_lengths[ PAGE_LABEL ] = + zz_lengths[ UNDER_REC ] = + zz_lengths[ CROSS ] = + zz_lengths[ FORCE_CROSS ] = + zz_lengths[ SPLIT ] = + zz_lengths[ PAR ] = + zz_lengths[ ROW_THR ] = + zz_lengths[ COL_THR ] = + zz_lengths[ HSPANNER ] = + zz_lengths[ VSPANNER ] = + zz_lengths[ ACAT ] = + zz_lengths[ HCAT ] = + zz_lengths[ VCAT ] = + zz_lengths[ ONE_COL ] = + zz_lengths[ ONE_ROW ] = + zz_lengths[ WIDE ] = + zz_lengths[ HIGH ] = + zz_lengths[ HSHIFT ] = + zz_lengths[ VSHIFT ] = + zz_lengths[ HSCALE ] = + zz_lengths[ VSCALE ] = + zz_lengths[ HCOVER ] = + zz_lengths[ VCOVER ] = + zz_lengths[ SCALE ] = + zz_lengths[ KERN_SHRINK ] = + zz_lengths[ HCONTRACT ] = + zz_lengths[ VCONTRACT ] = + zz_lengths[ HLIMITED ] = + zz_lengths[ VLIMITED ] = + zz_lengths[ HEXPAND ] = + zz_lengths[ VEXPAND ] = + zz_lengths[ START_HVSPAN ] = + zz_lengths[ START_HSPAN ] = + zz_lengths[ START_VSPAN ] = + zz_lengths[ HSPAN ] = + zz_lengths[ VSPAN ] = + zz_lengths[ PADJUST ] = + zz_lengths[ HADJUST ] = + zz_lengths[ VADJUST ] = + zz_lengths[ ROTATE ] = + zz_lengths[ BACKGROUND ] = + zz_lengths[ VERBATIM ] = + zz_lengths[ RAW_VERBATIM ] = + zz_lengths[ CASE ] = + zz_lengths[ YIELD ] = + zz_lengths[ BACKEND ] = + zz_lengths[ FILTERED ] = + zz_lengths[ XCHAR ] = + zz_lengths[ FONT ] = + zz_lengths[ SPACE ] = + zz_lengths[ YUNIT ] = + zz_lengths[ ZUNIT ] = + zz_lengths[ BREAK ] = + zz_lengths[ UNDERLINE ] = + zz_lengths[ COLOUR ] = + zz_lengths[ LANGUAGE ] = + zz_lengths[ CURR_LANG ] = + zz_lengths[ CURR_FAMILY ] = + zz_lengths[ CURR_FACE ] = + zz_lengths[ COMMON ] = + zz_lengths[ RUMP ] = + zz_lengths[ MELD ] = + zz_lengths[ INSERT ] = + zz_lengths[ ONE_OF ] = + zz_lengths[ NEXT ] = + zz_lengths[ PLUS ] = + zz_lengths[ MINUS ] = + zz_lengths[ ENV_OBJ ] = + zz_lengths[ ENV ] = + zz_lengths[ ENVA ] = + zz_lengths[ ENVB ] = + zz_lengths[ ENVC ] = + zz_lengths[ ENVD ] = + zz_lengths[ CENV ] = + zz_lengths[ CLOS ] = + zz_lengths[ LVIS ] = + zz_lengths[ LUSE ] = + zz_lengths[ LEO ] = + zz_lengths[ OPEN ] = + zz_lengths[ TAGGED ] = + zz_lengths[ INCGRAPHIC ] = + zz_lengths[ SINCGRAPHIC ] = + zz_lengths[ PLAIN_GRAPHIC] = + zz_lengths[ GRAPHIC ] = + ceiling(sizeof(struct closure_type), sizeof(ALIGN)); + + zz_lengths[ HEAD ] = + ceiling(sizeof(struct head_type), sizeof(ALIGN)); + + zz_lengths[ LBR ] = + zz_lengths[ RBR ] = + zz_lengths[ BEGIN ] = + zz_lengths[ END ] = + zz_lengths[ USE ] = + zz_lengths[ NOT_REVEALED ] = + zz_lengths[ GSTUB_NONE ] = + zz_lengths[ GSTUB_INT ] = + zz_lengths[ GSTUB_EXT ] = + zz_lengths[ UNEXPECTED_EOF] = + zz_lengths[ PREPEND ] = + zz_lengths[ SYS_PREPEND ] = + zz_lengths[ DATABASE ] = + zz_lengths[ SYS_DATABASE ] = + zz_lengths[ DEAD ] = + zz_lengths[ UNATTACHED ] = + zz_lengths[ RECEPTIVE ] = + zz_lengths[ RECEIVING ] = + zz_lengths[ RECURSIVE ] = + zz_lengths[ PRECEDES ] = + zz_lengths[ FOLLOWS ] = + zz_lengths[ CROSS_FOLL ] = + zz_lengths[ CROSS_FOLL_OR_PREC] = + zz_lengths[ GALL_FOLL ] = + zz_lengths[ GALL_FOLL_OR_PREC ] = + zz_lengths[ CROSS_TARG ] = + zz_lengths[ GALL_TARG ] = + zz_lengths[ GALL_PREC ] = + zz_lengths[ CROSS_PREC ] = + zz_lengths[ PAGE_LABEL_IND] = + zz_lengths[ SCALE_IND ] = + zz_lengths[ COVER_IND ] = + zz_lengths[ EXPAND_IND ] = + zz_lengths[ THREAD ] = + zz_lengths[ CR_LIST ] = + ceiling(sizeof(struct closure_type), sizeof(ALIGN)); + + /* symbol types */ + zz_lengths[ MACRO ] = + zz_lengths[ LOCAL ] = + zz_lengths[ LPAR ] = + zz_lengths[ RPAR ] = + zz_lengths[ NPAR ] = + ceiling(sizeof(struct symbol_type), sizeof(ALIGN)); + + /* gap objects */ + zz_lengths[ TSPACE ] = + zz_lengths[ TJUXTA ] = + zz_lengths[ GAP_OBJ ] = + ceiling(sizeof(struct gapobj_type), sizeof(ALIGN)); + + /* cross-reference and data base types */ + zz_lengths[ CROSS_SYM ] = + zz_lengths[ CR_ROOT ] = ceiling(sizeof(struct cr_type) , sizeof(ALIGN)); + + /* external galley record */ + zz_lengths[ EXT_GALL ] = ceiling(sizeof(struct ext_gall_type),sizeof(ALIGN)); + +} /* end MemInit() */ + + +/*@::GetMemory()@*************************************************************/ +/* */ +/* OBJECT GetMemory(siz, pos) */ +/* */ +/* Return a pointer to siz ALIGNs of memory (0 < siz < MAX_OBJECT_REC). */ +/* */ +/*****************************************************************************/ + +OBJECT GetMemory(int siz, FILE_POS *pos) +{ static ALIGN *next_free = (ALIGN *) nilobj; + static ALIGN *top_free = (ALIGN *) nilobj; + OBJECT res; + + debug1(DMA, DDD, "GetMemory( %d )", siz); + + /* get memory from operating system, if not enough left here */ + if( &next_free[siz] > top_free ) + { +#if DEBUG_ON + DebugRegisterUsage(MEM_OBJECTS, 1, MEM_CHUNK * sizeof(ALIGN)); +#endif + next_free = (ALIGN *) calloc(MEM_CHUNK, sizeof(ALIGN)); + ifdebug(DMA, D, no_of_calls++; ) + if( next_free == NULL ) + Error(31, 1, "exiting now (run out of memory)", FATAL, pos); + top_free = &next_free[MEM_CHUNK]; + debug2(DMA, DD, "GetMemory: calloc returned %ld - %ld", + (long) next_free, (long) top_free); + } + + res = (OBJECT) next_free; + next_free = &next_free[siz]; +#if DEBUG_ON + recs_created++; bytes_created += siz * sizeof(ALIGN); +#endif + debug3(DMA, DDD, "GetMemory returning @%ld (next_free = @%ld, top_free = @%ld", + (long) res, (long) next_free, (long) top_free); + return res; +} /* end GetMemory */ |