1 /********************************************************************/
2 /*                                                                  */
3 /*  s7   Seed7 interpreter                                          */
4 /*  Copyright (C) 1989 - 2019, 2021  Thomas Mertes                  */
5 /*                                                                  */
6 /*  This program is free software; you can redistribute it and/or   */
7 /*  modify it under the terms of the GNU General Public License as  */
8 /*  published by the Free Software Foundation; either version 2 of  */
9 /*  the License, or (at your option) any later version.             */
10 /*                                                                  */
11 /*  This program is distributed in the hope that it will be useful, */
12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of  */
13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   */
14 /*  GNU General Public License for more details.                    */
15 /*                                                                  */
16 /*  You should have received a copy of the GNU General Public       */
17 /*  License along with this program; if not, write to the           */
18 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
19 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
20 /*                                                                  */
21 /*  Module: General                                                 */
22 /*  File: seed7/src/flistutl.c                                      */
23 /*  Changes: 1993, 1994, 2010, 2013, 2015, 2019  Thomas Mertes      */
24 /*           2021  Thomas Mertes                                    */
25 /*  Content: Procedures for free memory list maintenance.           */
26 /*                                                                  */
27 /*  This file contains the heapsize procedure which calculates      */
28 /*  the size of the currently used heap memory. This is done by     */
29 /*  subtracting the size of the free lists from the size of all     */
30 /*  memory requested with ALLOC_ macros. Note that the memory       */
31 /*  totally requested from the system is more than the memory       */
32 /*  requested with the ALLOC_ macros because of the chunk           */
33 /*  mechanism.                                                      */
34 /*  There is also the procedure reuse_free_lists which gives the    */
35 /*  memory occupied by the free lists back to the system. This      */
36 /*  makes only sense when the CHUNK_ALLOCS are turned off. This is  */
37 /*  because the chunk alloc mechanism is tuned for speed (and to    */
38 /*  work with free lists) and does not recycle any freed memory.    */
39 /*                                                                  */
40 /*  Here is the chunk allocation mechanism. All memory allocations  */
41 /*  with fixed small sizes are allocated out of chunks and are      */
42 /*  maintained in free lists. Only strings and large buffers        */
43 /*  are directly allocated with malloc. All heap requests run       */
44 /*  via macros defined in heaputil.h. This macros call malloc or    */
45 /*  use the chunk mechanism. Requests which run via the chunk       */
46 /*  mechanism should be done via macros defined in flistutl.h.      */
47 /*  This macros use free lists to maintain the free memory.         */
48 /*                                                                  */
49 /********************************************************************/
50 
51 #define LOG_FUNCTIONS 0
52 #define VERBOSE_EXCEPTIONS 0
53 
54 #include "stdlib.h"
55 #include "stdio.h"
56 
57 #include "version.h"
58 #include "common.h"
59 #include "data.h"
60 #include "data_rtl.h"
61 #include "sql_drv.h"
62 #include "heaputl.h"
63 
64 #undef EXTERN
65 #define EXTERN
66 #define DO_INIT
67 #include "flistutl.h"
68 
69 
70 #if USE_CHUNK_ALLOCS
71 static const unsigned int chunk_size[] = { 32768, 16384, 8192, 4096,
72     2048, 1024, 512, 256, 128, 64, 0 };
73 #endif
74 
75 
76 
77 #ifdef OUT_OF_ORDER
check_obj_flist(objectType object)78 boolType check_obj_flist (objectType object)
79 
80   {
81     objectType help_obj;
82     objectType next_obj;
83 
84   /* check_obj_flist */
85     help_obj = flist.objects;
86     while (help_obj != NULL) {
87       next_obj = help_obj->value.objValue;
88       if (help_obj == object) {
89         help_obj->value.objValue = NULL;
90         printf("****************************************\n");
91         printf("object in flist\n%ld %08lx ", refNum(help_obj), (unsigned long int) help_obj);
92         trace1(help_obj);
93         printf("\n");
94         help_obj->value.objValue = next_obj;
95         /* printf("%d", 1/0); */
96         return FALSE;
97       } /* if */
98       help_obj = next_obj;
99     } /* while */
100     return TRUE;
101   } /* check_obj_flist */
102 #endif
103 
104 
105 
106 #if DO_HEAPSIZE_COMPUTATION || DO_HEAP_STATISTIC
object_flist_count(void)107 static unsigned long object_flist_count (void)
108 
109   {
110     register objectType help_obj;
111     register unsigned long num_objects = 0;
112 
113   /* object_flist_count */
114     help_obj = flist.objects;
115     while (help_obj != NULL) {
116       help_obj = help_obj->value.objValue;
117       num_objects++;
118     } /* while */
119     return num_objects;
120   } /* object_flist_count */
121 
122 
123 
list_elem_flist_count(void)124 static unsigned long list_elem_flist_count (void)
125 
126   {
127     register listType help_list;
128     register unsigned long num_list_elems = 0;
129 
130   /* list_elem_flist_count */
131     help_list = flist.list_elems;
132     while (help_list != NULL) {
133       help_list = help_list->next;
134       num_list_elems++;
135     } /* while */
136     return num_list_elems;
137   } /* list_elem_flist_count */
138 
139 
140 
node_flist_count(void)141 static unsigned long node_flist_count (void)
142 
143   {
144     register nodeType help_node;
145     register unsigned long num_nodes = 0;
146 
147   /* node_flist_count */
148     help_node = flist.nodes;
149     while (help_node != NULL) {
150       help_node = help_node->next1;
151       num_nodes++;
152     } /* while */
153     return num_nodes;
154   } /* node_flist_count */
155 
156 
157 
infile_flist_count(void)158 static unsigned long infile_flist_count (void)
159 
160   {
161     register inFileType help_infile;
162     register unsigned long num_infiles = 0;
163 
164   /* infile_flist_count */
165     help_infile = flist.infiles;
166     while (help_infile != NULL) {
167       help_infile = help_infile->next;
168       num_infiles++;
169     } /* while */
170     return num_infiles;
171   } /* infile_flist_count */
172 
173 
174 
stri_flist_count(unsigned long * stri_chars)175 static unsigned long stri_flist_count (unsigned long *stri_chars)
176 
177   {
178 #if WITH_STRI_FREELIST
179     register freeListElemType help_elem;
180     register unsigned long num_elems;
181 #endif
182     register unsigned long num_stris = 0;
183 
184   /* stri_flist_count */
185 #if WITH_STRI_FREELIST
186 #if WITH_STRI_CAPACITY
187     {
188       unsigned int index;
189 
190       *stri_chars = 0;
191       for (index = 0; index < STRI_FREELIST_ARRAY_SIZE; index++) {
192         num_elems = 0;
193         help_elem = sflist[index];
194         while (help_elem != NULL) {
195 #if 0
196           striType stri;
197           memSizeType saved_size;
198 
199           stri = (striType) help_elem;
200           saved_size = stri->size;
201           stri->size = stri->capacity;
202           prot_stri(stri);
203           prot_nl();
204           stri->size = saved_size;
205 #endif
206           help_elem = help_elem->next;
207           num_elems++;
208         } /* while */
209         num_stris += num_elems;
210         *stri_chars += index * num_elems;
211         /* printf("sflist[%d]=%lu %lu\n", index, num_elems, index * num_elems); */
212       } /* for */
213       /* printf("num_stris=%lu\n", num_stris);
214          printf("stri_chars=%lu\n", *stri_chars);
215          printf("count.stri=%lu\n", count.stri);
216          printf("count.stri_elems=%lu\n", count.stri_elems); */
217     }
218 #else
219     num_elems = 0;
220     help_elem = sflist;
221     while (help_elem != NULL) {
222       help_elem = help_elem->next;
223       num_elems++;
224     } /* while */
225     num_stris = num_elems;
226     *stri_chars = num_elems;
227 #endif
228 #else
229     *stri_chars = 0;
230 #endif
231     return num_stris;
232   } /* stri_flist_count */
233 #endif
234 
235 
236 
237 #if DO_HEAP_STATISTIC
heapStatistic(void)238 void heapStatistic (void)
239 
240   {
241     unsigned long num_flist_objects;
242     unsigned long num_flist_list_elems;
243     unsigned long num_flist_nodes;
244     unsigned long num_flist_infiles;
245     unsigned long num_flist_stris;
246     unsigned long num_flist_stri_elems;
247     memSizeType bytes_used;
248     memSizeType bytes_in_buffers;
249     memSizeType bytes_free;
250     memSizeType bytes_total;
251 
252   /* heapStatistic */
253     logFunction(printf("heapStatistic\n"););
254     num_flist_objects    = object_flist_count();
255     num_flist_list_elems = list_elem_flist_count();
256     num_flist_nodes      = node_flist_count();
257     num_flist_infiles    = infile_flist_count();
258     num_flist_stris      = stri_flist_count(&num_flist_stri_elems);
259     bytes_used = 0;
260     if (count.stri > num_flist_stris) {
261       printf(F_U_MEM(9) " bytes in %8lu string records of      %4u bytes\n",
262           (count.stri - num_flist_stris) * SIZ_STRI(0),
263           count.stri - num_flist_stris,
264           (unsigned int) SIZ_STRI(0));
265       bytes_used += (count.stri - num_flist_stris) * SIZ_STRI(0);
266       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " string chars of        %4u bytes\n",
267           (count.stri_elems - num_flist_stri_elems) * sizeof(strElemType),
268           count.stri_elems - num_flist_stri_elems,
269           (unsigned int) sizeof(strElemType));
270       bytes_used += (count.stri_elems - num_flist_stri_elems) * sizeof(strElemType);
271     } /* if */
272     if (count.bstri != 0) {
273       printf(F_U_MEM(9) " bytes in %8lu bstring records of     %4u bytes\n",
274           count.bstri * SIZ_BSTRI(0),
275           count.bstri,
276           (unsigned int) SIZ_BSTRI(0));
277       bytes_used += count.bstri * SIZ_BSTRI(0);
278       printf(F_U_MEM(9) " bytes in %8lu bstrings of average    %4lu bytes\n",
279           count.bstri_elems * sizeof(ucharType),
280           count.bstri,
281           (unsigned long) ((count.bstri_elems * sizeof(ucharType)) / count.bstri));
282       bytes_used += count.bstri_elems * sizeof(ucharType);
283     } /* if */
284     if (count.array != 0) {
285       printf(F_U_MEM(9) " bytes in %8lu arrays of              %4u bytes\n",
286           count.array * SIZ_ARR(0),
287           count.array,
288           (unsigned int) SIZ_ARR(0));
289       bytes_used += count.array * SIZ_ARR(0);
290     } /* if */
291     if (count.arr_elems != 0) {
292       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " array elements of      %4u bytes\n",
293           count.arr_elems * SIZ_REC(objectRecord),
294           count.arr_elems,
295           (unsigned int) SIZ_REC(objectRecord));
296       bytes_used += count.arr_elems * SIZ_REC(objectRecord);
297     } /* if */
298     if (count.rtl_arr_elems != 0) {
299       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " rtl array elems of     %4u bytes\n",
300           count.rtl_arr_elems * SIZ_REC(rtlObjectType),
301           count.rtl_arr_elems,
302           (unsigned int) SIZ_REC(rtlObjectType));
303       bytes_used += count.rtl_arr_elems * SIZ_REC(rtlObjectType);
304     } /* if */
305     if (count.hash != 0) {
306       printf(F_U_MEM(9) " bytes in %8lu hashtables of          %4u bytes\n",
307           count.hash * SIZ_HSH(0),
308           count.hash,
309           (unsigned int) SIZ_HSH(0));
310       bytes_used += count.hash * SIZ_HSH(0);
311     } /* if */
312     if (count.hsh_elems != 0) {
313       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " hashtable elems of     %4u bytes\n",
314           count.hsh_elems * SIZ_REC(hashElemType),
315           count.hsh_elems,
316           (unsigned int) SIZ_REC(hashElemType));
317       bytes_used += count.hsh_elems * SIZ_REC(hashElemType);
318     } /* if */
319     if (count.helem != 0) {
320       printf(F_U_MEM(9) " bytes in %8lu helems of              %4u bytes\n",
321           count.helem * SIZ_REC(hashElemRecord),
322           count.helem,
323           (unsigned int) SIZ_REC(hashElemRecord));
324       bytes_used += count.helem * SIZ_REC(hashElemRecord);
325     } /* if */
326     if (count.rtl_helem != 0) {
327       printf(F_U_MEM(9) " bytes in %8lu rtl helems of          %4u bytes\n",
328           count.rtl_helem * SIZ_REC(rtlHashElemRecord),
329           count.rtl_helem,
330           (unsigned int) SIZ_REC(rtlHashElemRecord));
331       bytes_used += count.rtl_helem * SIZ_REC(rtlHashElemRecord);
332     } /* if */
333     if (count.set != 0) {
334       printf(F_U_MEM(9) " bytes in %8lu sets of                %4u bytes\n",
335           count.set * SIZ_SET(0),
336           count.set,
337           (unsigned int) SIZ_SET(0));
338       bytes_used += count.set * SIZ_SET(0);
339     } /* if */
340     if (count.set_elems != 0) {
341       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " set elements of        %4u bytes\n",
342           count.set_elems * SIZ_REC(bitSetType),
343           count.set_elems,
344           (unsigned int) SIZ_REC(bitSetType));
345       bytes_used += count.set_elems * SIZ_REC(bitSetType);
346     } /* if */
347     if (count.stru != 0) {
348       printf(F_U_MEM(9) " bytes in %8lu structs of             %4u bytes\n",
349           count.stru * SIZ_SCT(0),
350           count.stru,
351           (unsigned int) SIZ_SCT(0));
352       bytes_used += count.stru * SIZ_SCT(0);
353     } /* if */
354     if (count.sct_elems != 0) {
355       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " struct elements of     %4u bytes\n",
356           count.sct_elems * SIZ_REC(objectRecord),
357           count.sct_elems,
358           (unsigned int) SIZ_REC(objectRecord));
359       bytes_used += count.sct_elems * SIZ_REC(objectRecord);
360     } /* if */
361 #if BIGINT_LIB == BIG_RTL_LIBRARY
362     if (count.big != 0) {
363       printf(F_U_MEM(9) " bytes in %8lu bigIntegers of         %4u bytes\n",
364           count.big * SIZ_BIG(0),
365           count.big,
366           (unsigned int) SIZ_BIG(0));
367       bytes_used += count.big * SIZ_BIG(0);
368     } /* if */
369     if (count.big_elems != 0) {
370       printf(F_U_MEM(9) " bytes in " F_U_MEM(8) " bigdigits of           %4u bytes\n",
371           count.big_elems * sizeof_bigDigitType,
372           count.big_elems,
373           (unsigned int) sizeof_bigDigitType);
374       bytes_used += count.big_elems * sizeof_bigDigitType;
375     } /* if */
376 #endif
377     if (count.ident != 0) {
378       printf(F_U_MEM(9) " bytes in %8lu ident records of       %4u bytes\n",
379           count.ident * SIZ_REC(identRecord),
380           count.ident,
381           (unsigned int) SIZ_REC(identRecord));
382       bytes_used += count.ident * SIZ_REC(identRecord);
383     } /* if */
384     if (count.idt != 0) {
385       printf(F_U_MEM(9) " bytes in %8lu idents of average      %4lu bytes\n",
386           count.idt_bytes + count.idt,
387           count.idt,
388           (unsigned long) ((count.idt_bytes + count.idt) / count.idt));
389       bytes_used += count.idt_bytes + count.idt;
390     } /* if */
391     if (count.entity != 0) {
392       printf(F_U_MEM(9) " bytes in %8lu entities of            %4u bytes\n",
393           count.entity * SIZ_REC(entityRecord),
394           count.entity,
395           (unsigned int) SIZ_REC(entityRecord));
396       bytes_used += count.entity * SIZ_REC(entityRecord);
397     } /* if */
398     if (count.property != 0) {
399       printf(F_U_MEM(9) " bytes in %8lu properties of          %4u bytes\n",
400           count.property * SIZ_REC(propertyRecord),
401           count.property,
402           (unsigned int) SIZ_REC(propertyRecord));
403       bytes_used += count.property * SIZ_REC(propertyRecord);
404     } /* if */
405     if (count.object > num_flist_objects) {
406       printf(F_U_MEM(9) " bytes in %8lu objects of             %4u bytes\n",
407           (count.object - num_flist_objects) * SIZ_REC(objectRecord),
408           count.object - num_flist_objects,
409           (unsigned int) SIZ_REC(objectRecord));
410       bytes_used += (count.object - num_flist_objects) * SIZ_REC(objectRecord);
411     } /* if */
412     if (count.node > num_flist_nodes) {
413       printf(F_U_MEM(9) " bytes in %8lu nodes of               %4u bytes\n",
414           (count.node - num_flist_nodes) * SIZ_REC(nodeRecord),
415           count.node - num_flist_nodes,
416           (unsigned int) SIZ_REC(nodeRecord));
417       bytes_used += (count.node - num_flist_nodes) * SIZ_REC(nodeRecord);
418     } /* if */
419     if (count.token != 0) {
420       printf(F_U_MEM(9) " bytes in %8lu tokens of              %4u bytes\n",
421           count.token * SIZ_REC(tokenRecord),
422           count.token,
423           (unsigned int) SIZ_REC(tokenRecord));
424       bytes_used += count.token * SIZ_REC(tokenRecord);
425     } /* if */
426     if (count.owner != 0) {
427       printf(F_U_MEM(9) " bytes in %8lu owners of              %4u bytes\n",
428           count.owner * SIZ_REC(ownerRecord),
429           count.owner,
430           (unsigned int) SIZ_REC(ownerRecord));
431       bytes_used += count.owner * SIZ_REC(ownerRecord);
432     } /* if */
433     if (count.stack != 0) {
434       printf(F_U_MEM(9) " bytes in %8lu stacks of              %4u bytes\n",
435           count.stack * SIZ_REC(stackRecord),
436           count.stack,
437           (unsigned int) SIZ_REC(stackRecord));
438       bytes_used += count.stack * SIZ_REC(stackRecord);
439     } /* if */
440     if (count.typelist_elems != 0) {
441       printf(F_U_MEM(9) " bytes in %8lu typelist elems of      %4u bytes\n",
442           count.typelist_elems * SIZ_REC(typeListRecord),
443           count.typelist_elems,
444           (unsigned int) SIZ_REC(typeListRecord));
445       bytes_used += count.typelist_elems * SIZ_REC(typeListRecord);
446     } /* if */
447     if (count.type != 0) {
448       printf(F_U_MEM(9) " bytes in %8lu types of               %4u bytes\n",
449           count.type * SIZ_REC(typeRecord),
450           count.type,
451           (unsigned int) SIZ_REC(typeRecord));
452       bytes_used += count.type * SIZ_REC(typeRecord);
453     } /* if */
454     if (count.list_elem > num_flist_list_elems) {
455       printf(F_U_MEM(9) " bytes in %8lu list_elems of          %4u bytes\n",
456           (count.list_elem - num_flist_list_elems) * SIZ_REC(listRecord),
457           count.list_elem - num_flist_list_elems,
458           (unsigned int) SIZ_REC(listRecord));
459       bytes_used += (count.list_elem - num_flist_list_elems) * SIZ_REC(listRecord);
460     } /* if */
461     if (count.block != 0) {
462       printf(F_U_MEM(9) " bytes in %8lu blocks of              %4u bytes\n",
463           count.block * SIZ_REC(blockRecord),
464           count.block,
465           (unsigned int) SIZ_REC(blockRecord));
466       bytes_used += count.block * SIZ_REC(blockRecord);
467     } /* if */
468     if (count.loclist != 0) {
469       printf(F_U_MEM(9) " bytes in %8lu loclists of            %4u bytes\n",
470           count.loclist * SIZ_REC(locListRecord),
471           count.loclist,
472           (unsigned int) SIZ_REC(locListRecord));
473       bytes_used += count.loclist * SIZ_REC(locListRecord);
474     } /* if */
475     if (count.infil > num_flist_infiles) {
476       printf(F_U_MEM(9) " bytes in %8lu infiles of             %4u bytes\n",
477           (count.infil - num_flist_infiles) * SIZ_REC(inFileRecord),
478           count.infil - num_flist_infiles,
479           (unsigned int) SIZ_REC(inFileRecord));
480       bytes_used += (count.infil - num_flist_infiles) * SIZ_REC(inFileRecord);
481     } /* if */
482     if (count.polldata != 0) {
483       printf(F_U_MEM(9) " bytes in %8lu pollData elements of   %4u bytes\n",
484           count.polldata * sizeof_pollRecord,
485           count.polldata,
486           (unsigned int) sizeof_pollRecord);
487       bytes_used += count.polldata * sizeof_pollRecord;
488     } /* if */
489     if (count.files != 0) {
490       printf(F_U_MEM(9) " bytes in %8lu files of               %4u bytes\n",
491           count.files * SIZ_REC(fileRecord),
492           count.files,
493           (unsigned int) SIZ_REC(fileRecord));
494       bytes_used += count.win_bytes;
495     } /* if */
496     if (count.win != 0) {
497       printf(F_U_MEM(9) " bytes in %8lu windows of             %4u bytes\n",
498           count.win_bytes,
499           count.win,
500           (unsigned int) (count.win_bytes / count.win));
501       bytes_used += count.win_bytes;
502     } /* if */
503     if (count.process != 0) {
504       printf(F_U_MEM(9) " bytes in %8lu processes of           %4u bytes\n",
505           count.process * sizeof_processRecord,
506           count.process,
507           (unsigned int) sizeof_processRecord);
508       bytes_used += count.process * sizeof_processRecord;
509     } /* if */
510     if (count.sql_func != 0) {
511       printf(F_U_MEM(9) " bytes in %8lu sqlFunc records of     %4u bytes\n",
512           count.sql_func * SIZ_REC(sqlFuncRecord),
513           count.sql_func,
514           (unsigned int) SIZ_REC(sqlFuncRecord));
515       bytes_used += count.sql_func * SIZ_REC(sqlFuncRecord);
516     } /* if */
517     if (count.database != 0) {
518       printf(F_U_MEM(9) " bytes in %8lu database records of    %4u bytes\n",
519           count.database_bytes,
520           count.database,
521           (unsigned int) (count.database_bytes / count.database));
522       bytes_used += count.database_bytes;
523     } /* if */
524     if (count.prepared_stmt != 0) {
525       printf(F_U_MEM(9) " bytes in %8lu prepared statements of %4u bytes\n",
526           count.prepared_stmt_bytes,
527           count.prepared_stmt,
528           (unsigned int) (count.prepared_stmt_bytes / count.prepared_stmt));
529       bytes_used += count.prepared_stmt_bytes;
530     } /* if */
531     if (count.fetch_data != 0) {
532       printf(F_U_MEM(9) " bytes in %8lu fetchData records of   %4u bytes\n",
533           count.fetch_data_bytes,
534           count.fetch_data,
535           (unsigned int) (count.fetch_data_bytes / count.fetch_data));
536       bytes_used += count.fetch_data_bytes;
537     } /* if */
538     if (count.prog != 0) {
539       printf(F_U_MEM(9) " bytes in %8lu progs of               %4u bytes\n",
540           count.prog * SIZ_REC(progRecord),
541           count.prog,
542           (unsigned int) SIZ_REC(progRecord));
543       bytes_used += count.prog * SIZ_REC(progRecord);
544     } /* if */
545     bytes_in_buffers =
546         count.fnam_bytes + count.fnam +
547         count.symb_bytes + count.symb +
548         count.byte;
549     if (bytes_in_buffers != 0) {
550       printf(F_U_MEM(9) " bytes in buffers\n", bytes_in_buffers);
551       bytes_used += bytes_in_buffers;
552     } /* if */
553     if (bytes_used != 0) {
554       printf(F_U_MEM(9) " bytes in use\n", bytes_used);
555     } /* if */
556     if (bytes_used != heapsize()) {
557       printf("*** \nbytes_used=" FMT_U_MEM " heapsize=" FMT_U_MEM " diff=" FMT_U_MEM "\n",
558           bytes_used, heapsize(), bytes_used - heapsize());
559     } /* if */
560     bytes_free = 0;
561     if (num_flist_objects != 0) {
562       printf(F_U_MEM(9) " bytes in %8lu free objects of        %4u bytes\n",
563           num_flist_objects * SIZ_REC(objectRecord),
564           num_flist_objects,
565           (unsigned int) SIZ_REC(objectRecord));
566       bytes_free += num_flist_objects * SIZ_REC(objectRecord);
567     } /* if */
568     if (num_flist_list_elems != 0) {
569       printf(F_U_MEM(9) " bytes in %8lu free list_elems of     %4u bytes\n",
570           num_flist_list_elems * SIZ_REC(listRecord),
571           num_flist_list_elems,
572           (unsigned int) SIZ_REC(listRecord));
573       bytes_free += num_flist_list_elems * SIZ_REC(listRecord);
574     } /* if */
575     if (num_flist_nodes != 0) {
576       printf(F_U_MEM(9) " bytes in %8lu free nodes of          %4u bytes\n",
577           num_flist_nodes * SIZ_REC(nodeRecord),
578           num_flist_nodes,
579           (unsigned int) SIZ_REC(nodeRecord));
580       bytes_free += num_flist_nodes * SIZ_REC(nodeRecord);
581     } /* if */
582     if (num_flist_infiles != 0) {
583       printf(F_U_MEM(9) " bytes in %8lu free infiles of        %4u bytes\n",
584           num_flist_infiles * SIZ_REC(inFileRecord),
585           num_flist_infiles,
586           (unsigned int) SIZ_REC(inFileRecord));
587       bytes_free += num_flist_infiles * SIZ_REC(inFileRecord);
588     } /* if */
589     if (num_flist_stris != 0) {
590       printf(F_U_MEM(9) " bytes in %8lu free string records of %4u bytes\n",
591           num_flist_stris * SIZ_STRI(0),
592           num_flist_stris,
593           (unsigned int) SIZ_STRI(0));
594       bytes_free += num_flist_stris * SIZ_STRI(0);
595       printf(F_U_MEM(9) " bytes in %8lu free string chars of   %4u bytes\n",
596           num_flist_stri_elems * sizeof(strElemType),
597           num_flist_stri_elems,
598           (unsigned int) sizeof(strElemType));
599       bytes_free += num_flist_stri_elems * sizeof(strElemType);
600     } /* if */
601     bytes_total = bytes_used + bytes_free;
602     printf(F_U_MEM(9) " bytes total (with " FMT_U_MEM " bytes in free lists)\n",
603         bytes_total,
604         bytes_free);
605 #if DO_HEAPSIZE_COMPUTATION
606     if (bytes_total != hs) {
607       printf("*** \nbytes_total=" FMT_U_MEM " hs=" FMT_U_MEM " diff=" FMT_U_MEM "\n",
608           bytes_total, hs, bytes_total - hs);
609     } /* if */
610 #endif
611 #if USE_CHUNK_ALLOCS
612     if (chunk.number_of_chunks != 0) {
613       printf(F_U_MEM(9) " bytes in %8u chunks\n",
614           chunk.total_size, chunk.number_of_chunks);
615       printf(F_U_MEM(9) " unused bytes in last chunk\n",
616           (memSizeType) (chunk.beyond - chunk.freemem));
617       printf(F_U_MEM(9) " lost bytes in chunks\n", chunk.lost_bytes);
618       printf(F_U_MEM(9) " bytes total requested\n", bytes_total +
619           (memSizeType) (chunk.beyond - chunk.freemem) + chunk.lost_bytes);
620     } /* if */
621 #endif
622 #if DO_HEAP_CHECK
623     /* check_heap(0, __FILE__, __LINE__); */
624 #endif
625     logFunction(printf("heapStatistic -->\n"););
626   } /* heapStatistic */
627 #endif
628 
629 
630 
631 #ifdef OUT_OF_ORDER
compute_hs(void)632 static memSizeType compute_hs (void)
633 
634   {
635     memSizeType bytes_total;
636 
637   /* compute_hs */
638     logFunction(printf("compute_hs\n"););
639     bytes_total = 0;
640     bytes_total += count.stri * SIZ_STRI(0);
641     bytes_total += count.stri_elems * sizeof(strElemType);
642     bytes_total += count.bstri * SIZ_BSTRI(0);
643     bytes_total += count.bstri_elems * sizeof(ucharType);
644     bytes_total += count.array * SIZ_ARR(0);
645     bytes_total += count.arr_elems * SIZ_REC(objectRecord);
646     bytes_total += count.hash * SIZ_HSH(0);
647     bytes_total += count.hsh_elems * SIZ_REC(hashElemType);
648     bytes_total += count.hsh_elems * SIZ_REC(hashElemRecord);
649     bytes_total += count.set * SIZ_SET(0);
650     bytes_total += count.set_elems * SIZ_REC(bitSetType);
651     bytes_total += count.stru * SIZ_SCT(0);
652     bytes_total += count.sct_elems * SIZ_REC(objectRecord);
653     bytes_total += count.big * SIZ_BIG(0);
654     bytes_total += count.big_elems * SIZ_REC(bigDigitType);
655     bytes_total += count.ident * SIZ_REC(identRecord);
656     bytes_total += count.idt_bytes + count.idt;
657     bytes_total += count.entity * SIZ_REC(entityRecord);
658     bytes_total += count.property * SIZ_REC(propertyRecord);
659     bytes_total += count.object * SIZ_REC(objectRecord);
660     bytes_total += count.node * SIZ_REC(nodeRecord);
661     bytes_total += count.token * SIZ_REC(tokenRecord);
662     bytes_total += count.owner * SIZ_REC(ownerRecord);
663     bytes_total += count.stack * SIZ_REC(stackRecord);
664     bytes_total += count.typelist_elems * SIZ_REC(typeListRecord);
665     bytes_total += count.type * SIZ_REC(typeRecord);
666     bytes_total += count.list_elem * SIZ_REC(listRecord);
667     bytes_total += count.block * SIZ_REC(blockRecord);
668     bytes_total += count.loclist * SIZ_REC(locListRecord);
669     bytes_total += count.infil * SIZ_REC(inFileRecord);
670     bytes_total += count.polldata * sizeof_pollRecord;
671     bytes_total += count.files * SIZ_REC(fileRecord);
672     bytes_total += count.win_bytes;
673     bytes_total += count.process * sizeof_processRecord;
674     bytes_total += count.sql_func * SIZ_REC(sqlFuncRecord);
675     bytes_total += count.database_bytes;
676     bytes_total += count.prepared_stmt_bytes;
677     bytes_total += count.fetch_data_bytes;
678     bytes_total += count.prog * SIZ_REC(progRecord);
679     bytes_total += count.fnam_bytes + count.fnam +
680         count.symb_bytes + count.symb +
681         count.byte;
682     logFunction(printf("compute_hs -->\n"););
683     return bytes_total;
684   } /* compute_hs */
685 #endif
686 
687 
688 
heapsize(void)689 memSizeType heapsize (void)
690 
691   {
692 #if DO_HEAPSIZE_COMPUTATION
693     memSizeType flist_bytes;
694     unsigned long num_flist_stri_elems;
695 #endif
696     memSizeType result;
697 
698   /* heapsize */
699 #if DO_HEAPSIZE_COMPUTATION
700     flist_bytes = object_flist_count() * sizeof(objectRecord);
701     flist_bytes += list_elem_flist_count() * sizeof(listRecord);
702     flist_bytes += node_flist_count() * sizeof(nodeRecord);
703     flist_bytes += infile_flist_count() * sizeof(inFileRecord);
704     flist_bytes += stri_flist_count(&num_flist_stri_elems) * SIZ_STRI(0);
705     flist_bytes += num_flist_stri_elems * sizeof(strElemType);
706 /*  printf(" %ld ", hs); */
707     result = hs - flist_bytes;
708 #else
709     result = 0;
710 #endif
711     return result;
712   } /* heapsize */
713 
714 
715 
716 #if USE_CHUNK_ALLOCS
717 #ifdef USE_FLIST_ALLOC
flist_alloc(size_t size)718 void *flist_alloc (size_t size)
719 
720   {
721     size_t size_of_rec;
722     void *result;
723 
724   /* flist_alloc */
725     if (size <= sizeof(listRecord) && flist.list_elems != NULL) {
726       result = (void *) flist.list_elems;
727       flist.list_elems = flist.list_elems->next;
728       size_of_rec = sizeof(listRecord);
729     } else if (size <= sizeof(objectRecord) && flist.objects != NULL) {
730       result = (void *) flist.objects;
731       flist.objects = flist.objects->value.objValue;
732       size_of_rec = sizeof(objectRecord);
733     } else if (size <= sizeof(inFileRecord) && flist.infiles != NULL) {
734       result = (void *) flist.infiles;
735       flist.infiles = flist.infiles->next;
736       size_of_rec = sizeof(inFileRecord);
737     } else {
738       result = NULL;
739       size_of_rec = size;
740     } /* if */
741     LOST_B += size_of_rec - size;
742 /*  printf("flist_alloc(%d) --> " FMT_X_MEM "\n", size, (memSizeType) result); */
743     return result;
744   } /* flist_alloc */
745 #endif
746 #endif
747 
748 
749 
750 #if !USE_CHUNK_ALLOCS
reuse_free_lists(void)751 void reuse_free_lists (void)
752 
753   {
754     objectType help_obj;
755     listType help_list;
756     inFileType help_infile;
757 
758   /* reuse_free_lists */
759     /* Free the flist.objects and the flist.list_elems lists */
760     while (flist.objects != NULL) {
761       help_obj = flist.objects;
762       flist.objects = flist.objects->value.objValue;
763       FREE_RECORD(help_obj, objectRecord, count.object);
764     } /* while */
765     while (flist.list_elems != NULL) {
766       help_list = flist.list_elems;
767       flist.list_elems = flist.list_elems->next;
768       FREE_RECORD(help_list, listRecord, count.list_elem);
769     } /* while */
770     while (flist.infiles != NULL) {
771       help_infile = flist.infiles;
772       flist.infiles = flist.infiles->next;
773       FREE_RECORD(help_infile, inFileRecord, count.infil);
774     } /* while */
775   } /* reuse_free_lists */
776 #endif
777 
778 
779 
780 #if USE_CHUNK_ALLOCS
heap_chunk(size_t size)781 void *heap_chunk (size_t size)
782 
783   {
784     int index;
785     listType list_elem;
786     void *result;
787 
788   /* heap_chunk */
789     logFunction(printf("heap_chunk(" FMT_U_MEM ")\n", size););
790 /*  printf("%lu ", heapsize()); */
791     index = 0;
792     result = NULL;
793     while (chunk_size[index] >= size && chunk_size[index] != 0 &&
794         (result = (void *) MALLOC(chunk_size[index])) == NULL) {
795       index++;
796     } /* while */
797     if (result == NULL) {
798 #ifdef USE_FLIST_ALLOC
799       if ((result = flist_alloc(size)) == NULL) {
800         result = MALLOC(size);
801       } /* if */
802 #else
803       result = MALLOC(size);
804 #endif
805     } else {
806       if (chunk.start != NULL) {
807         /* There might be unused memory in the old chunk. A realloc() */
808         /* of the old chunk could be dangerous. Realloc() could move  */
809         /* the memory area of the chunk. Such a move would invalidate */
810         /* all pointers into the old chunk. Instead remaining unused  */
811         /* memory from the old chunk is used as free list elements.   */
812         /* Elements of listRecord have been chosen, because they are  */
813         /* common and the free list elements with the smallest size.  */
814         while (sizeof(listRecord) <= (memSizeType) (chunk.beyond - chunk.freemem)) {
815           if (OLD_CHUNK(list_elem, listType, sizeof(listRecord))) {
816             COUNT_FLISTELEM(listRecord, count.list_elem);
817             FREE_L_ELEM(list_elem);
818           } /* if */
819         } /* while */
820         chunk.lost_bytes += (memSizeType) (chunk.beyond - chunk.freemem);
821       } /* if */
822       chunk.size = chunk_size[index];
823       chunk.total_size += chunk.size;
824       chunk.start = (char *) result;
825       chunk.beyond = chunk.start + chunk.size;
826       chunk.freemem = chunk.start + size;
827       chunk.size -= size;
828       chunk.number_of_chunks++;
829     } /* if */
830     logFunction(printf("heap_chunk --> " FMT_U_MEM "\n", (memSizeType) result););
831     return result;
832   } /* heap_chunk */
833 #endif
834 
835 
836 
837 #if DO_HEAP_CHECK
check_heap(long sizediff,const char * file_name,unsigned int line_num)838 void check_heap (long sizediff, const char *file_name, unsigned int line_num)
839 
840   {
841     memSizeType bytes_used;
842     /* static long last_sizediff = 0;
843        static unsigned int last_line_num = 0; */
844 
845   /* check_heap */
846     logFunction(printf("check_heap\n"););
847     bytes_used =
848         ((memSizeType) count.stri) * SIZ_STRI(0) +
849         count.stri_elems * sizeof(strElemType) +
850         ((memSizeType) count.bstri) * SIZ_BSTRI(0) +
851         count.bstri_elems * sizeof(ucharType) +
852         ((memSizeType) count.array) * SIZ_ARR(0) +
853         count.arr_elems * SIZ_REC(objectRecord) +
854         count.rtl_arr_elems * SIZ_REC(rtlObjectType) +
855         ((memSizeType) count.hash) * SIZ_HSH(0) +
856         count.hsh_elems * SIZ_REC(hashElemType) +
857         ((memSizeType) count.helem) * SIZ_REC(hashElemRecord) +
858         ((memSizeType) count.rtl_helem) * SIZ_REC(rtlHashElemRecord) +
859         ((memSizeType) count.set) * SIZ_SET(0) +
860         count.set_elems * SIZ_REC(bitSetType) +
861         ((memSizeType) count.stru) * SIZ_SCT(0) +
862         count.sct_elems * SIZ_REC(objectRecord) +
863         ((memSizeType) count.big) * SIZ_BIG(0) +
864         count.big_elems * SIZ_REC(bigDigitType) +
865         ((memSizeType) count.ident) * SIZ_REC(identRecord) +
866         count.idt_bytes + ((memSizeType) count.idt) +
867         ((memSizeType) count.entity)         * SIZ_REC(entityRecord) +
868         ((memSizeType) count.property)       * SIZ_REC(propertyRecord) +
869         ((memSizeType) count.object)         * SIZ_REC(objectRecord) +
870         ((memSizeType) count.node)           * SIZ_REC(nodeRecord) +
871         ((memSizeType) count.token)          * SIZ_REC(tokenRecord) +
872         ((memSizeType) count.owner)          * SIZ_REC(ownerRecord) +
873         ((memSizeType) count.stack)          * SIZ_REC(stackRecord) +
874         ((memSizeType) count.typelist_elems) * SIZ_REC(typeListRecord) +
875         ((memSizeType) count.type)           * SIZ_REC(typeRecord) +
876         ((memSizeType) count.list_elem)      * SIZ_REC(listRecord) +
877         ((memSizeType) count.block)          * SIZ_REC(blockRecord) +
878         ((memSizeType) count.loclist)        * SIZ_REC(locListRecord) +
879         ((memSizeType) count.infil)          * SIZ_REC(inFileRecord) +
880         ((memSizeType) count.polldata)       * sizeof_pollRecord +
881         ((memSizeType) count.win_bytes) +
882         ((memSizeType) count.process)        * sizeof_processRecord +
883         ((memSizeType) count.sql_func)       * SIZ_REC(sqlFuncRecord) +
884         ((memSizeType) count.database_bytes) +
885         ((memSizeType) count.prepared_stmt_bytes) +
886         ((memSizeType) count.fetch_data_bytes) +
887         ((memSizeType) count.prog)           * SIZ_REC(progRecord) +
888         count.fnam_bytes + ((memSizeType) count.fnam) +
889         count.symb_bytes + ((memSizeType) count.symb) +
890         count.byte;
891     if (bytes_used != hs) {
892       printf("*** %s(%u)\n" FMT_U_MEM " " FMT_U_MEM " " FMT_U_MEM " %ld \n",
893           file_name, line_num, bytes_used, hs, bytes_used - hs, sizediff);
894 /*    heapStatistic();
895       fflush(stdout);
896       printf("should not happen\n");
897       exit(1); */
898 /*  } else {
899       printf("\n%lu %ld %d \n", hs, sizediff, in_file.line); */
900     } /* if */
901     /* last_sizediff = sizediff;
902        last_line_num = line_num; */
903     /* if (sizediff > 0) {
904       printf("\nalloc(%ld)\n", sizediff);
905     } else {
906       printf("\nfree(%ld)\n", -sizediff);
907     } if */
908 /*  show_statistic(); */
909     logFunction(printf("check_heap -->\n"););
910   } /* check_heap */
911 #endif
912