forked from urbit/vere
-
Notifications
You must be signed in to change notification settings - Fork 0
/
allocate.h
746 lines (611 loc) · 21.8 KB
/
allocate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
#ifndef U3_ALLOCATE_H
#define U3_ALLOCATE_H
#include "error.h"
#include "manage.h"
/** Constants.
**/
/* u3a_bits: number of bits in word-addressed pointer. 29 == 2GB.
*/
# define u3a_bits U3_OS_LoomBits /* 30 */
/* u3a_vits: number of virtual bits in a noun reference gained via shifting
*/
# define u3a_vits 1
/* u3a_walign: references into the loom are guaranteed to be word-aligned to:
*/
# define u3a_walign (1 << u3a_vits)
/* u3a_balign: u3a_walign in bytes
*/
# define u3a_balign (sizeof(c3_w)*u3a_walign)
/* u3a_bits_max: max loom bex
*/
# define u3a_bits_max (8 * sizeof(c3_w) + u3a_vits)
/* u3a_page: number of bits in word-addressed page. 12 == 16K page
*/
# define u3a_page 12ULL
/* u3a_pages: maximum number of pages in memory.
*/
# define u3a_pages (1ULL << (u3a_bits + u3a_vits - u3a_page) )
/* u3a_words: maximum number of words in memory.
*/
# define u3a_words ( 1ULL << (u3a_bits + u3a_vits))
/* u3a_bytes: maximum number of bytes in memory.
*/
# define u3a_bytes ((sizeof(c3_w) * u3a_words))
/* u3a_cells: number of representable cells.
*/
# define u3a_cells (( u3a_words / u3a_minimum ))
/* u3a_maximum: maximum loom object size (largest possible atom).
*/
# define u3a_maximum ( u3a_words - (c3_wiseof(u3a_box) + c3_wiseof(u3a_atom) + 1))
/* u3a_minimum: minimum loom object size (actual size of a cell).
*/
# define u3a_minimum ((c3_w)( 1 + c3_wiseof(u3a_box) + c3_wiseof(u3a_cell) ))
/* u3a_fbox_no: number of free lists per size.
*/
# define u3a_fbox_no 27
/** Structures.
**/
/* u3a_atom, u3a_cell: logical atom and cell structures.
*/
typedef struct {
c3_w mug_w;
} u3a_noun;
typedef struct {
c3_w mug_w;
c3_w len_w;
c3_w buf_w[0];
} u3a_atom;
typedef struct {
c3_w mug_w;
u3_noun hed;
u3_noun tel;
} u3a_cell;
/* u3a_box: classic allocation box.
**
** The box size is also stored at the end of the box in classic
** bad ass malloc style. Hence a box is:
**
** ---
** siz_w
** use_w
** user data
** siz_w
** ---
**
** Do not attempt to adjust this structure!
*/
typedef struct _u3a_box {
c3_w siz_w; // size of this box
c3_w use_w; // reference count; free if 0
# ifdef U3_MEMORY_DEBUG
c3_w eus_w; // recomputed refcount
c3_w cod_w; // tracing code
# endif
} u3a_box;
/* u3a_fbox: free node in heap. Sets minimum node size.
*/
typedef struct _u3a_fbox {
u3a_box box_u;
u3p(struct _u3a_fbox) pre_p;
u3p(struct _u3a_fbox) nex_p;
} u3a_fbox;
/* u3a_jets: jet dashboard
*/
typedef struct _u3a_jets {
u3p(u3h_root) hot_p; // hot state (home road only)
u3p(u3h_root) war_p; // warm state
u3p(u3h_root) cod_p; // cold state
u3p(u3h_root) han_p; // hank cache
u3p(u3h_root) bas_p; // battery hashes
} u3a_jets;
/* u3a_road: contiguous allocation and execution context.
*/
typedef struct _u3a_road {
u3p(struct _u3a_road) par_p; // parent road
u3p(struct _u3a_road) kid_p; // child road list
u3p(struct _u3a_road) nex_p; // sibling road
u3p(c3_w) cap_p; // top of transient region
u3p(c3_w) hat_p; // top of durable region
u3p(c3_w) mat_p; // bottom of transient region
u3p(c3_w) rut_p; // bottom of durable region
u3p(c3_w) ear_p; // original cap if kid is live
c3_w fut_w[32]; // futureproof buffer
struct { // escape buffer
union {
jmp_buf buf;
c3_w buf_w[256]; // futureproofing
};
} esc;
struct { // miscellaneous config
c3_w fag_w; // flag bits
} how; //
struct { // allocation pools
u3p(u3a_fbox) fre_p[u3a_fbox_no]; // heap by node size log
u3p(u3a_fbox) cel_p; // custom cell allocator
c3_w fre_w; // number of free words
c3_w max_w; // maximum allocated
} all;
u3a_jets jed; // jet dashboard
struct { // bytecode state
u3p(u3h_root) har_p; // formula->post of bytecode
} byc;
struct { // scry namespace
u3_noun gul; // (list $+(* (unit (unit)))) now
} ski;
struct { // trace stack
u3_noun tax; // (list ,*)
u3_noun mer; // emergency buffer to release
} bug;
struct { // profile stack
c3_d nox_d; // nock steps
c3_d cel_d; // cell allocations
u3_noun don; // (list batt)
u3_noun trace; // (list trace)
u3_noun day; // doss, only in u3H (moveme)
} pro;
struct { // memoization caches
u3p(u3h_root) har_p; // transient
u3p(u3h_root) per_p; // persistent
} cax;
} u3a_road;
typedef u3a_road u3_road;
/* u3a_flag: flags for how.fag_w. All arena related.
*/
enum u3a_flag {
u3a_flag_sand = 0x1, // bump allocation (XX not impl)
};
/* u3a_pile: stack control, abstracted over road direction.
*/
typedef struct _u3a_pile {
c3_ws mov_ws;
c3_ws off_ws;
u3_post top_p;
#ifdef U3_MEMORY_DEBUG
u3a_road* rod_u;
#endif
} u3a_pile;
/** Macros. Should be better commented.
**/
/* In and out of the box.
u3a_boxed -> sizeof u3a_box + allocation size (len_w) + 1 (for storing the redundant size)
u3a_boxto -> the region of memory adjacent to the box.
u3a_botox -> the box adjacent to the region of memory
*/
# define u3a_boxed(len_w) (len_w + c3_wiseof(u3a_box) + 1)
# define u3a_boxto(box_v) ( (void *) \
( (u3a_box *)(void *)(box_v) + 1 ) )
# define u3a_botox(tox_v) ( (u3a_box *)(void *)(tox_v) - 1 )
/* Inside a noun.
*/
/* u3a_is_cat(): yes if noun [som] is direct atom.
*/
# define u3a_is_cat(som) (((som) >> 31) ? c3n : c3y)
/* u3a_is_dog(): yes if noun [som] is indirect noun.
*/
# define u3a_is_dog(som) (((som) >> 31) ? c3y : c3n)
/* u3a_is_pug(): yes if noun [som] is indirect atom.
*/
# define u3a_is_pug(som) ((0b10 == ((som) >> 30)) ? c3y : c3n)
/* u3a_is_pom(): yes if noun [som] is indirect cell.
*/
# define u3a_is_pom(som) ((0b11 == ((som) >> 30)) ? c3y : c3n)
/* u3a_is_atom(): yes if noun [som] is direct atom or indirect atom.
*/
# define u3a_is_atom(som) c3o(u3a_is_cat(som), \
u3a_is_pug(som))
# define u3ud(som) u3a_is_atom(som)
/* u3a_is_cell: yes if noun [som] is cell.
*/
# define u3a_is_cell(som) u3a_is_pom(som)
# define u3du(som) u3a_is_cell(som)
/* u3a_h(): get head of cell [som]. Bail if [som] is not cell.
*/
# define u3a_h(som) \
( _(u3a_is_cell(som)) \
? ( ((u3a_cell *)u3a_to_ptr(som))->hed )\
: u3m_bail(c3__exit) )
# define u3h(som) u3a_h(som)
/* u3a_t(): get tail of cell [som]. Bail if [som] is not cell.
*/
# define u3a_t(som) \
( _(u3a_is_cell(som)) \
? ( ((u3a_cell *)u3a_to_ptr(som))->tel )\
: u3m_bail(c3__exit) )
# define u3t(som) u3a_t(som)
# define u3to(type, x) ((type *)u3a_into(x))
# define u3tn(type, x) (x) ? (type*)u3a_into(x) : (void*)NULL
# define u3of(type, x) (u3a_outa((type*)x))
/* u3a_is_north(): yes if road [r] is north road.
*/
# define u3a_is_north(r) __((r)->cap_p > (r)->hat_p)
/* u3a_is_south(): yes if road [r] is south road.
*/
# define u3a_is_south(r) !u3a_is_north((r))
/* u3a_open(): words of contiguous free space in road [r]
*/
# define u3a_open(r) ( (c3y == u3a_is_north(r)) \
? (c3_w)((r)->cap_p - (r)->hat_p) \
: (c3_w)((r)->hat_p - (r)->cap_p) )
/* u3a_full(): total words in road [r];
** u3a_full(r) == u3a_heap(r) + u3a_temp(r) + u3a_open(r)
*/
# define u3a_full(r) ( (c3y == u3a_is_north(r)) \
? (c3_w)((r)->mat_p - (r)->rut_p) \
: (c3_w)((r)->rut_p - (r)->mat_p) )
/* u3a_heap(): words of heap in road [r]
*/
# define u3a_heap(r) ( (c3y == u3a_is_north(r)) \
? (c3_w)((r)->hat_p - (r)->rut_p) \
: (c3_w)((r)->rut_p - (r)->hat_p) )
/* u3a_temp(): words of stack in road [r]
*/
# define u3a_temp(r) ( (c3y == u3a_is_north(r)) \
? (c3_w)((r)->mat_p - (r)->cap_p) \
: (c3_w)((r)->cap_p - (r)->mat_p) )
# define u3a_north_is_senior(r, dog) \
__((u3a_to_off(dog) < (r)->rut_p) || \
(u3a_to_off(dog) >= (r)->mat_p))
# define u3a_north_is_junior(r, dog) \
__((u3a_to_off(dog) >= (r)->cap_p) && \
(u3a_to_off(dog) < (r)->mat_p))
# define u3a_north_is_normal(r, dog) \
c3a(!(u3a_north_is_senior(r, dog)), \
!(u3a_north_is_junior(r, dog)))
# define u3a_south_is_senior(r, dog) \
__((u3a_to_off(dog) < (r)->mat_p) || \
(u3a_to_off(dog) >= (r)->rut_p))
# define u3a_south_is_junior(r, dog) \
__((u3a_to_off(dog) < (r)->cap_p) && \
(u3a_to_off(dog) >= (r)->mat_p))
# define u3a_south_is_normal(r, dog) \
c3a(!(u3a_south_is_senior(r, dog)), \
!(u3a_south_is_junior(r, dog)))
# define u3a_is_junior(r, som) \
( _(u3a_is_cat(som)) \
? c3n \
: _(u3a_is_north(r)) \
? u3a_north_is_junior(r, som) \
: u3a_south_is_junior(r, som) )
# define u3a_is_senior(r, som) \
( _(u3a_is_cat(som)) \
? c3y \
: _(u3a_is_north(r)) \
? u3a_north_is_senior(r, som) \
: u3a_south_is_senior(r, som) )
# define u3a_is_mutable(r, som) \
( _(u3a_is_atom(som)) \
? c3n \
: _(u3a_is_senior(r, som)) \
? c3n \
: _(u3a_is_junior(r, som)) \
? c3n \
: (u3a_botox(u3a_to_ptr(som))->use_w == 1) \
? c3y : c3n )
/* like _box_vaal but for rods. Again, probably want to prefix validation
functions at the very least. Maybe they can be defined in their own header.
ps. while arguably cooler to have this compile to
do {(void(0));(void(0));} while(0)
It may be nicer to just wrap an inline function in #ifdef C3DBG guards. You
could even return the then validated road like
u3a_road f() {
u3a_road rod_u;
...
return _rod_vaal(rod_u);
}
*/
# define _rod_vaal(rod_u) \
do { \
c3_dessert(((uintptr_t)((u3a_road*)(rod_u))->hat_p \
& u3a_walign-1) == 0); \
} while(0)
/** Globals.
**/
/// Current road (thread-local).
extern u3_road* u3a_Road;
# define u3R u3a_Road
/* u3_Code: memory code.
*/
#ifdef U3_MEMORY_DEBUG
extern c3_w u3_Code;
#endif
# define u3_Loom ((c3_w *)(void *)U3_OS_LoomBase)
/* u3a_into(): convert loom offset [x] into generic pointer.
*/
# define u3a_into(x) ((void *)(u3_Loom + (x)))
/* u3a_outa(): convert pointer [p] into word offset into loom.
*/
# define u3a_outa(p) ((c3_w *)(void *)(p) - u3_Loom)
/* u3a_to_off(): mask off bits 30 and 31 from noun [som].
*/
# define u3a_to_off(som) (((som) & 0x3fffffff) << u3a_vits)
/* u3a_to_ptr(): convert noun [som] into generic pointer into loom.
*/
# define u3a_to_ptr(som) (u3a_into(u3a_to_off(som)))
/* u3a_to_wtr(): convert noun [som] into word pointer into loom.
*/
# define u3a_to_wtr(som) ((c3_w *)u3a_to_ptr(som))
/** Inline functions.
**/
/* u3a_to_pug(): set bit 31 of [off].
*/
inline c3_w u3a_to_pug(c3_w off) {
c3_dessert((off & u3a_walign-1) == 0);
return (off >> u3a_vits) | 0x80000000;
}
/* u3a_to_pom(): set bits 30 and 31 of [off].
*/
inline c3_w u3a_to_pom(c3_w off) {
c3_dessert((off & u3a_walign-1) == 0);
return (off >> u3a_vits) | 0xc0000000;
}
/** road stack.
**/
/* u3a_drop(): drop a road stack frame per [pil_u].
*/
inline void
u3a_drop(const u3a_pile* pil_u)
{
u3R->cap_p -= pil_u->mov_ws;
}
/* u3a_peek(): examine the top of the road stack.
*/
inline void*
u3a_peek(const u3a_pile* pil_u)
{
return u3to(void, (u3R->cap_p + pil_u->off_ws));
}
/* u3a_pop(): drop a road stack frame, peek at the new top.
*/
inline void*
u3a_pop(const u3a_pile* pil_u)
{
u3a_drop(pil_u);
return u3a_peek(pil_u);
}
/* u3a_push(): push a frame onto the road stack, per [pil_u].
*/
inline void*
u3a_push(const u3a_pile* pil_u)
{
u3R->cap_p += pil_u->mov_ws;
#ifndef U3_GUARD_PAGE
// !off means we're on a north road
//
if ( !pil_u->off_ws ) {
if( !(u3R->cap_p > u3R->hat_p) ) {
u3m_bail(c3__meme);
}
# ifdef U3_MEMORY_DEBUG
u3_assert( pil_u->top_p >= u3R->cap_p );
# endif
}
else {
if( !(u3R->cap_p < u3R->hat_p) ) {
u3m_bail(c3__meme);
}
# ifdef U3_MEMORY_DEBUG
u3_assert( pil_u->top_p <= u3R->cap_p );
# endif
}
#endif /* ifndef U3_GUARD_PAGE */
#ifdef U3_MEMORY_DEBUG
u3_assert( pil_u->rod_u == u3R );
#endif
return u3a_peek(pil_u);
}
/* u3a_pile_done(): assert valid upon completion.
*/
inline c3_o
u3a_pile_done(const u3a_pile* pil_u)
{
return (pil_u->top_p == u3R->cap_p) ? c3y : c3n;
}
/** Functions.
**/
/** Allocation.
**/
/* Word-aligned allocation.
*/
/* u3a_walloc(): allocate storage measured in words.
*/
void*
u3a_walloc(c3_w len_w);
/* u3a_celloc(): allocate a cell. Faster, sometimes.
*/
c3_w*
u3a_celloc(void);
/* u3a_wfree(): free storage.
*/
void
u3a_wfree(void* lag_v);
/* u3a_wtrim(): trim storage.
*/
void
u3a_wtrim(void* tox_v, c3_w old_w, c3_w len_w);
/* u3a_wealloc(): word realloc.
*/
void*
u3a_wealloc(void* lag_v, c3_w len_w);
/* u3a_pile_prep(): initialize stack control.
*/
void
u3a_pile_prep(u3a_pile* pil_u, c3_w len_w);
/* C-style aligned allocation - *not* compatible with above.
*/
/* u3a_malloc(): aligned storage measured in bytes.
*/
void*
u3a_malloc(size_t len_i);
/* u3a_calloc(): aligned storage measured in bytes.
*/
void*
u3a_calloc(size_t num_i, size_t len_i);
/* u3a_realloc(): aligned realloc in bytes.
*/
void*
u3a_realloc(void* lag_v, size_t len_i);
/* u3a_free(): free for aligned malloc.
*/
void
u3a_free(void* tox_v);
/* Reference and arena control.
*/
/* u3a_gain(): gain a reference count in normal space.
*/
u3_weak
u3a_gain(u3_weak som);
# define u3k(som) u3a_gain(som)
/* u3a_take(): gain, copying juniors.
*/
u3_noun
u3a_take(u3_noun som);
/* u3a_left(): true of junior if preserved.
*/
c3_o
u3a_left(u3_noun som);
/* u3a_lose(): lose a reference.
*/
void
u3a_lose(u3_weak som);
# define u3z(som) u3a_lose(som)
/* u3a_wash(): wash all lazy mugs in subtree. RETAIN.
*/
void
u3a_wash(u3_noun som);
/* u3a_use(): reference count.
*/
c3_w
u3a_use(u3_noun som);
/* u3a_wed(): unify noun references.
*/
void
u3a_wed(u3_noun* a, u3_noun* b);
/* u3a_luse(): check refcount sanity.
*/
void
u3a_luse(u3_noun som);
/* u3a_mark_ptr(): mark a pointer for gc. Produce size.
*/
c3_w
u3a_mark_ptr(void* ptr_v);
/* u3a_mark_mptr(): mark a u3_malloc-allocated ptr for gc.
*/
c3_w
u3a_mark_mptr(void* ptr_v);
/* u3a_mark_noun(): mark a noun for gc. Produce size.
*/
c3_w
u3a_mark_noun(u3_noun som);
/* u3a_mark_road(): mark ad-hoc persistent road structures.
*/
c3_w
u3a_mark_road(FILE* fil_u);
/* u3a_reclaim(): clear ad-hoc persistent caches to reclaim memory.
*/
void
u3a_reclaim(void);
/* u3a_rewrite_compact(): rewrite pointers in ad-hoc persistent road structures.
*/
void
u3a_rewrite_compact(void);
/* u3a_rewrite_ptr(): mark a pointer as already having been rewritten
*/
c3_o
u3a_rewrite_ptr(void* ptr_v);
/* u3a_rewrite_noun(): rewrite a noun for compaction.
*/
void
u3a_rewrite_noun(u3_noun som);
/* u3a_rewritten(): rewrite a pointer for compaction.
*/
u3_post
u3a_rewritten(u3_post som_p);
/* u3a_rewritten(): rewritten noun pointer for compaction.
*/
u3_noun
u3a_rewritten_noun(u3_noun som);
/* u3a_count_noun(): count size of noun.
*/
c3_w
u3a_count_noun(u3_noun som);
/* u3a_discount_noun(): clean up after counting a noun.
*/
c3_w
u3a_discount_noun(u3_noun som);
/* u3a_count_ptr(): count a pointer for gc. Produce size. */
c3_w
u3a_count_ptr(void* ptr_v);
/* u3a_discount_ptr(): discount a pointer for gc. Produce size. */
c3_w
u3a_discount_ptr(void* ptr_v);
/* u3a_idle(): measure free-lists in [rod_u]
*/
c3_w
u3a_idle(u3a_road* rod_u);
/* u3a_ream(): ream free-lists.
*/
void
u3a_ream(void);
/* u3a_sweep(): sweep a fully marked road.
*/
c3_w
u3a_sweep(void);
/* u3a_pack_seek(): sweep the heap, modifying boxes to record new addresses.
*/
void
u3a_pack_seek(u3a_road* rod_u);
/* u3a_pack_move(): sweep the heap, moving boxes to new addresses.
*/
void
u3a_pack_move(u3a_road* rod_u);
/* u3a_sane(): check allocator sanity.
*/
void
u3a_sane(void);
/* u3a_lush(): leak push.
*/
c3_w
u3a_lush(c3_w lab_w);
/* u3a_lop(): leak pop.
*/
void
u3a_lop(c3_w lab_w);
/* u3a_print_time: print microsecond time.
*/
void
u3a_print_time(c3_c* str_c, c3_c* cap_c, c3_d mic_d);
/* u3a_print_memory(): print memory amount.
*/
void
u3a_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w);
/* u3a_prof(): mark/measure/print memory profile. RETAIN.
*/
c3_w
u3a_prof(FILE* fil_u, c3_w den_w, u3_noun mas);
/* u3a_maid(): maybe print memory.
*/
c3_w
u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w);
/* u3a_deadbeef(): write 0xdeadbeef from hat to cap.
*/
void
u3a_deadbeef(void);
/* u3a_walk_fore(): preorder traversal, visits ever limb of a noun.
**
** cells are visited *before* their heads and tails
** and can shortcircuit traversal by returning [c3n]
*/
void
u3a_walk_fore(u3_noun a,
void* ptr_v,
void (*pat_f)(u3_atom, void*),
c3_o (*cel_f)(u3_noun, void*));
/* u3a_string(): `a` as an on-loom c-string.
*/
c3_c*
u3a_string(u3_atom a);
/* u3a_loom_sane(): sanity checks the state of the loom for obvious corruption
*/
void
u3a_loom_sane();
#endif /* ifndef U3_ALLOCATE_H */