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