/* include/rail.h ** ** This file is in the public domain. */ /** Data types. **/ /** Ray types. **/ /* u2_rail: an allocation control frame. */ typedef u2_ray u2_rail; /* u2_wire: an execution context, inheriting rail */ typedef u2_ray u2_wire; /** Structures - in loom space. **/ /* Base rail. */ typedef struct _u2_loom_rail { u2_ray cap_r; // top of transient region u2_ray hat_r; // top of new durable region u2_ray mat_r; // bottom of transient region u2_ray rut_r; // bottom of new durable region c3_m hip_m; // memory model in durable; c3__rock, c3__sand } u2_loom_rail; # define u2_rail_cap_r(ral_r) *u2_at(ral_r, u2_loom_rail, cap_r) # define u2_rail_hat_r(ral_r) *u2_at(ral_r, u2_loom_rail, hat_r) # define u2_rail_mat_r(ral_r) *u2_at(ral_r, u2_loom_rail, mat_r) # define u2_rail_rut_r(ral_r) *u2_at(ral_r, u2_loom_rail, rut_r) # define u2_rail_hip_m(ral_r) *u2_at(ral_r, u2_loom_rail, hip_m) /* Pork - base of frame. */ typedef struct { u2_ray mut_r; // parent mat u2_ray rit_r; // parent rut c3_m hap_m; // parent hip } u2_loom_pork; # define u2_pork_mut_r(pik_r) *u2_at(pik_r, u2_loom_pork, mut_r) # define u2_pork_rit_r(pik_r) *u2_at(pik_r, u2_loom_pork, rit_r) # define u2_pork_hap_m(pik_r) *u2_at(pik_r, u2_loom_pork, hap_m) /* Floe - a solid rail allocator. Implied by `hip_m == c3__sand`. */ typedef struct { } u2_loom_floe; /* Soup - a liquid rail allocator. */ # define u2_soup_free_no 28 typedef struct { u2_ray fre_r[u2_soup_free_no]; // doubly-linked free lists u2_cash_slot lot_s; // modern memo cache #ifdef U2_PROFILE_MEMORY c3_w liv_w; // number of words live #endif } u2_loom_soup; # define u2_soup_fre_r(sop_r, x) *u2_at(sop_r, u2_loom_soup, fre_r[x]) # define u2_soup_lot_r(sop_r) u2_aftr(sop_r, u2_loom_soup, lot_s) # define u2_soup_liv_w(sop_r) *u2_at(sop_r, u2_loom_soup, liv_w) /* A noun box, for liquid hats. Behind pointer, addressed fwd. ** ** 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 _u2_loom_rail_box { c3_w siz_w; // size of this box c3_w use_w; // reference count; free if 0 } u2_loom_rail_box; # define u2_rail_box_siz(box) *u2_at(box, u2_loom_rail_box, siz_w) # define u2_rail_box_use(box) *u2_at(box, u2_loom_rail_box, use_w) /* A free node. Addressed from the box. */ typedef struct _u2_loom_rail_hut { u2_loom_rail_box b; u2_ray pre_r; // next on free list u2_ray nex_r; // next on free list } u2_loom_rail_hut; # define u2_rail_hut_siz(hut) *u2_at(hut, u2_loom_rail_hut, b.siz_w) # define u2_rail_hut_use(hut) *u2_at(hut, u2_loom_rail_hut, b.use_w) # define u2_rail_hut_pre(hut) *u2_at(hut, u2_loom_rail_hut, pre_r) # define u2_rail_hut_nex(hut) *u2_at(hut, u2_loom_rail_hut, nex_r) /** Abbreviations. **/ # define u2_rc(ral_r, a, b) u2_rl_cell(ral_r, a, b) # define u2_rt(ral_r, a, b, c) u2_rl_trel(ral_r, a, b, c) # define u2_rq(ral_r, a, b, c, d) u2_rl_qual(ral_r, a, b, c, d) # define u2_ri(ral_r, a, b, c, d, e) u2_rl_quil(ral_r, a, b, c, d, e) # define u2_ro(ral_r, a) u2_rl_lone(ral_r, a) # define u2_ru(ral_r, a) u2_rl_unit(ral_r, a) # define u2_rx(ral_r, a) u2_rl_take(ral_r, a) # define u2_rz(ral_r, a) u2_rl_lose(ral_r, a) # define u2_rl u2_rl_list # define u2_rk u2_rl_rack /** Functions. **/ /** Miscellaneous and interesting. **/ /* u2_rl_boot(): ** ** Create an empty rail in an empty loom, with memory model `hip`. ** See u2_rl_leap() for storage policies. */ u2_ray u2_rl_boot(c3_m hip_m); /* u2_rl_clear(): ** ** Yes iff [lef] does not point to any word >= [net] ** and < [bat]. */ u2_bean u2_rl_clear(u2_noun lef, u2_ray net_r, u2_ray bat_r); /* u2_rl_init(): ** ** Install an empty rail within `hat_r` and `mat_r` in the loom, ** with memory model `hip`. ** ** Returns ray to rail, which always equalls the passed `mat_r`. */ u2_ray u2_rl_init(c3_m hip_m, u2_ray hat_r, u2_ray mat_r); /* u2_rl_dump(): ** ** Print memory structure for benefit of archeologists. */ void u2_rl_dump(u2_ray ral_r); /* u2_rl_drain(): ** ** Clear the memo cache (soup). */ void u2_rl_drain(u2_ray ral_r); /* u2_rl_fall(): ** ** Reverse the beams backward, restoring the old frame. */ void u2_rl_fall(u2_ray ral_r); /* u2_rl_fall_part(): ** ** Fall on `ral`, also releasing the partition `aux`. */ void u2_rl_fall_part(u2_ray ral_r, u2_ray aux_r); /* u2_rl_flog(): ** ** Release the can, setting cap to mat. */ void u2_rl_flog(u2_ray ral_r); /* u2_rl_gain(): ** ** Gain a reference to `som`, returning it. */ u2_weak // transfer u2_rl_gain(u2_ray ral_r, u2_weak som); // retain /* u2_rl_free(): ** ** Free storage allocated by u2_rl_malloc(). */ void u2_rl_free(u2_ray ral_r, void* lag_v); /* u2_rl_ok(): ** ** Ensure that all reference counts are valid in `som`. */ void u2_rl_ok(u2_ray ral_r, u2_noun som); // retain /* u2_rl_junior(): ** ** Yes iff `dus` is junior in `ral` - ie, must be copied ** to be referenced on the hat. */ u2_bean u2_rl_junior(u2_ray ral_r, u2_noun dus); // retain /* u2_rl_leap(): ** ** Reverse the beams forward, with memory model `hip`. ** Memory models at present: ** ** c3__sand solid, no boxes or reference counts ** c3__rock liquid, boxes, reference-counted heap ** ** Returns u2_yes on success. */ u2_bean u2_rl_leap(u2_ray ral_r, c3_m hip_m); /* u2_rl_leap_part(): ** ** Reverse and split rail, inserting partition of size `num/dem` ** plus `tip`. ** ** Returns partition rail, `aux_r`. */ u2_ray u2_rl_leap_part(u2_ray ral_r, c3_m hop_m, c3_w num_w, c3_w dem_w, c3_w tip_w); /* u2_rl_lose(): ** ** Lose a reference to `som`. Free it if refcount == 0. */ void u2_rl_lose(u2_ray ral_r, u2_weak som); // transfer /* u2_rl_gc_mark_noun(): ** ** Mark a noun for gc. Return allocated words. */ c3_w u2_rl_gc_mark_noun(u2_ray ral_r, u2_noun som); /* u2_rl_gc_mark_ptr(): ** ** Mark a pointer allocated with ralloc. Return allocated words. */ c3_w u2_rl_gc_mark_ptr(u2_ray ral_r, u2_ray ptr_r); /* u2_rl_gc_mark(): ** ** Mark a rail (mainly memo cache). Return allocated words. */ c3_w u2_rl_gc_mark(u2_ray ral_r); /* u2_rl_gc_sweep(): ** ** Sweep memory, freeing unused blocks. Match live, save leaked. */ c3_w u2_rl_gc_sweep(u2_ray ral_r, c3_w sav_w); /* u2_rl_malloc(): ** ** Allocate `sib_w` *bytes* of raw C storage. */ void* u2_rl_malloc(u2_ray ral_r, c3_w sib_w); /* u2_rl_malt(): ** ** Initialize slab `sal` as an atom, internally measured. */ u2_atom // transfer u2_rl_malt(u2_rail ral_r, u2_ray sal_r); /* u2_rl_mint(): ** ** Initialize slab `sal` as an atom, externally measured. */ u2_atom // transfer u2_rl_mint(u2_rail ral_r, u2_ray sal_r, c3_w len_w); /* u2_rl_moot(): ** ** Initialize slab `sal` as an atom, originally measured. */ u2_atom // transfer u2_rl_moot(u2_rail ral_r, u2_ray sal_r); /* u2_rl_open(): ** ** Yes iff [a] more words remain in the pad. */ u2_bean u2_rl_open(u2_ray ral_r, c3_w a_w); /* u2_rl_ralloc(): ** ** Allocate `siz_w` words of raw ray storage. */ u2_ray u2_rl_ralloc(u2_ray ral_r, c3_w siz_w); /* u2_rl_rfree(): ** ** Free raw ray storage allocated by `u2_rl_ralloc()`. */ void u2_rl_rfree(u2_ray ral_r, u2_ray nov_r); /* u2_rl_senior(): ** ** Yes iff `dus` is senior in `ral` - ie, does not ** require reference counting. */ u2_bean u2_rl_senior(u2_ray ral_r, u2_noun dus); // retain /* u2_rl_slab(): ** ** Create a blank atomic slab of `len` words. */ u2_ray u2_rl_slab(u2_rail ral_r, c3_w len_w); /* u2_rl_slaq(): ** ** Create a blank atomic slab of `len` bloqs of size `met`. */ u2_ray u2_rl_slaq(u2_wire wir_r, c3_g met_g, c3_w len_w); /* u2_rl_refs(): ** ** Return the reference count of (som). For debugging, etc. */ c3_w u2_rl_refs(u2_ray ral_r, u2_noun som); /* u2_rl_copy(): ** ** Copy indirect noun `fiz` into main storage, preserving dags. ** Must be followed by `rl_wash(fiz)` if `fiz` is to be preserved. */ u2_weak // transfer u2_rl_copy(u2_ray ral_r, u2_dog fiz); // retain /* u2_rl_take(): ** ** Produce `a`, as eligible result. Copy juniors; reference peers. */ u2_weak // transfer u2_rl_take(u2_ray ral_r, u2_weak a); // retain # define u2_rl_ice(ral_r, a) \ u2_rl_take(ral_r, a) /* u2_rl_tamp(): ** ** Tamp, eliding the segment from `net` up to `bat`, ** preserving the root `lef`. ** ** Assumes u2_rl_clear() with the same arguments. */ u2_noun u2_rl_tamp(u2_ray ral_r, u2_noun lef, u2_ray net_r, u2_ray bat_r); /* u2_rl_valid(): ** ** Validate rail for memory bugs. */ void u2_rl_valid(u2_ray ral_r); /* u2_rl_water(): ** ** Return east and west watermarks, respectively. */ void u2_rl_water(u2_ray ral_r, c3_w* maz_w, c3_w* buc_w); /** Basic noun fabrication. **/ /* u2_rl_bytes(): ** ** Copy `a` bytes from `b` to an LSB first atom. */ u2_weak // transfer u2_rl_bytes(u2_ray ral_r, c3_w a_w, const c3_y* b_y); /* u2_rl_cell(): ** ** Produce the cell `[a b]`. */ u2_weak // transfer u2_rl_cell(u2_ray ral_r, u2_weak a, // transfer u2_weak b); // transfer /* u2_rl_list(): ** ** Produce a null-terminated list, terminating `...` with `u2_none`. */ u2_weak // transfer u2_rl_list(u2_rail ral_r, ...); // transfer /* u2_rl_lone(): ** ** Create the unit `[0 a]`. */ #if 0 u2_weak // transfer u2_rl_lone(u2_rail ral_r, u2_weak a); // transfer #else # define u2_rl_lone(ral_r, a) \ u2_rc(ral_r, a, u2_nul) #endif /* u2_rl_molt(): ** ** Mutate `som` with a 0-terminated list of axis, noun pairs. ** Axes must be cats (31 bit). */ u2_weak // transfer u2_rl_molt(u2_rail ral_r, u2_weak som, // retain ...); // transfer /* u2_rl_molv(): ** ** As u2_rl_molt(), by argument pointer. */ u2_weak // transfer u2_rl_molv(u2_rail ral_r, u2_weak som, // retain va_list vap); // transfer /* u2_rl_mp(): ** ** Copy the GMP integer [a] into an atom. */ u2_weak // transfer u2_rl_mp(u2_ray ral_r, mpz_t a_mp); // transfer /* u2_rl_qual(): ** ** Produce the triple `[a b c d]`. */ #if 0 u2_weak // transfer u2_rl_qual(u2_rail ral_r, u2_weak a, // transfer u2_weak b, // transfer u2_weak c, // transfer u2_weak d); // transfer #else # define u2_rl_qual(ral_r, a, b, c, d) \ u2_rc(ral_r, a, u2_rt(ral_r, b, c, d)) #endif /* u2_rl_rack(): ** ** Produce an n-tuple, terminating `...` with `u2_none`. */ u2_weak // transfer u2_rl_rack(u2_rail ral_r, ...); // transfer /* u2_rl_string(): ** ** Produce an LSB-first atom from the C string `a`. */ u2_weak // transfer u2_rl_string(u2_ray ral_r, const c3_c* a_c); /* u2_rl_trel(): ** ** Create the triple `[a b c]`. */ #if 0 u2_weak // transfer u2_rl_trel(u2_rail ral_r, u2_weak a, // transfer u2_weak b, // transfer u2_weak c); // transfer #else # define u2_rl_trel(ral_r, a, b, c) \ u2_rc(ral_r, a, u2_rc(ral_r, b, c)) #endif /* u2_rl_unit(): ** ** Create the unit `[0 a]`. */ #if 0 u2_weak // transfer u2_rl_unit(u2_rail ral_r, u2_weak a); // transfer #else # define u2_rl_unit(ral_r, a) \ u2_rc(ral_r, u2_nul, a) #endif /* u2_rl_vint(): ** ** Create `a + 1`. */ u2_weak // transfer u2_rl_vint(u2_rail ral_r, u2_weak a); // transfer /* u2_rl_words(): ** ** Copy [a] words from [b] into an atom. */ u2_weak // transfer u2_rl_words(u2_ray ral_r, c3_w a_w, const c3_w* b_w); /** Caching. **/ /* u2_rl_find(): ** ** Cache search for function (0 means nock) and sample. */ u2_weak // transfer u2_rl_find(u2_ray ral_r, u2_mote fun_m, u2_noun sam); // retain /* u2_rl_save(): ** ** Cache store for function (0 means nock), sample and product. */ u2_weak // transfer u2_rl_save(u2_ray ral_r, u2_mote fun_m, // retain u2_noun sam, // retain u2_noun pro); // transfer /* u2_rl_uniq(): ** ** Use cache to render object unique. */ u2_noun // produce u2_rl_uniq(u2_ray ral_r, u2_noun som); // submit /* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`. ** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`. ** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`. ** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`. ** ** Extend as needed... */ u2_weak // transfer u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain u2_noun); // retain u2_weak // transfer u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun); // retain u2_weak // transfer u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun); // retain u2_weak // transfer u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun); // retain /* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`. ** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`. ** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`. ** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`. ** ** Extended */ u2_weak // transfer u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun); // transfer u2_weak // transfer u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun); // transfer u2_weak // transfer u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun); // transfer u2_weak // transfer u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun, // retain u2_noun); // transfer