mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-01 03:23:09 +03:00
Merge branch 'master' of https://github.com/urbit/urbit
This commit is contained in:
commit
f3c6e4c34e
499
f/meme.c
499
f/meme.c
@ -13,56 +13,172 @@
|
||||
|
||||
/* _me_boot_north(): install a north road.
|
||||
*/
|
||||
static void
|
||||
_me_boot_north(void* mem_v, c3_w len_w)
|
||||
static u2_road*
|
||||
_me_boot_north(c3_w* mem_w, c3_w len_w)
|
||||
{
|
||||
for
|
||||
c3_w* rut_w = mem_w;
|
||||
c3_w* hat_w = rut_w;
|
||||
c3_w* mat_w = ((mem_w + len_w) - c3_wiseof(u2_road));
|
||||
c3_w* cap_w = mat_w;
|
||||
u2_road* rod_u = (void*) mat_w;
|
||||
|
||||
memset(rod_u, 0, sizeof(u2_road));
|
||||
|
||||
rod_u->rut_w = rut_w;
|
||||
rod_u->hat_w = hat_w;
|
||||
|
||||
rod_u->mat_w = mat_w;
|
||||
rod_u->cap_w = cap_w;
|
||||
|
||||
return rod_u;
|
||||
}
|
||||
|
||||
/* _me_boot_south(): install a south road.
|
||||
*/
|
||||
static u2_road*
|
||||
_me_boot_south(c3_w* mem_w, c3_w len_w)
|
||||
{
|
||||
c3_w* rut_w = mem_w;
|
||||
c3_w* hat_w = rut_w;
|
||||
c3_w* mat_w = ((mem_w + len_w) - c3_wiseof(u2_road));
|
||||
c3_w* cap_w = mat_w;
|
||||
u2_road* rod_u = (void*) mat_w;
|
||||
|
||||
memset(rod_u, 0, sizeof(u2_road));
|
||||
|
||||
rod_u->rut_w = rut_w;
|
||||
rod_u->hat_w = hat_w;
|
||||
|
||||
rod_u->mat_w = mat_w;
|
||||
rod_u->cap_w = cap_w;
|
||||
|
||||
return rod_u;
|
||||
}
|
||||
|
||||
/* u2_me_boot(): make u2R and u2H from nothing.
|
||||
*/
|
||||
void
|
||||
u2_me_boot(void* mem_v, c3_w len_w)
|
||||
{
|
||||
c3_w* mem_w = mem_v;
|
||||
|
||||
u2H = (u2_road*) mem_v;
|
||||
memset(u2H, 0, sizeof(u2_road));
|
||||
|
||||
u2H->rut_w = (mem_w + c3_sizeof(u2_road));
|
||||
u2H->hat_w = u2H->rut_w;
|
||||
|
||||
u2H->mat_w = (mem_w + len_w);
|
||||
u2H->cap_w = u2H->mat_w;
|
||||
|
||||
u2R = u2H;
|
||||
u2H = u2R = _me_boot_north(mem_v, len_w);
|
||||
}
|
||||
|
||||
/* u2_me_leap(): advance to inner road.
|
||||
/* _me_road_all_hat(): in u2R, allocate directly on the hat.
|
||||
*/
|
||||
static c3_w*
|
||||
_me_road_all_hat(c3_w len_w)
|
||||
{
|
||||
if ( len_w > u2_me_open ) {
|
||||
return u2_me_bail(c3__meme);
|
||||
}
|
||||
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
c3_w* all_w;
|
||||
|
||||
all_w = u2R->hat;
|
||||
u2R->hat += len_w;
|
||||
return all_w;
|
||||
}
|
||||
else {
|
||||
u2R->hat -= len_w;
|
||||
return u2R->hat;
|
||||
}
|
||||
}
|
||||
|
||||
/* _me_road_all_cap(): in u2R, allocate directly on the cap.
|
||||
*/
|
||||
static c3_w*
|
||||
_me_road_all_hat(c3_w len_w)
|
||||
{
|
||||
if ( len_w > u2_me_open ) {
|
||||
return u2_me_bail(c3__meme);
|
||||
}
|
||||
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
u2R->cap -= len_w;
|
||||
return u2R->cap;
|
||||
}
|
||||
else {
|
||||
c3_w* all_w;
|
||||
|
||||
all_w = u2R->cap;
|
||||
u2R->cap += len_w;
|
||||
return all_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* u2_me_leap(): in u2R, create a new road within the existing one.
|
||||
*/
|
||||
void
|
||||
u2_me_leap(void)
|
||||
u2_me_leap()
|
||||
{
|
||||
u2_road* rod_u;
|
||||
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
rod_u = _me_boot_south(u2R->hat_w, (u2R->cap_w - u2R->hat_w));
|
||||
}
|
||||
else {
|
||||
rod_u = _me_boot_south(u2R->cap_w, (u2R->hat_w - u2R->cap_w));
|
||||
}
|
||||
|
||||
c3_assert(0 == u2R->kid_u);
|
||||
rod_u->par_u = u2R;
|
||||
u2R->kid_u = rod_u;
|
||||
u2R = rod_u;
|
||||
}
|
||||
|
||||
/* u2_me_fall(): in u2R, return an inner road to its parent.
|
||||
*/
|
||||
void
|
||||
u2_me_fall()
|
||||
{
|
||||
c3_assert(0 != u2R->par_u);
|
||||
|
||||
u2R->par_u->cap_w = u2R->hat_u;
|
||||
u2R = u2R->par_u;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* _me_free_slot(): select the right free list to search for a block.
|
||||
/* u2_me_golf(): record cap length for u2_flog().
|
||||
*/
|
||||
c3_w
|
||||
_me_free_slot(c3_w siz_w)
|
||||
u2_me_golf(void)
|
||||
{
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
return u2R->mat - u2R->cap;
|
||||
}
|
||||
else {
|
||||
return u2R->cap - u2R->mat;
|
||||
}
|
||||
}
|
||||
|
||||
/* u2_me_flog(): reset cap.
|
||||
*/
|
||||
void
|
||||
u2_me_flog(c3_w gof_w)
|
||||
{
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
u2R->cap = u2R->mat - gof_w;
|
||||
} else {
|
||||
u2R->cap = u2R->mat + gof_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* u2_me_water(): produce watermarks.
|
||||
*/
|
||||
void
|
||||
u2_me_water(c3_w* low_w, c3_w* hig_w);
|
||||
{
|
||||
c3_assert(u2R == u2H);
|
||||
|
||||
*low_w = (u2H->hat_w - u2H->rut_w);
|
||||
*hig_w = (u2H->mat_w - u2H->cap_w) + c3_wiseof(u2_road);
|
||||
}
|
||||
|
||||
/* _me_box_slot(): select the right free list to search for a block.
|
||||
*/
|
||||
c3_w
|
||||
_me_box_slot(c3_w siz_w)
|
||||
{
|
||||
if ( siz_w < 8 ) {
|
||||
return 0;
|
||||
@ -83,160 +199,241 @@ _me_free_slot(c3_w siz_w)
|
||||
}
|
||||
}
|
||||
|
||||
/* u2_me_walloc(): allocate storage measured in words.
|
||||
/* _me_box_make(): construct a box.
|
||||
*/
|
||||
u2_me_box*
|
||||
_me_box_make(c3_v* box_v, c3_w siz_w, c3_w use_w)
|
||||
{
|
||||
u2_me_box* box_u = box_v;
|
||||
c3_w* box_w = box_v;
|
||||
|
||||
box_w[0] = siz_w;
|
||||
box_w[siz_w - 1] = siz_w;
|
||||
|
||||
#ifdef U2_MEMORY_DEBUG
|
||||
box_u->cod_w = COD_w;
|
||||
#endif
|
||||
box_u->use_w = use_w;
|
||||
|
||||
return box_u;
|
||||
}
|
||||
|
||||
/* _me_box_attach(): attach a box to the free list.
|
||||
*/
|
||||
void
|
||||
_me_box_attach(u2_me_box* box_u)
|
||||
{
|
||||
c3_assert(box_u->siz_w >= (1 + c3_wiseof(u2_me_free)));
|
||||
{
|
||||
c3_w sel_w = _me_box_slot(box_u->siz_w);
|
||||
u2_me_free* fre_u = (void *)box_u;
|
||||
u2_me_free** pfr_u = &u2R->all.fre_u[sel_w];
|
||||
|
||||
fre_u->pre_u = 0;
|
||||
fre_u->nex_u = (*pfr_u);
|
||||
(*pfr_u) = fre_u;
|
||||
}
|
||||
}
|
||||
|
||||
/* _me_box_detach(): detach a box from the free list.
|
||||
*/
|
||||
void
|
||||
_me_box_detach(u2_me_box* box_u)
|
||||
{
|
||||
u2_me_free* fre_u = (void*) box_u;
|
||||
|
||||
if ( fre_u->pre_u ) {
|
||||
fre_u->pre_u->nex_u = fre_u->nex_u;
|
||||
}
|
||||
else {
|
||||
c3_w sel_w = _me_box_slot(box_u->siz_w);
|
||||
|
||||
u2R->all.fre_u[sel_w] = fre_u->nex_u;
|
||||
}
|
||||
}
|
||||
|
||||
/* u2_me_walloc(): allocate storage words on hat.
|
||||
*/
|
||||
void*
|
||||
u2_me_walloc(c3_w len_w)
|
||||
{
|
||||
c3_w siz_w = c3_max(u2_me_minimum, u2_me_boxed(len_w));
|
||||
c3_w sel_w = _me_free_slot(siz_w);
|
||||
c3_w sel_w = _me_box_slot(siz_w);
|
||||
|
||||
// XX: this logic is totally bizarre, but preserve it.
|
||||
//
|
||||
if ( (sel_w != 0) && (sel_w != u2_me_free_no - 1) ) {
|
||||
sel_w += 1;
|
||||
}
|
||||
|
||||
while ( 1 ) {
|
||||
u2_me_free* pfr_u = u2R->all.fre_u[sel_w];
|
||||
c3_w* box_w;
|
||||
u2_me_free** pfr_u = &u2R->all.fre_u[sel_w];
|
||||
|
||||
if ( 0 == pfr_u ) {
|
||||
if ( sel_w < (u2_me_free_no - 1) ) {
|
||||
sel_w += 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* Nothing in top free list. Chip away at the hat.
|
||||
*/
|
||||
if ( u2_no == u2_me_open(siz_w) ) {
|
||||
u2_loop_signal_memory();
|
||||
while ( 1 ) {
|
||||
if ( 0 == *pfr_u ) {
|
||||
if ( sel_w < (u2_me_free_no - 1) ) {
|
||||
sel_w += 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
box_w = u2R->lay.hat_w;
|
||||
u2R->lay.hat_w += siz_w;
|
||||
|
||||
_me_box_make(
|
||||
|
||||
box_r = u2_rail_hat_r(ral_r);
|
||||
u2_rail_hat_r(ral_r) += siz_w;
|
||||
|
||||
_rl_bloq_make(ral_r, box_r, siz_w, 1);
|
||||
_rl_live_grab(ral_r, siz_w);
|
||||
|
||||
_rl_bloq_cheq(box_r);
|
||||
return (box_r + c3_wiseof(u2_loom_rail_box));
|
||||
/* Nothing in top free list. Chip away at the hat.
|
||||
*/
|
||||
return u2_me_boxto(_me_box_make(_me_road_all_hat(siz_w), siz_w, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pfr_r = u2_aftr(sop_r, u2_loom_soup, fre_r) + sel_w;
|
||||
|
||||
while ( 1 ) {
|
||||
u2_ray fre_r = *u2_at_ray(pfr_r);
|
||||
u2_ray box_r;
|
||||
|
||||
if ( 0 == fre_r ) {
|
||||
if ( sel_w < (u2_me_free_no - 1) ) {
|
||||
sel_w += 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* Nothing in top free list. Chip away at the hat.
|
||||
*/
|
||||
if ( u2_no == u2_rl_open(ral_r, siz_w) ) {
|
||||
#if 1
|
||||
u2_loop_signal_memory();
|
||||
#else
|
||||
/* Yo, our rail is totally full.
|
||||
*/
|
||||
printf("lose: siz_w: %d sel_w: %d\n", siz_w, sel_w);
|
||||
u2_rl_dump(ral_r);
|
||||
|
||||
u2_ho_warn_here();
|
||||
// XX: integrate with integral wire.
|
||||
//
|
||||
// A bunch of testing is needed to make this actually work.
|
||||
// return 0;
|
||||
c3_assert(0);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
box_r = u2_rail_hat_r(ral_r);
|
||||
u2_rail_hat_r(ral_r) += siz_w;
|
||||
|
||||
_rl_bloq_make(ral_r, box_r, siz_w, 1);
|
||||
_rl_live_grab(ral_r, siz_w);
|
||||
|
||||
_rl_bloq_cheq(box_r);
|
||||
return (box_r + c3_wiseof(u2_loom_rail_box));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( siz_w > u2_rail_hut_siz(fre_r) ) {
|
||||
/* This free block is too small. Continue searching.
|
||||
*/
|
||||
pfr_r = u2_aftr(fre_r, u2_loom_rail_hut, nex_r);
|
||||
}
|
||||
else {
|
||||
/* We have found a free block of adequate size. Remove it
|
||||
** from the free list.
|
||||
*/
|
||||
box_r = fre_r;
|
||||
else {
|
||||
if ( siz_w > (*pfr_u)->box_u->siz_w ) {
|
||||
/* This free block is too small. Continue searching.
|
||||
*/
|
||||
pfr_u = &((*pfr_u)->nex_u);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
u2_me_box* box_u = &((*pfr_u)->box_u);
|
||||
|
||||
/* We have found a free block of adequate size. Remove it
|
||||
** from the free list.
|
||||
*/
|
||||
{
|
||||
{
|
||||
u2_ray pre_r = u2_rail_hut_pre(box_r);
|
||||
u2_ray nex_r = u2_rail_hut_nex(box_r);
|
||||
|
||||
c3_assert((0 == pre_r) ||
|
||||
(u2_at_ray(pfr_r) == &u2_rail_hut_nex(pre_r)));
|
||||
*u2_at_ray(pfr_r) = nex_r;
|
||||
|
||||
if ( 0 != nex_r ) {
|
||||
u2_rail_hut_pre(nex_r) = pre_r;
|
||||
}
|
||||
c3_assert((0 == (*pfr_u)->pre_u) ||
|
||||
(*pfr_u)->pre_u->nex_u == (*pfr_u));
|
||||
c3_assert((0 == (*pfr_u)->nex_u) ||
|
||||
(*pfr_u)->nex_u->pre_u == (*pfr_u));
|
||||
}
|
||||
|
||||
if ( (siz_w + 6) < u2_rail_hut_siz(box_r) ) {
|
||||
/* Split the block.
|
||||
*/
|
||||
u2_ray end_r = (box_r + siz_w);
|
||||
|
||||
_rl_bloq_make(ral_r, end_r, u2_rail_hut_siz(fre_r) - siz_w, 0);
|
||||
_rl_bloq_attach(ral_r, end_r);
|
||||
_rl_bloq_make(ral_r, box_r, siz_w, 1);
|
||||
|
||||
_rl_live_grab(ral_r, siz_w);
|
||||
if ( 0 != (*pfr_u)->nex_u ) {
|
||||
(*pfr_u)->nex_u->pre_u = (*pfr_u)->pre_u;
|
||||
}
|
||||
else {
|
||||
c3_assert(u2_rail_box_use(box_r) == 0);
|
||||
u2_rail_box_use(box_r) = 1;
|
||||
# ifdef U2_LEAK_DEBUG
|
||||
*u2_at_ray(box_r + 2) = COD_w;
|
||||
# endif
|
||||
|
||||
_rl_live_grab(ral_r, u2_rail_hut_siz(box_r));
|
||||
}
|
||||
_rl_bloq_cheq(box_r);
|
||||
return (box_r + c3_wiseof(u2_loom_rail_box));
|
||||
*pfr_u = (*pfr_u)->nex_u;
|
||||
}
|
||||
|
||||
/* If we can chop off another block, do it.
|
||||
*/
|
||||
if ( (siz_w + c3_wiseof(u2_me_free) + 1) <= box_u->siz_w ) {
|
||||
/* Split the block.
|
||||
*/
|
||||
c3_w* box_w = ((c3_w *)(void *)box_uy);
|
||||
c3_w* end_w = box_w + siz_w;
|
||||
c3_w lef_w = (box_u->siz_w - siz_w);
|
||||
|
||||
_me_box_attach(_me_box_make(end_w, lef_w, 0));
|
||||
return u2_me_boxto(_me_box_make(box_w, siz_w, 1));
|
||||
}
|
||||
else {
|
||||
c3_assert(0 == box_u->use_w);
|
||||
#ifdef U2_MEMORY_DEBUG
|
||||
box_u->cod_w = COD_w;
|
||||
#endif
|
||||
return u2_me_boxto(box_u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* u2_me_malloc(): allocate storage measured in bytes.
|
||||
*/
|
||||
void*
|
||||
u2_me_malloc(c3_w len_w);
|
||||
u2_me_malloc(c3_w len_w)
|
||||
{
|
||||
return u2_me_walloc((len_w + 3) >> 2);
|
||||
}
|
||||
|
||||
/* u2_me_free(): free storage.
|
||||
*/
|
||||
void
|
||||
u2_me_free(void* lag_v);
|
||||
u2_me_free(void* tox_v);
|
||||
{
|
||||
c3_w* lag_w = lag_v;
|
||||
return;
|
||||
u2_me_box* box_u = u2_me_botox(tox_v);
|
||||
c3_w* box_w = (c3_w *)(void *)box_u;
|
||||
|
||||
c3_assert(box_u->use_w != 0);
|
||||
box_u->use_w -= 1;
|
||||
if ( 0 != box_u->use_w ) return;
|
||||
|
||||
/* Clear the contents of the block, for debugging.
|
||||
*/
|
||||
{
|
||||
c3_w i_w;
|
||||
|
||||
for ( i_w = c3_wiseof(u2_me_box); (i_w + 1) < box_u->siz_w; i_w++ ) {
|
||||
((c3_w*)tox_v)[i_w] = 0xdeadbeef;
|
||||
}
|
||||
}
|
||||
|
||||
if ( u2_yes == u2_me_is_north ) {
|
||||
c3_w* bot_w = u2R->rut_w;
|
||||
c3_w* top_w = u2R->hat_w;
|
||||
|
||||
/* Try to coalesce with the previous block.
|
||||
*/
|
||||
if ( box_w != u2R->rut_w ) {
|
||||
c3_w laz_w = *(box_w - 1);
|
||||
u2_me_box* pox_u = (u2_me_box*)(void *)(box_w - laz_w);
|
||||
|
||||
if ( 0 == pox_u->use_w ) {
|
||||
_me_box_detach(pox_u);
|
||||
_me_box_make(pox_u, (laz_w + box_u->siz_w), 0);
|
||||
|
||||
box_u = pox_u;
|
||||
box_w = (c3_w*)(void *)box_u;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to coalesce with the next block, or the wilderness.
|
||||
*/
|
||||
if ( (box_w + siz_w) == u2R->hat_w ) {
|
||||
u2R->hat_w = box_w;
|
||||
}
|
||||
else {
|
||||
u2_me_box* nox_u = (u2_me_box*)(void *)(box_w + box_u->siz_w);
|
||||
|
||||
if ( 0 == nox_u->use_w ) {
|
||||
_me_nox_detach(nox_u);
|
||||
_me_box_make(box_u, (nox_u->siz_w + box_u->siz_w));
|
||||
}
|
||||
_me_box_attach(box_u);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (
|
||||
}
|
||||
|
||||
if ( ((c3_w*) tox_v) == u2
|
||||
if ( box_r != beg_r ) {
|
||||
c3_w las_w = *u2_at_ray(box_r - 1);
|
||||
u2_ray tod_r = (box_r - las_w);
|
||||
|
||||
if ( 0 == u2_rail_hut_use(tod_r) ) {
|
||||
_rl_bloq_detach(ral_r, tod_r);
|
||||
_rl_bloq_make(ral_r, tod_r, (las_w + u2_rail_hut_siz(box_r)), 0);
|
||||
box_r = tod_r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to coalesce with the next block, or with the wilderness.
|
||||
*/
|
||||
{
|
||||
c3_w siz_w = u2_rail_hut_siz(box_r);
|
||||
|
||||
if ( (box_r + siz_w == hat_r) ) {
|
||||
u2_rail_hat_r(ral_r) = box_r;
|
||||
}
|
||||
else {
|
||||
u2_ray hob_r = (box_r + siz_w);
|
||||
|
||||
if ( 0 == u2_rail_hut_use(hob_r) ) {
|
||||
_rl_bloq_detach(ral_r, hob_r);
|
||||
_rl_bloq_make(ral_r, box_r, (siz_w + u2_rail_hut_siz(hob_r)), 0);
|
||||
}
|
||||
|
||||
/* Add to the appropriate free list.
|
||||
*/
|
||||
_rl_bloq_attach(ral_r, box_r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////// Atoms from proto-atoms.
|
||||
|
@ -24,6 +24,7 @@
|
||||
** ---
|
||||
** siz_w
|
||||
** use_w
|
||||
** if(debug) cod_w
|
||||
** user data
|
||||
** siz_w
|
||||
** ---
|
||||
@ -33,16 +34,25 @@
|
||||
typedef struct _u2_me_box {
|
||||
c3_w siz_w; // size of this box
|
||||
c3_w use_w; // reference count; free if 0
|
||||
# ifdef U2_LEAK_DEBUG
|
||||
# ifdef U2_MEMORY_DEBUG
|
||||
c3_w cod_w; // tracing code
|
||||
# endif
|
||||
} u2_me_box;
|
||||
|
||||
# define u2_me_boxed(len_w) (len_w + c3_wiseof(u2_me_box) + 1)
|
||||
# define u2_me_boxof(box_v) ( (void *) \
|
||||
# define u2_me_boxto(box_v) ( (void *) \
|
||||
( ((c3_w *)(void*)(box_v)) + \
|
||||
c3_wiseof(u2_me_box) ) )
|
||||
# define u2_me_botox(tox_v) ( (struct _u2_me_box *) \
|
||||
(void *) \
|
||||
( ((c3_w *)(void*)(tox_v)) - \
|
||||
c3_wiseof(u2_me_box) ) )
|
||||
|
||||
((box_w) + c3_wiseof(u2_me_box))
|
||||
|
||||
/* u2_me_free: free node in heap. Sets minimum node size.
|
||||
**
|
||||
** XXO: pre_u and nex_u should live in box.
|
||||
*/
|
||||
typedef struct _u2_me_free {
|
||||
u2_me_box box_u;
|
||||
@ -75,9 +85,10 @@
|
||||
** (stack); ~ is deep storage (immutable); $ is the allocation block;
|
||||
** # is free memory.
|
||||
**
|
||||
** Pointer restrictions: pointers stored in + can point anywhere;
|
||||
** pointers in - can only point to - or ~; pointers in ~ can only
|
||||
** point to ~.
|
||||
** Pointer restrictions: pointers stored in + can point anywhere,
|
||||
** except to more central pointers in +. (Ie, all pointers from
|
||||
** stack to stack must point downward on the stack.) Pointers in
|
||||
** - can only point to - or ~; pointers in ~ only point to ~.
|
||||
**
|
||||
** To "leap" is to create a new inner road in the ### free space.
|
||||
** but in the reverse direction, so that when the inner road
|
||||
@ -89,14 +100,28 @@
|
||||
*/
|
||||
typedef struct _u2_me_road {
|
||||
struct _u2_me_road* par_u; // parent road
|
||||
struct _u2_me_road* kid_u; // child road list
|
||||
struct _u2_me_road* nex_u; // sibling road
|
||||
|
||||
struct { // layout information
|
||||
c3_w* cap_w; // top of transient region
|
||||
c3_w* hat_w; // top of durable region
|
||||
c3_w* mat_w; // bottom of transient region
|
||||
c3_w* rut_w; // bottom of durable region
|
||||
|
||||
c3_w* gar_w; // bottom of guard region (future)
|
||||
c3_w* rag_w; // top of guard region (future)
|
||||
|
||||
c3_w pad_w[4]; // future interesting info
|
||||
} lay;
|
||||
|
||||
struct { // escape buffer
|
||||
union {
|
||||
jmp_buf buf;
|
||||
c3_w buf_w[256]; // futureproofing
|
||||
};
|
||||
} esc;
|
||||
|
||||
struct { // allocation pools
|
||||
u2_me_free* fre_u[u2_me_free_no]; // heap by node size log
|
||||
# ifdef U2_MEMORY_DEBUG
|
||||
@ -112,6 +137,10 @@
|
||||
u2_noun fly; // $+(* (unit))
|
||||
} ski;
|
||||
|
||||
struct { // need state
|
||||
u2_noun nyd; // (list path)
|
||||
} nyd;
|
||||
|
||||
struct { // trace stack
|
||||
u2_noun tax; // (list ,*)
|
||||
} bug;
|
||||
@ -147,27 +176,51 @@
|
||||
/** Macros.
|
||||
**/
|
||||
# define u2_me_is_north ((u2R->cap > u2R->hat) ? u2_yes : u2_no)
|
||||
# define u2_me_is_south (!u2_me_is_north)
|
||||
# define u2_me_is_south ((u2_yes == u2_me_is_north) ? u2_no : u2_yes)
|
||||
|
||||
# define u2_me_open ( (u2_yes == u2_me_is_north) \
|
||||
? (c3_w)(u2R->cap - u2R->hat) \
|
||||
: (c3_w)(u2R->hat - u2R->cap) )
|
||||
|
||||
# define u2_me_into(x) (((c3_w*)(void*)u2H) + (x))
|
||||
# define u2_me_outa(p) (((c3_w*)(void*)(p)) - (c3w*)(void*)u2H)
|
||||
|
||||
|
||||
/** Functions.
|
||||
**/
|
||||
**/
|
||||
/* u2_me_boot(): make u2R and u2H from `len` words at `mem`.
|
||||
*/
|
||||
void
|
||||
u2_me_boot(void* mem_v, c3_w len_w);
|
||||
|
||||
/* u2_me_grab(): garbage-collect memory. Assumes u2R == u2H.
|
||||
/* u2_me_trap(): setjmp within road.
|
||||
*/
|
||||
#if 0
|
||||
u2_noun
|
||||
u2_me_trap(void);
|
||||
#else
|
||||
# define u2_me_trap() (u2_noun)(setjmp(u2R->esc.buf))
|
||||
#endif
|
||||
|
||||
/* u2_me_bail(): bail out. Does not return.
|
||||
**
|
||||
** Bail motes:
|
||||
**
|
||||
** %exit :: semantic failure
|
||||
** %intr :: interrupt
|
||||
** %fail :: execution failure
|
||||
** %need :: network block
|
||||
** %meme :: out of memory
|
||||
*/
|
||||
c3_i
|
||||
u2_me_bail(c3_m how_m);
|
||||
|
||||
/* u2_me_grab(): garbage-collect memory. Asserts u2R == u2H.
|
||||
*/
|
||||
void
|
||||
u2_me_grab(void);
|
||||
|
||||
/* u2_me_check(): checkpoint memory to file.
|
||||
**
|
||||
** Assumes u2R == u2H.
|
||||
/* u2_me_check(): checkpoint memory to file. Asserts u2R == u2H.
|
||||
*/
|
||||
void
|
||||
u2_me_check(void);
|
||||
@ -182,19 +235,32 @@
|
||||
void
|
||||
u2_me_leap(void);
|
||||
|
||||
/* u2_me_flog(): release inner-allocated storage.
|
||||
/* u2_me_golf(): record cap length for u2_flog().
|
||||
*/
|
||||
c3_w
|
||||
u2_me_golf(void);
|
||||
|
||||
/* u2_me_flog(): pop the cap.
|
||||
**
|
||||
** The proper sequence for inner allocation is:
|
||||
** A common sequence for inner allocation is:
|
||||
**
|
||||
** c3_w gof_w = u2_me_golf();
|
||||
** u2_me_leap();
|
||||
** // allocate some inner stuff...
|
||||
** u2_me_fall();
|
||||
** // inner stuff is still valid, but on cap
|
||||
** u2_me_
|
||||
**
|
||||
** u2_me_flog(0) simply clears the cap.
|
||||
*/
|
||||
void
|
||||
u2_me_flog(void);
|
||||
|
||||
|
||||
/* u2_me_water(): produce high and low watermarks. Asserts u2R == u2H.
|
||||
*/
|
||||
void
|
||||
u2_me_water(c3_w *low_w, c3_w *hig_w);
|
||||
|
||||
/** Allocation.
|
||||
**/
|
||||
/* Basic allocation.
|
||||
|
Loading…
Reference in New Issue
Block a user