mirror of
https://github.com/urbit/shrub.git
synced 2024-12-15 21:03:10 +03:00
262 lines
5.7 KiB
C
262 lines
5.7 KiB
C
/* f/rail.c
|
|
**
|
|
** This file is in the public domain.
|
|
*/
|
|
#include "all.h"
|
|
|
|
#ifdef U2_LEAK_DEBUG
|
|
c3_w COD_w;
|
|
#endif
|
|
|
|
|
|
//////// Basic allocation.
|
|
|
|
|
|
/* _me_box_make(): make a box.
|
|
*/
|
|
c3_w
|
|
_me_box_make()
|
|
|
|
/* _me_free_slot(): select the right free list to search for a block.
|
|
*/
|
|
c3_w
|
|
_me_free_slot(c3_w siz_w)
|
|
{
|
|
if ( siz_w < 8 ) {
|
|
return 0;
|
|
}
|
|
else {
|
|
c3_w i_w = 1;
|
|
|
|
while ( 1 ) {
|
|
if ( i_w == u2_me_free_no ) {
|
|
return (i_w - 1);
|
|
}
|
|
if ( siz_w < 16 ) {
|
|
return i_w;
|
|
}
|
|
siz_w = (siz_w + 1) >> 1;
|
|
i_w += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* u2_me_walloc(): allocate storage measured in words.
|
|
*/
|
|
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);
|
|
|
|
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;
|
|
|
|
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();
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* u2_me_malloc(): allocate storage measured in bytes.
|
|
*/
|
|
void*
|
|
u2_me_malloc(c3_w len_w);
|
|
|
|
/* u2_me_free(): free storage.
|
|
*/
|
|
void
|
|
u2_me_free(void* lag_v);
|
|
{
|
|
c3_w* lag_w = lag_v;
|
|
return;
|
|
}
|
|
|
|
//////// Atoms from proto-atoms.
|
|
|
|
/* Basic allocation.
|
|
*/
|
|
/* u2_me_walloc(): allocate storage measured in words.
|
|
*/
|
|
void*
|
|
u2_me_walloc(c3_w len_w);
|
|
|
|
/* u2_me_malloc(): allocate storage measured in bytes.
|
|
*/
|
|
void*
|
|
u2_me_malloc(c3_w len_w);
|
|
|
|
/* u2_me_free(): free storage.
|
|
*/
|
|
void
|
|
u2_me_free(void* lag_v);
|
|
|
|
|
|
|
|
/* u2_me_slab(): create a length-bounded proto-atom.
|
|
*/
|
|
c3_w*
|
|
u2_me_slab(c3_w len_w)
|
|
{
|
|
u2_ray nov_r = u2_rl_ralloc(ral_r, (len_w + c3_wiseof(u2_loom_atom)));
|
|
u2_atom nov = u2_pug_of(nov_r, 0);
|
|
|
|
*u2_at_dog_mug(nov) = 0;
|
|
*u2_at_pug_len(nov) = len_w;
|
|
|
|
/* Clear teh slab.
|
|
*/
|
|
{
|
|
c3_w i_w;
|
|
|
|
for ( i_w=0; i_w < len_w; i_w++ ) {
|
|
*u2_at_pug_buf(nov, i_w) = 0;
|
|
}
|
|
}
|
|
return (nov_r + c3_wiseof(u2_loom_atom));
|
|
|
|
/* u2_me_slaq(): u2_me_slaq() with a defined blocksize.
|
|
*/
|
|
c3_w*
|
|
u2_me_slaq(c3_g met_g, c3_w len_w);
|
|
|
|
/* u2_me_malt(): measure and finish a proto-atom.
|
|
*/
|
|
u2_noun
|
|
u2_me_malt(c3_w* sal_w);
|
|
|
|
/* u2_me_moot(): finish a pre-measured proto-atom; dangerous.
|
|
*/
|
|
u2_noun
|
|
u2_me_moot(c3_w* sal_w);
|
|
|
|
/* u2_me_mint(): finish a measured proto-atom.
|
|
*/
|
|
u2_noun
|
|
u2_me_mint(c3_w* sal_w, c3_w len_w);
|