1 /* i/n/a.h
2 **
3 ** This file is in the public domain.
4 */
5   /**  Options.
6   **/
7     /* U3_MEMORY_DEBUG: add debugging information to heap.  Breaks image.
8     */
9 #     undef U3_MEMORY_DEBUG
10 
11   /**  Constants.
12   **/
13     /* u3a_bits: number of bits in word-addressed pointer.  29 == 2GB.
14     */
15 #     define u3a_bits  U3_OS_LoomBits
16 
17     /* u3a_page: number of bits in word-addressed page.  12 == 16Kbyte page.
18     */
19 #     define u3a_page   12
20 
21     /* u3a_pages: number of pages in memory.
22     */
23 #     define u3a_pages  (1 << (u3a_bits - u3a_page))
24 
25     /* u3a_words: number of words in memory.
26     */
27 #     define u3a_words  (1 << u3a_bits)
28 
29     /* u3a_bytes: number of bytes in memory.
30     */
31 #     define u3a_bytes  (c3_w)((1 << (2 + u3a_bits)))
32 
33     /* u3a_minimum: minimum number of words in a box.
34     */
35 #ifdef U3_MEMORY_DEBUG
36 #     define u3a_minimum   8
37 #else
38 #     define u3a_minimum   6
39 #endif
40 
41     /* u3a_fbox_no: number of free lists per size.
42     */
43 #     define u3a_fbox_no   27
44 
45 
46   /**  Structures.
47   **/
48     /* u3a_atom, u3a_cell: logical atom and cell structures.
49     */
50       typedef struct {
51         c3_w mug_w;
52       } u3a_noun;
53 
54       typedef struct {
55         c3_w mug_w;
56         c3_w len_w;
57         c3_w buf_w[0];
58       } u3a_atom;
59 
60       typedef struct {
61         c3_w    mug_w;
62         u3_noun hed;
63         u3_noun tel;
64       } u3a_cell;
65 
66     /* u3a_box: classic allocation box.
67     **
68     ** The box size is also stored at the end of the box in classic
69     ** bad ass malloc style.  Hence a box is:
70     **
71     **    ---
72     **    siz_w
73     **    use_w
74     **      user data
75     **    siz_w
76     **    ---
77     **
78     ** Do not attempt to adjust this structure!
79     */
80       typedef struct _u3a_box {
81         c3_w   siz_w;                       // size of this box
82         c3_w   use_w;                       // reference count; free if 0
83 #       ifdef U3_MEMORY_DEBUG
84           c3_w   eus_w;                     // recomputed refcount
85           c3_w   cod_w;                     // tracing code
86 #       endif
87       } u3a_box;
88 
89     /* u3a_fbox: free node in heap.  Sets minimum node size.
90     */
91       typedef struct _u3a_fbox {
92         u3a_box               box_u;
93         u3p(struct _u3a_fbox) pre_p;
94         u3p(struct _u3a_fbox) nex_p;
95       } u3a_fbox;
96 
97     /* u3a_road: contiguous allocation and execution context.
98     */
99       typedef struct _u3a_road {
100         u3p(struct _u3a_road) par_p;          //  parent road
101         u3p(struct _u3a_road) kid_p;          //  child road list
102         u3p(struct _u3a_road) nex_p;          //  sibling road
103 
104         u3p(c3_w) cap_p;                      //  top of transient region
105         u3p(c3_w) hat_p;                      //  top of durable region
106         u3p(c3_w) mat_p;                      //  bottom of transient region
107         u3p(c3_w) rut_p;                      //  bottom of durable region
108         u3p(c3_w) ear_p;                      //  original cap if kid is live
109 
110         c3_w fut_w[32];                       //  futureproof buffer
111 
112         struct {                              //  escape buffer
113           union {
114             jmp_buf buf;
115             c3_w buf_w[256];                  //  futureproofing
116           };
117         } esc;
118 
119         struct {                              //  miscellaneous config
120           c3_w fag_w;                         //  flag bits
121         } how;                                //
122 
123         struct {                              //  allocation pools
124           u3p(u3a_fbox) fre_p[u3a_fbox_no];   //  heap by node size log
125           u3p(u3a_fbox) cel_p;                //  custom cell allocator
126           c3_w fre_w;                         //  number of free words
127           c3_w max_w;                         //  maximum allocated
128         } all;
129 
130         struct {                              //  jet dashboard
131           u3p(u3h_root) har_p;                //  warm state
132           u3_noun       das;                  //  cold state
133         } jed;
134 
135         struct {                              //  namespace
136           u3_noun gul;                        //  (list $+(* (unit (unit)))) now
137         } ski;
138 
139         struct {                              //  trace stack
140           u3_noun tax;                        //  (list ,*)
141           u3_noun mer;                        //  emergency buffer to release
142         } bug;
143 
144         struct {                              //  profile stack
145           c3_d    nox_d;                      //  nock steps
146           c3_d    cel_d;                      //  cell allocations
147           u3_noun don;                        //  (list batt)
148           u3_noun day;                        //  doss, only in u3H (moveme)
149         } pro;
150 
151         struct {                              //  memoization
152           u3p(u3h_root) har_p;                //  (map (pair term noun) noun)
153         } cax;
154       } u3a_road;
155       typedef u3a_road u3_road;
156 
157     /* u3a_flag: flags for how.fag_w.  All arena related.
158     */
159       enum u3a_flag {
160         u3a_flag_sand  = 0x1,                 //  bump allocation (XX not impl)
161       };
162 
163 
164   /**  Macros.  Should be better commented.
165   **/
166     /* In and out of the box.
167     */
168 #     define u3a_boxed(len_w)  (len_w + c3_wiseof(u3a_box) + 1)
169 #     define u3a_boxto(box_v)  ( (void *) \
170                                    ( ((c3_w *)(void*)(box_v)) + \
171                                      c3_wiseof(u3a_box) ) )
172 #     define u3a_botox(tox_v)  ( (struct _u3a_box *) \
173                                    (void *) \
174                                    ( ((c3_w *)(void*)(tox_v)) - \
175                                       c3_wiseof(u3a_box)  ) )
176     /* Inside a noun.
177     */
178 #     define u3a_is_cat(som)    (((som) >> 31) ? c3n : c3y)
179 #     define u3a_is_dog(som)    (((som) >> 31) ? c3y : c3n)
180 
181 #     define u3a_is_pug(som)    ((2 == ((som) >> 30)) ? c3y : c3n)
182 #     define u3a_is_pom(som)    ((3 == ((som) >> 30)) ? c3y : c3n)
183 #     define u3a_to_off(som)    ((som) & 0x3fffffff)
184 #     define u3a_to_ptr(som)    (u3a_into(u3a_to_off(som)))
185 #     define u3a_to_wtr(som)    ((c3_w *)u3a_to_ptr(som))
186 #     define u3a_to_pug(off)    (off | 0x80000000)
187 #     define u3a_to_pom(off)    (off | 0xc0000000)
188 
189 #     define u3a_is_atom(som)    c3o(u3a_is_cat(som), \
190                                          u3a_is_pug(som))
191 #     define u3a_is_cell(som)    u3a_is_pom(som)
192 #     define u3a_de_twin(dog, dog_w)  ((dog & 0xc0000000) | u3a_outa(dog_w))
193 
194 #     define u3a_h(som) \
195         ( _(u3a_is_cell(som)) \
196            ? ( ((u3a_cell *)u3a_to_ptr(som))->hed )\
197            : u3m_bail(c3__exit) )
198 
199 #     define u3a_t(som) \
200         ( _(u3a_is_cell(som)) \
201            ? ( ((u3a_cell *)u3a_to_ptr(som))->tel )\
202            : u3m_bail(c3__exit) )
203 
204 #     define  u3a_into(x) ((void *)(u3_Loom + (x)))
205 #     define  u3a_outa(p) (((c3_w*)(void*)(p)) - u3_Loom)
206 
207 #     define  u3a_is_north(r)  __(r->cap_p > r->hat_p)
208 #     define  u3a_is_south(r)  !u3a_is_north(r)
209 
210 #     define  u3a_open(r)      ( (c3y == u3a_is_north(r)) \
211                                   ? (c3_w)(r->cap_p - r->hat_p) \
212                                   : (c3_w)(r->hat_p - r->cap_p) )
213 
214 #     define  u3a_north_is_senior(r, dog) \
215                 __((u3a_to_off(dog) < r->rut_p) ||  \
216                        (u3a_to_off(dog) >= r->mat_p))
217 
218 #     define  u3a_north_is_junior(r, dog) \
219                 __((u3a_to_off(dog) >= r->cap_p) && \
220                        (u3a_to_off(dog) < r->mat_p))
221 
222 #     define  u3a_north_is_normal(r, dog) \
223                 c3a(!(u3a_north_is_senior(r, dog)),  \
224                        !(u3a_north_is_junior(r, dog)))
225 
226 #     define  u3a_south_is_senior(r, dog) \
227                 __((u3a_to_off(dog) < r->mat_p) || \
228                        (u3a_to_off(dog) >= r->rut_p))
229 
230 #     define  u3a_south_is_junior(r, dog) \
231                 __((u3a_to_off(dog) < r->cap_p) && \
232                        (u3a_to_off(dog) >= r->mat_p))
233 
234 #     define  u3a_south_is_normal(r, dog) \
235                 c3a(!(u3a_south_is_senior(r, dog)),  \
236                        !(u3a_south_is_junior(r, dog)))
237 
238 #     define  u3a_is_junior(r, som) \
239                 ( _(u3a_is_cat(som)) \
240                       ?  c3n \
241                       :  _(u3a_is_north(r)) \
242                          ?  u3a_north_is_junior(r, som) \
243                          :  u3a_south_is_junior(r, som) )
244 
245 #     define  u3a_is_senior(r, som) \
246                 ( _(u3a_is_cat(som)) \
247                       ?  c3y \
248                       :  _(u3a_is_north(r)) \
249                          ?  u3a_north_is_senior(r, som) \
250                          :  u3a_south_is_senior(r, som) )
251 
252 
253   /**  Globals.
254   **/
255     /* u3_Road / u3R: current road (thread-local).
256     */
257       c3_global u3_road* u3a_Road;
258 #       define u3R  u3a_Road
259 
260     /* u3_Code: memory code.
261     */
262 #ifdef U3_MEMORY_DEBUG
263       c3_global c3_w u3_Code;
264 #endif
265 
266 #   define u3_Loom      ((c3_w *)(void *)U3_OS_LoomBase)
267 
268   /**  Functions.
269   **/
270     /**  Allocation.
271     **/
272       /* Word-aligned allocation.
273       */
274         /* u3a_walloc(): allocate storage measured in words.
275         */
276           void*
277           u3a_walloc(c3_w len_w);
278 
279         /* u3a_celloc(): allocate a cell.  Faster, sometimes.
280         */
281           c3_w*
282           u3a_celloc(void);
283 
284         /* u3a_wfree(): free storage.
285         */
286           void
287           u3a_wfree(void* lag_v);
288 
289         /* u3a_wealloc(): word realloc.
290         */
291           void*
292           u3a_wealloc(void* lag_v, c3_w len_w);
293 
294         /* u3a_push(): allocate space on the road stack
295         */
296           void*
297           u3a_push(c3_w len_w);
298 
299         /* u3a_pop(): deallocate space on the road stack
300         */
301           void
302           u3a_pop(c3_w len_w);
303 
304         /* u3a_peek(): examine the top of the road stack
305         */
306           void*
307           u3a_peek(c3_w len_w);
308 
309 
310       /* C-style aligned allocation - *not* compatible with above.
311       */
312         /* u3a_malloc(): aligned storage measured in bytes.
313         */
314           void*
315           u3a_malloc(size_t len_i);
316 
317         /* u3a_calloc(): aligned storage measured in bytes.
318         */
319           void*
320           u3a_calloc(size_t num_i, size_t len_i);
321 
322         /* u3a_realloc(): aligned realloc in bytes.
323         */
324           void*
325           u3a_realloc(void* lag_v, size_t len_i);
326 
327         /* u3a_realloc2(): gmp-shaped realloc.
328         */
329           void*
330           u3a_realloc2(void* lag_v, size_t old_i, size_t new_i);
331 
332         /* u3a_free(): free for aligned malloc.
333         */
334           void
335           u3a_free(void* tox_v);
336 
337         /* u3a_free2(): gmp-shaped free.
338         */
339           void
340           u3a_free2(void* tox_v, size_t siz_i);
341 
342       /* Reference and arena control.
343       */
344         /* u3a_gain(): gain a reference count in normal space.
345         */
346           u3_weak
347           u3a_gain(u3_weak som);
348 
349         /* u3a_take(): gain, copying juniors.
350         */
351           u3_noun
352           u3a_take(u3_noun som);
353 
354         /* u3a_left(): true of junior if preserved.
355         */
356           c3_o
357           u3a_left(u3_noun som);
358 
359         /* u3a_lose(): lose a reference.
360         */
361           void
362           u3a_lose(u3_weak som);
363 
364         /* u3a_wash(): wash all lazy mugs in subtree.  RETAIN.
365         */
366           void
367           u3a_wash(u3_noun som);
368 
369         /* u3a_use(): reference count.
370         */
371           c3_w
372           u3a_use(u3_noun som);
373 
374         /* u3a_luse(): check refcount sanity.
375         */
376           void
377           u3a_luse(u3_noun som);
378 
379         /* u3a_mark_ptr(): mark a pointer for gc.  Produce size.
380         */
381           c3_w
382           u3a_mark_ptr(void* ptr_v);
383 
384         /* u3a_mark_mptr(): mark a u3_malloc-allocated ptr for gc.
385         */
386           c3_w
387           u3a_mark_mptr(void* ptr_v);
388 
389         /* u3a_mark_noun(): mark a noun for gc.  Produce size.
390         */
391           c3_w
392           u3a_mark_noun(u3_noun som);
393 
394         /* u3a_sweep(): sweep a fully marked road.
395         */
396           c3_w
397           u3a_sweep(void);
398 
399         /* u3a_sane(): check allocator sanity.
400         */
401           void
402           u3a_sane(void);
403 
404         /* u3a_lush(): leak push.
405         */
406           c3_w
407           u3a_lush(c3_w lab_w);
408 
409         /* u3a_lop(): leak pop.
410         */
411           void
412           u3a_lop(c3_w lab_w);
413 
414         /* u3a_print_memory: print memory amount.
415         */
416           void
417           u3a_print_memory(c3_c* cap_c, c3_w wor_w);
418 
419         /* u3a_deadbeef(): write 0xdeadbeef from hat to cap.
420         */
421           void
422           u3a_deadbeef(void);
423 
424       /* Atoms from proto-atoms.
425       */
426         /* u3a_slab(): create a length-bounded proto-atom.
427         */
428           c3_w*
429           u3a_slab(c3_w len_w);
430 
431         /* u3a_slaq(): u3a_slab() with a defined blocksize.
432         */
433           c3_w*
434           u3a_slaq(c3_g met_g, c3_w len_w);
435 
436         /* u3a_malt(): measure and finish a proto-atom.
437         */
438           u3_noun
439           u3a_malt(c3_w* sal_w);
440 
441         /* u3a_moot(): finish a pre-measured proto-atom; dangerous.
442         */
443           u3_noun
444           u3a_moot(c3_w* sal_w);
445 
446         /* u3a_mint(): finish a measured proto-atom.
447         */
448           u3_noun
449           u3a_mint(c3_w* sal_w, c3_w len_w);
450 
451 
452