1 /********************************************************************/
2 /*                                                                  */
3 /*  s7   Seed7 interpreter                                          */
4 /*  Copyright (C) 1989 - 2000  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.h                                      */
23 /*  Changes: 1993, 1994  Thomas Mertes                              */
24 /*  Content: Procedures for free memory list maintenance.           */
25 /*                                                                  */
26 /********************************************************************/
27 
28 typedef struct {
29     objectType objects;
30     listType list_elems;
31     nodeType nodes;
32     inFileType infiles;
33   } freeListRootType;
34 
35 #ifdef DO_INIT
36 freeListRootType flist = {NULL, NULL, NULL, NULL};
37 #else
38 EXTERN freeListRootType flist;
39 #endif
40 
41 
42 #if DO_HEAP_LOG
43 #define F_LOG1(X)     printf("\nlalloc(%u) -> %ld\n", sizeof(*X), (long) X),
44 #define F_LOG2(X)     printf("\nlfree(%u) <- %ld\n", sizeof(*X), (long) X),
45 #else
46 #define F_LOG1(X)
47 #define F_LOG2(X)
48 #endif
49 
50 #if USE_CHUNK_ALLOCS
51 #define ALIGN(size)              (((((size) - 1) >> MALLOC_ALIGNMENT) + 1) << MALLOC_ALIGNMENT)
52 #if USE_ALTERNATE_CHUNK_ALLOCS
53 #define OLD_CHUNK(var,tp,byt)    (var = (tp) chunk.freemem, chunk.freemem += (byt), TRUE)
54 #define NEW_CHUNK(var,tp,byt)    ((var = (tp) heap_chunk(byt)) != NULL)
55 #define ALLOC_CHUNK(var,tp,byt)  ((byt) > chunk.beyond - chunk.freemem ? NEW_CHUNK(var, tp, byt) : OLD_CHUNK(var, tp, byt))
56 #define FREE_CHUNK(var,byt)      (chunk.lost_bytes += (byt))
57 #else
58 #define OLD_CHUNK(var,tp,byt)    (var = (tp) chunk.freemem, chunk.freemem += (byt), chunk.size -= (byt), TRUE)
59 #define NEW_CHUNK(var,tp,byt)    ((var = (tp) heap_chunk(byt)) != NULL)
60 #define ALLOC_CHUNK(var,tp,byt)  ((byt) > chunk.size ? NEW_CHUNK(var, tp, byt) : OLD_CHUNK(var, tp, byt))
61 #define FREE_CHUNK(var,byt)      (chunk.lost_bytes += (byt))
62 #endif
63 #else
64 #endif
65 
66 
67 #if USE_CHUNK_ALLOCS
68 #define ALLOC_ID_NAME(var,len)     ALLOC_CHUNK(var, ustriType, ALIGN(SIZ_USTRI(len)))
69 #define FREE_ID_NAME(var,len)      (CNT(CNT2_USTRI(len, SIZ_USTRI(len), count.idt, count.idt_bytes)) FREE_CHUNK(var, ALIGN(SIZ_USTRI(len))))
70 #else
71 #define ALLOC_ID_NAME(var,len)     ALLOC_HEAP(var, ustriType, SIZ_USTRI(len))
72 #define FREE_ID_NAME(var,len)      (CNT(CNT2_USTRI(len, SIZ_USTRI(len), count.idt, count.idt_bytes)) FREE_HEAP(var, SIZ_USTRI(len)))
73 #endif
74 #define COUNT_ID_NAME(len)         CNT1_USTRI((len), SIZ_USTRI(len), count.idt, count.idt_bytes)
75 
76 #if USE_CHUNK_ALLOCS
77 #define ALLOC_FLISTELEM(var,rec)   ALLOC_CHUNK(var, rec *, ALIGN(SIZ_REC(rec)))
78 #else
79 #define ALLOC_FLISTELEM(var,rec)   ALLOC_HEAP(var, rec *, SIZ_REC(rec))
80 #endif
81 
82 #define COUNT_FLISTELEM(rec,cnt)   CNT1_REC(SIZ_REC(rec), cnt)
83 
84 
85 #define HEAP_OBJ(O,T)   (!ALLOC_FLISTELEM(O, T) ? FALSE : (CNT(COUNT_FLISTELEM(T, count.object))    TRUE))
86 #define HEAP_L_E(L,T)   (!ALLOC_FLISTELEM(L, T) ? FALSE : (CNT(COUNT_FLISTELEM(T, count.list_elem)) TRUE))
87 #define HEAP_NODE(N,T)  (!ALLOC_FLISTELEM(N, T) ? FALSE : (CNT(COUNT_FLISTELEM(T, count.node))      TRUE))
88 #define HEAP_FILE(F,T)  (!ALLOC_FLISTELEM(F, T) ? FALSE : (CNT(COUNT_FLISTELEM(T, count.infil))     TRUE))
89 
90 #define POP_OBJ(O)      (O = flist.objects,    flist.objects = flist.objects->value.objValue, F_LOG1(O) TRUE)
91 #define POP_L_E(L)      (L = flist.list_elems, flist.list_elems = flist.list_elems->next,     F_LOG1(L) TRUE)
92 #define POP_NODE(N)     (N = flist.nodes,      flist.nodes = flist.nodes->next1,              F_LOG1(N) TRUE)
93 #define POP_FILE(F)     (F = flist.infiles,    flist.infiles = flist.infiles->next,           F_LOG1(F) TRUE)
94 
95 
96 #if WITH_OBJECT_FREELIST
97 #define ALLOC_OBJECT(O) (flist.objects != NULL ? POP_OBJ(O) : HEAP_OBJ(O, objectRecord))
98 #define FREE_OBJECT(O)  (F_LOG2(O) (O)->value.objValue = flist.objects, (O)->objcategory = 0, flist.objects = (O))
99 /* #define FREE_OBJECT(O)  (printf("FREE_OBJECT(%lu)\n", O), F_LOG2(O) (O)->value.objValue = flist.objects, (O)->objcategory = 0, flist.objects = (O)) */
100 /* #define FREE_OBJECT(O)  (F_LOG2(O) check_obj_flist(O) ? ((O)->value.objValue=flist.objects,(O)->objcategory=0,flist.objects=(O)) : NULL) */
101 #else
102 #define ALLOC_OBJECT(O) HEAP_OBJ(O, objectRecord)
103 #define FREE_OBJECT(O)  FREE_RECORD(O, objectRecord, count.object)
104 #if USE_CHUNK_ALLOCS
105 #error Configuration error: USE_CHUNK_ALLOCS needs WITH_OBJECT_FREELIST
106 #endif
107 #endif
108 
109 #if WITH_LIST_FREELIST
110 #define ALLOC_L_ELEM(L) (flist.list_elems != NULL ? POP_L_E(L) : HEAP_L_E(L, listRecord))
111 #define FREE_L_ELEM(L)  (F_LOG2(L) (L)->next = flist.list_elems, flist.list_elems = (L))
112 #else
113 #define ALLOC_L_ELEM(L) HEAP_L_E(L, listRecord)
114 #define FREE_L_ELEM(L)  FREE_RECORD(L, listRecord, count.list_elem)
115 #if USE_CHUNK_ALLOCS
116 #error Configuration error: USE_CHUNK_ALLOCS needs WITH_LIST_FREELIST
117 #endif
118 #endif
119 
120 #if WITH_NODE_FREELIST
121 #define ALLOC_NODE(N)   (flist.nodes != NULL ? POP_NODE(N) : HEAP_NODE(N, nodeRecord))
122 #define FREE_NODE(N)    (F_LOG2(N) (N)->next1 = flist.nodes, flist.nodes = (N))
123 #else
124 #define ALLOC_NODE(N)   HEAP_NODE(N, nodeRecord)
125 #define FREE_NODE(N)    FREE_RECORD(N, nodeRecord, count.node)
126 #if USE_CHUNK_ALLOCS
127 #error Configuration error: USE_CHUNK_ALLOCS needs WITH_NODE_FREELIST
128 #endif
129 #endif
130 
131 #if WITH_FILE_FREELIST
132 #define ALLOC_FILE(F)   (flist.infiles != NULL ? POP_FILE(F) : HEAP_FILE(F, inFileRecord))
133 #define FREE_FILE(F)    (F_LOG2(F) (F)->next = flist.infiles, flist.infiles = (F))
134 #else
135 #define ALLOC_FILE(F)   HEAP_FILE(F, inFileRecord)
136 #define FREE_FILE(F)    FREE_RECORD(F, inFileRecord, count.infil)
137 #if USE_CHUNK_ALLOCS
138 #error Configuration error: USE_CHUNK_ALLOCS needs WITH_FILE_FREELIST
139 #endif
140 #endif
141 
142 
143 #if DO_HEAP_STATISTIC
144 void heapStatistic (void);
145 #endif
146 memSizeType heapsize (void);
147 #if USE_CHUNK_ALLOCS
148 #ifdef USE_FLIST_ALLOC
149 void *flist_alloc (size_t);
150 #endif
151 #else
152 void reuse_free_lists (void);
153 #endif
154 #if USE_CHUNK_ALLOCS
155 void *heap_chunk (size_t);
156 #endif
157