shrub/f/meme.c
2014-07-05 14:26:35 -07:00

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);