19e41a8323b5225d13107c3cd76e439ca1bedec9
[vlp.git] / src / int / memory.c
1 #include "depend.h"
2 #include "genint.h"
3 #include "int.h"
4 #include "process.h"
5 #include "intproto.h"
6
7 /**
8  * @file Memory management routines
9  */
10
11 #ifndef NO_PROTOTYPES
12 static void compandtake(word, word *, word *, word *, bool);
13 static void sinsert(word);
14 #else
15 static void compandtake();
16 static void sinsert();
17 #endif
18
19
20 int compactify_allowed=1;
21 #define space 400 /* words */
22
23
24 void request(word app, word *ah, word *am)
25 {
26         word t2, t4, t5;
27         bool wascompactified, found;
28
29         if (app >= MAXAPPT)
30                 errsignal(RTEMEMOV);
31         wascompactified = FALSE;
32
33         if (compactify_allowed && thisp->force_compactification) {
34                 compactify();
35                 thisp->force_compactification = FALSE;
36                 wascompactified = TRUE;
37         }
38
39         /* reserve dictionary item */
40         if (thisp->freeitem != 0) {
41                 *ah = thisp->freeitem;
42                 thisp->freeitem = M[*ah];
43         }
44         else {
45                 *ah = thisp->lastitem - 2;
46                 /* cannot take free item */
47                 if (*ah <= thisp->lastused + space) {
48                         if (compactify_allowed) {
49                                 if(!wascompactified) {
50                                         compactify();
51                                         wascompactified = TRUE;
52                                 }
53                         } else {
54                                 thisp->force_compactification = TRUE;
55                         }
56                         *ah = thisp->lastitem - 2;
57                         if (*ah <= thisp->lastused)
58                                 errsignal(RTEMEMOV);
59                 }
60
61                 thisp->lastitem = *ah;
62                 /* clear mark */
63                 M[*ah + 1] = 0;
64         }
65         /* now we have a free dict. item */
66
67         /* special case app=2 */
68         if (app == 2 && thisp->headk2 != 0) {
69                 *am = thisp->headk2;
70                 thisp->headk2 = M[*am + SHORTLINK];
71         } else {
72                 word t1 = thisp->headk;
73                 found = FALSE;
74                 t4 = 0;
75                 while (t1 != thisp->lower && !found) {
76                         t2 = M[t1];
77                         if (t2 == app)
78                                 found = TRUE;
79                         else if (t2 - app >= 2)
80                                 found = TRUE;
81                         else {
82                                 t4 = t1;
83                                 t1 = M[t1 + LONGLINK];
84                         }
85                 }
86                 if(found) {
87                         t5 = M[t1 + SHORTLINK];
88                         if (t5 != 0)
89                                 M[t5 + LONGLINK] = M[t1 + LONGLINK];
90                         else
91                                 t5 = M[t1 + LONGLINK];
92                         if (t4 == 0)
93                                 thisp->headk = t5;
94                         else
95                                 M[t4 + LONGLINK] = t5;
96
97                         *am = t1;
98                         /* at least two extra words */
99                         if (t2 > app) {
100                                 t5 = t1 + app;
101                                 M[t5] = t2 - app;
102                                 sinsert(t5);
103                         }
104                 } else if (thisp->lastitem - thisp->lastused > app + space) {
105                         *am = thisp->lastused+1;
106                         thisp->lastused += app;
107                 } else {
108                         /* return dictionary item */
109                         M[*ah] = thisp->freeitem;
110                         thisp->freeitem = *ah;
111                         if(compactify_allowed) {
112                                 if( !wascompactified )
113                                         compactify();
114                         } else
115                                 thisp->force_compactification = TRUE;
116
117                         /* reserve dictionary item */
118                         *ah = thisp->lastitem-2;
119                         thisp->lastitem = *ah;
120                         /* clear mark */
121                         M[*ah + 1] = 0;
122                         if (thisp->lastitem - thisp->lastused > app) {
123                                 *am = thisp->lastused + 1;
124                                 thisp->lastused += app;
125                         }
126                         else
127                                 errsignal(RTEMEMOV);
128                 }
129         }
130         M[*am] = app;
131         for (t2 = *am+1; t2 < *am + app; t2++)
132                 M[t2] = 0;
133
134         M[*ah] = *am;
135 }
136
137 /* Dispose of a memory item. */
138 static void sinsert(word am)
139 {
140         word t1, t2, t3, t4;
141         /* appetite */
142         t1 = M[ am ];
143         /* a special list should be used */
144         if (t1 == 2) {
145                 M[am + SHORTLINK] = thisp->headk2;
146                 thisp->headk2 = am;
147         }
148         else {
149                 t2 = thisp->headk;
150                 t4 = 0;
151                 /* look for a proper place */
152                 while (TRUE) {
153                         /* appetite */
154                         t3 = M[t2];
155                         /* an entry with matching appetite */
156                         if (t1 == t3) {
157                                 M[am + SHORTLINK] = M[t2 + SHORTLINK];
158                                 M[t2 + SHORTLINK] = am;
159                                 break;
160                         }
161                         else if (t1 < t3) {
162                                 M[am + LONGLINK] = t2;
163                                 M[am + SHORTLINK] = 0;
164                                 if (t4 == 0)
165                                         thisp->headk = am;
166                                 else
167                                         M[t4 + LONGLINK] = am;
168                                 break;
169                         }
170                         else {
171                                 t4 = t2;
172                                 t2 = M[t2 + LONGLINK];
173                         }
174                 }
175         }
176 }
177
178 /**
179  * Simple kill.
180  */
181 void disp(virtaddr *virt)
182 {
183         word t1, t2;
184
185         t1 = M[virt->addr + 1];
186         /* not none */
187         if (t1 == virt->mark) {
188                 /* advance mark */
189                 t1++;
190                 /* am */
191                 t2 = M[virt->addr];
192                 M[virt->addr + 1] = t1;
193                 /* mark still usable */
194                 if (t1 != MAXMARKER) {
195                         M[virt->addr] = thisp->freeitem;
196                         thisp->freeitem = virt->addr;
197                 }
198                 
199                 /* now dictionary item is released */
200                 
201                 /* on the boundary */
202                 if (t2 + M[t2] - 1 == thisp->lastused)
203                         thisp->lastused = t2 - 1;
204                 else
205                         sinsert(t2);
206         }
207 }
208
209 /**
210  * Compute available memory size
211  */
212 word memavail()
213 {
214         word t1, t2, avail;
215
216         /* contiguos memory */
217         avail = thisp->lastitem-thisp->lastused - 1;
218         /* go through killed 2 list */
219         t1 = thisp->headk2;
220         while (t1 != 0) {
221                 avail += 2;
222                 t1 = M[t1 + SHORTLINK];
223         }
224         t1 = thisp->headk;
225         /* go through killed object list */
226         while (t1 != thisp->lower) {
227                 t2 = t1;
228                 while (t2 != 0) {
229                         avail += M[t2];
230                         t2 = M[t2 + SHORTLINK];
231                 }
232                 t1 = M[t1 + LONGLINK];
233         }
234         /* go through free item list */
235         t1 = thisp->freeitem;
236         while (t1 != 0) {
237                 avail += 2;
238                 t1 = M[t1];
239         }
240         return avail;
241 }