shrub/f/wire.c
2014-07-31 13:23:02 -07:00

277 lines
6.0 KiB
C

/* f/wire.c
**
** This file is in the public domain.
*/
#include "all.h"
#include <sys/stat.h>
#include <fcntl.h>
/* u2_wr_init():
**
** Install an empty wire within `hat_r` and `mat_r` in the loom,
** with memory model `hip`.
**
** Returns ray to wire, which always equalls the passed `mat_r`.
*/
u2_ray
u2_wr_init(c3_m hip_m,
u2_ray hat_r,
u2_ray mat_r)
{
u2_ray wir_r;
#if 0
fprintf(stderr, "initial: hat_r %d, mat_r %d\r\n",
hat_r >> LoomPageWords,
mat_r >> LoomPageWords);
#endif
wir_r = u2_rl_init(hip_m, hat_r, mat_r);
u2_rail_hat_r(wir_r) += (c3_wiseof(u2_loom_wire) - c3_wiseof(u2_loom_rail));
#if 1
u2_wire_bas_r(wir_r) = 0;
#endif
u2_wire_kit_r(wir_r) = 0;
u2_cs_init(u2_wire_des_r(wir_r));
/* Trace stack, garbage.
*/
{
u2_wire_tax(wir_r) = u2_nul;
u2_wire_lan(wir_r) = u2_yes;
}
/* Permanent basket = 1/8 of address space.
*/
{
u2_ray bas_r;
bas_r = u2_rl_leap_part(wir_r, c3__sand, 1, 16, 0);
u2_wire_bas_r(wir_r) = bas_r;
#if 0
fprintf(stderr, "bas_r %d, hat %d, mat %d, cap %d, rut %d\n",
bas_r >> LoomPageWords,
u2_rail_hat_r(bas_r) >> LoomPageWords,
u2_rail_mat_r(bas_r) >> LoomPageWords,
u2_rail_cap_r(bas_r) >> LoomPageWords,
u2_rail_rut_r(bas_r) >> LoomPageWords);
fprintf(stderr, "wir_r %d, hat %d, mat %d, cap %d, rut %d\n",
wir_r >> LoomPageWords,
u2_rail_hat_r(wir_r) >> LoomPageWords,
u2_rail_mat_r(wir_r) >> LoomPageWords,
u2_rail_cap_r(wir_r) >> LoomPageWords,
u2_rail_rut_r(wir_r) >> LoomPageWords);
fprintf(stderr, "wir_r %x, hat %x, mat %x, cap %x, rut %x\n",
wir_r ,
u2_rail_hat_r(wir_r) ,
u2_rail_mat_r(wir_r) ,
u2_rail_cap_r(wir_r) ,
u2_rail_rut_r(wir_r) );
#endif
// u2_ba_init(wir_r, 0);
}
#if 1
/* Host control.
*/
{
u2_ho_push();
}
#endif
/* Basic performance tracking.
*/
{
u2_wire_bex_r(wir_r) = u2_rl_ralloc(wir_r, c3_wiseof(u2_loom_benx));
u2_bx_boot(wir_r);
}
/* New performance tracking.
*/
{
u2_wire_rac_r(wir_r) = u2_tx_init(wir_r);
}
/* Global namespace.
*/
{
u2_wire_hev_r(wir_r) = u2_hv_init(wir_r);
}
/* OS kernel.
*/
{
u2_wire_arv_r(wir_r) = u2_rl_ralloc(wir_r, c3_wiseof(u2_reck));
}
return wir_r;
}
/* _wr_open(): open checkpoint file, or return null.
*/
static c3_i
_wr_open(c3_c* cpu_c, c3_c* fil_c, c3_c* suf_c, c3_w len_w)
{
c3_c ful_c[8193];
c3_i fid_i;
snprintf(ful_c, 8193, "%s", cpu_c);
mkdir(ful_c, 0700);
snprintf(ful_c, 8193, "%s/.urb", cpu_c);
mkdir(ful_c, 0700);
snprintf(ful_c, 8193, "%s/.urb/chk", cpu_c);
mkdir(ful_c, 0700);
snprintf(ful_c, 8193, "%s/.urb/chk/%s.%s", cpu_c, fil_c, suf_c);
fid_i = open(ful_c, O_RDWR | O_CREAT, 0666);
if ( -1 == fid_i ) {
perror(ful_c); exit(1);
}
if ( len_w &&
(-1 == ftruncate(fid_i, (len_w * (1 << (LoomPageWords + 2))))) )
{
perror(ful_c); exit(1);
}
return fid_i;
}
/* u2_wr_check_init(): initialize checkpoint segments and/or files.
*/
void
u2_wr_check_init(c3_c* cpu_c)
{
// Segment A, low memory.
//
{
LoomSegmentA.bot_w = 2048;
LoomSegmentA.len_w = 30720;
LoomSegmentA.pgs_w = 0;
LoomSegmentA.ctl_i = _wr_open(cpu_c, "a", "ctl", 0);
LoomSegmentA.dat_i = _wr_open(cpu_c, "a", "dat", LoomSegmentA.len_w);
}
// Segment B, high memory.
//
{
LoomSegmentB.bot_w = LoomHalfPages;
LoomSegmentB.len_w = 30719;
LoomSegmentB.pgs_w = 0;
LoomSegmentB.ctl_i = _wr_open(cpu_c, "b", "ctl", 0);
LoomSegmentB.dat_i = _wr_open(cpu_c, "b", "dat", LoomSegmentB.len_w);
}
// Segment C, the basket control block. Ugly.
{
LoomSegmentC.bot_w = 63487;
LoomSegmentC.len_w = 1;
LoomSegmentC.pgs_w = 0;
LoomSegmentC.ctl_i = _wr_open(cpu_c, "c", "ctl", 0);
LoomSegmentC.dat_i = _wr_open(cpu_c, "c", "dat", LoomSegmentC.len_w);
}
// Segment D, the actual basket.
{
LoomSegmentD.bot_w = 0;
LoomSegmentD.len_w = 2048;
LoomSegmentD.pgs_w = 0;
LoomSegmentD.ctl_i = _wr_open(cpu_c, "d", "ctl", 0);
LoomSegmentD.dat_i = _wr_open(cpu_c, "d", "dat", LoomSegmentD.len_w);
}
}
static void
_wr_check_cheg(u2_cheg* ceg_u, u2_ray top_r)
{
c3_w top_w = (top_r + ((1 << LoomPageWords) - 1)) >> LoomPageWords;
c3_assert(top_w >= ceg_u->bot_w);
c3_assert(top_w < (ceg_u->bot_w + ceg_u->len_w));
if ( ceg_u->pgs_w > (top_w - ceg_u->bot_w) ) {
ceg_u->pgs_w = (top_w - ceg_u->bot_w);
}
}
/* u2_wr_check_save(): checkpoint wire in global structure.
*/
void
u2_wr_check_save()
{
u2_ray mat_r = u2_rail_mat_r(u2_Wire);
u2_ray hat_r = u2_rail_hat_r(u2_Wire);
if ( hat_r >= HalfSize ) {
_wr_check_cheg(&LoomSegmentB, hat_r);
_wr_check_cheg(&LoomSegmentA, mat_r);
} else {
_wr_check_cheg(&LoomSegmentA, hat_r);
_wr_check_cheg(&LoomSegmentB, mat_r);
}
#if 0
_wr_check_cheg(&LoomSegmentC, u2_rail_hat_r(bas_r));
#endif
}
/* u2_wr_ice(): u2_rl_ice(), with u2_bx_copy().
*/
u2_weak
u2_wr_ice(u2_ray wir_r,
u2_noun fiz)
{
u2_ray hat_r = u2_rail_hat_r(wir_r);
u2_noun buz;
c3_w cop_w;
buz = u2_rl_ice(wir_r, fiz);
cop_w = u2_rail_hat_r(wir_r) - hat_r;
if ( cop_w ) {
u2_bx_copy(wir_r, cop_w);
}
return buz;
}
/* u2_wr_mark():
**
** Mark all roots in a wire and return their allocation size.
*/
c3_w
u2_wr_mark(u2_ray wir_r)
{
c3_w siz_w = 0;
c3_assert(c3__rock == u2_rail_hip_m(wir_r));
{
{
u2_ray kit_r = u2_wire_kit_r(wir_r);
while ( kit_r ) {
siz_w += u2_rl_gc_mark_ptr(wir_r, u2_wire_kit_r(wir_r));
siz_w += u2_rl_gc_mark_noun(wir_r, u2_kite_tax(kit_r));
siz_w += u2_rl_gc_mark_noun(wir_r, u2_kite_don(kit_r));
kit_r = u2_kite_par_r(kit_r);
}
}
siz_w += u2_rl_gc_mark_ptr(wir_r, u2_wire_bex_r(wir_r));
siz_w += u2_rl_gc_mark_ptr(wir_r, u2_wire_rac_r(wir_r));
siz_w += u2_rl_gc_mark_ptr(wir_r, u2_wire_hev_r(wir_r));
siz_w += u2_rl_gc_mark_ptr(wir_r, u2_wire_arv_r(wir_r));
u2_hv_mark();
}
siz_w += u2_rl_gc_mark(wir_r);
return siz_w;
}