Merge pull request #5881 from urbit/peter/guard-page

u3: add guard page to loom
This commit is contained in:
Joe Bryan 2022-07-08 16:53:01 -04:00 committed by GitHub
commit 0a86639a04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 300 additions and 198 deletions

View File

@ -33,7 +33,7 @@ CFLAGS := $(CFLAGS)
################################################################################
.PHONY: all test clean mrproper
.PHONY: all bench test clean mrproper
################################################################################

1
pkg/urbit/configure vendored
View File

@ -64,6 +64,7 @@ do
shift
done
[ -z "${NO_GUARD_PAGE-}" ] && defmacro U3_GUARD_PAGE 1
[ -n "${MEMORY_DEBUG-}" ] && defmacro U3_MEMORY_DEBUG 1
[ -n "${MEMORY_LOG-}" ] && defmacro U3_MEMORY_LOG 1
[ -n "${CPU_DEBUG-}" ] && defmacro U3_CPU_DEBUG 1

View File

@ -56,6 +56,16 @@
# define c3_max(x, y) ( ((x) > (y)) ? (x) : (y) )
# define c3_min(x, y) ( ((x) < (y)) ? (x) : (y) )
//! Round up/down (respectively).
//!
//! @param[in] x Integer to round.
//! @param[in] n Multiple to round to. Must be power of 2.
//!
//! @return `x` rounded to the nearest multiple of `n`.
# define c3_rop(x, n) (((x) + ((n) - 1)) & (~((n) - 1)))
# define c3_rod(x, n) ((x) & ~((n) - 1))
/* Rotate.
*/
# define c3_rotw(r, x) ( ((x) << (r)) | ((x) >> (32 - (r))) )

View File

@ -25,7 +25,7 @@
/* u3a_bytes: number of bytes in memory.
*/
# define u3a_bytes (c3_w)((1 << (2 + u3a_bits)))
# define u3a_bytes (sizeof(c3_w) * u3a_words)
/* u3a_cells: number of representable cells.
*/
@ -397,36 +397,33 @@
u3a_push(const u3a_pile* pil_u)
{
u3R->cap_p += pil_u->mov_ws;
return u3a_peek(pil_u);
}
/* u3a_pile_sane(): bail on invalid road stack state.
*/
inline void
u3a_pile_sane(const u3a_pile* pil_u)
{
#ifndef U3_GUARD_PAGE
// !off means we're on a north road
//
if ( !pil_u->off_ws ) {
if( !(u3R->cap_p > u3R->hat_p) ) {
u3m_bail(c3__meme);
}
#ifdef U3_MEMORY_DEBUG
# ifdef U3_MEMORY_DEBUG
c3_assert( pil_u->top_p >= u3R->cap_p );
#endif
# endif
}
else {
if( !(u3R->cap_p < u3R->hat_p) ) {
u3m_bail(c3__meme);
}
#ifdef U3_MEMORY_DEBUG
# ifdef U3_MEMORY_DEBUG
c3_assert( pil_u->top_p <= u3R->cap_p );
#endif
# endif
}
#endif /* ifndef U3_GUARD_PAGE */
#ifdef U3_MEMORY_DEBUG
c3_assert( pil_u->rod_u == u3R );
#endif
return u3a_peek(pil_u);
}
/* u3a_pile_done(): assert valid upon completion.
@ -708,14 +705,6 @@
void (*pat_f)(u3_atom, void*),
c3_o (*cel_f)(u3_noun, void*));
/* u3a_walk_fore_unsafe(): u3a_walk_fore(), without overflow checks
*/
void
u3a_walk_fore_unsafe(u3_noun a,
void* ptr_v,
void (*pat_f)(u3_atom, void*),
c3_o (*cel_f)(u3_noun, void*));
/* u3a_string(): `a` as an on-loom c-string.
*/
c3_c*

View File

@ -84,4 +84,9 @@
void
u3e_foul(void);
/* u3e_init(): initialize page tracking.
*/
void
u3e_init(void);
#endif /* ifndef U3_EVENTS_H */

View File

@ -44,6 +44,11 @@
void
u3m_pave(c3_o nuu_o);
/* u3m_signal(): treat a nock-level exception as a signal interrupt.
*/
void
u3m_signal(u3_noun sig_l);
/* u3m_file(): load file, as atom, or bail.
*/
u3_noun

View File

@ -27,7 +27,6 @@
*top = i;
} while ( u3_nul != t );
u3a_pile_sane(&pil_u);
u3j_gate_prep(&sit_u, u3k(b));
while ( c3n == u3a_pile_done(&pil_u) ) {

View File

@ -984,10 +984,6 @@
u3j_site raq_u;
u3j_gate_prep(&raq_u, u3k(raq));
// check for stack overflow
//
u3a_pile_sane(&pil_u);
while ( c3n == u3a_pile_done(&pil_u) ) {
p_wag = _last_k(par_u->har, p_wag);
puq_wag = u3j_gate_slam(&raq_u, u3nc(par_u->res, puq_wag));

View File

@ -13,8 +13,6 @@ void*
u3a_pop(const u3a_pile* pil_u);
void*
u3a_push(const u3a_pile* pil_u);
void
u3a_pile_sane(const u3a_pile* pil_u);
c3_o
u3a_pile_done(const u3a_pile* pil_u);
@ -715,12 +713,13 @@ u3a_cellblock(c3_w num_w)
c3_w i_w;
if ( c3y == u3a_is_north(u3R) ) {
if ( u3R->cap_p <= (u3R->hat_p + (num_w * u3a_minimum)) ) {
if ( u3R->cap_p <= (u3R->hat_p + (num_w * u3a_minimum) + (1 << u3a_page)) ) {
return c3n;
}
else {
u3_post hat_p = u3R->hat_p;
u3_post cel_p = u3R->all.cel_p;
u3_post hat_p = u3R->hat_p;
u3R->hat_p += (num_w * u3a_minimum);
for ( i_w = 0; i_w < num_w; i_w++) {
u3_post all_p = hat_p;
@ -744,17 +743,18 @@ u3a_cellblock(c3_w num_w)
u3to(u3a_fbox, fre_p)->nex_p = cel_p;
cel_p = fre_p;
}
u3R->hat_p = hat_p;
u3R->all.cel_p = cel_p;
}
}
else {
if ( (u3R->cap_p + (num_w * u3a_minimum)) >= u3R->hat_p ) {
if ( (u3R->cap_p + (num_w * u3a_minimum) + (1 << u3a_page)) >= u3R->hat_p ) {
return c3n;
}
else {
u3_post hat_p = u3R->hat_p;
u3_post cel_p = u3R->all.cel_p;
u3_post hat_p = u3R->hat_p;
u3R->hat_p -= (num_w * u3a_minimum);
for ( i_w = 0; i_w < num_w; i_w++ ) {
u3_post all_p = (hat_p -= u3a_minimum);
@ -776,7 +776,7 @@ u3a_cellblock(c3_w num_w)
u3to(u3a_fbox, fre_p)->nex_p = cel_p;
cel_p = fre_p;
}
u3R->hat_p = hat_p;
u3R->all.cel_p = cel_p;
}
}
@ -1174,7 +1174,6 @@ _ca_take_next_north(u3a_pile* pil_u, u3_noun veb)
else {
u3a_cell* old_u = (u3a_cell*)veb_u;
_ca_take* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
fam_u->hed = u3_none;
fam_u->old = veb;
@ -1230,7 +1229,6 @@ _ca_take_next_south(u3a_pile* pil_u, u3_noun veb)
else {
u3a_cell* old_u = (u3a_cell*)veb_u;
_ca_take* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
fam_u->hed = u3_none;
fam_u->old = veb;
@ -2654,50 +2652,6 @@ u3a_walk_fore(u3_noun a,
else {
*top = u3t(a);
top = u3a_push(&pil_u);
u3a_pile_sane(&pil_u);
*top = u3h(a);
}
a = *top;
}
}
/* u3a_walk_fore_unsafe(): u3a_walk_fore(), without overflow checks
*/
void
u3a_walk_fore_unsafe(u3_noun a,
void* ptr_v,
void (*pat_f)(u3_atom, void*),
c3_o (*cel_f)(u3_noun, void*))
{
u3_noun* top;
u3a_pile pil_u;
// initialize stack control; push argument
//
u3a_pile_prep(&pil_u, sizeof(u3_noun));
top = u3a_push(&pil_u);
*top = a;
while ( c3n == u3a_pile_done(&pil_u) ) {
// visit an atom, then pop the stack
//
if ( c3y == u3a_is_atom(a) ) {
pat_f(a, ptr_v);
top = u3a_pop(&pil_u);
}
// vist a cell, if c3n, pop the stack
//
else if ( c3n == cel_f(a, ptr_v) ) {
top = u3a_pop(&pil_u);
}
// otherwise, push the tail and continue into the head
//
else {
*top = u3t(a);
// NB: overflow check elided here
//
top = u3a_push(&pil_u);
*top = u3h(a);
}

View File

@ -29,6 +29,11 @@
//! handled outside this module).
//! - faults are handled by dirtying the page and switching protections to
//! read/write.
//! - a guard page is initially placed in the approximate middle of the free
//! space between the heap and stack at the time of the first page fault.
//! when a fault is detected in the guard page, the guard page is recentered
//! in the free space of the current road. if the guard page cannot be
//! recentered, then memory exhaustion has occurred.
//!
//! ### updates (u3e_save())
//!
@ -71,6 +76,15 @@
#include <fcntl.h>
#include <sys/stat.h>
// Base loom offset of the guard page.
static u3p(c3_w) gar_pag_p;
//! Urbit page size in 4-byte words.
static const size_t pag_wiz_i = 1 << u3a_page;
//! Urbit page size in bytes.
static const size_t pag_siz_i = sizeof(c3_w) * pag_wiz_i;
#ifdef U3_SNAPSHOT_VALIDATION
/* Image check.
*/
@ -172,6 +186,60 @@ _ce_mapfree(void* map_v)
}
#endif
#ifdef U3_GUARD_PAGE
//! Place a guard page at the (approximate) middle of the free space between
//! the heap and stack of the current road, bailing if memory has been
//! exhausted.
static c3_i
_ce_center_guard_page(void)
{
u3p(c3_w) bot_p, top_p;
if ( !u3R ) {
top_p = u3a_outa(u3_Loom + u3a_words);
bot_p = u3a_outa(u3_Loom);
}
else if ( c3y == u3a_is_north(u3R) ) {
top_p = c3_rod(u3R->cap_p, pag_wiz_i);
bot_p = c3_rop(u3R->hat_p, pag_wiz_i);
}
else {
top_p = c3_rod(u3R->hat_p, pag_wiz_i);
bot_p = c3_rop(u3R->cap_p, pag_wiz_i);
}
if ( top_p < bot_p + pag_wiz_i ) {
fprintf(stderr,
"loom: not enough memory to recenter the guard page\r\n");
goto bail;
}
const u3p(c3_w) old_gar_p = gar_pag_p;
const c3_w mid_p = (top_p - bot_p) / 2;
gar_pag_p = bot_p + c3_rod(mid_p, pag_wiz_i);
if ( old_gar_p == gar_pag_p ) {
fprintf(stderr,
"loom: can't move the guard page to the same location"
" (base address %p)\r\n",
u3a_into(gar_pag_p));
goto bail;
}
if ( -1 == mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) {
fprintf(stderr,
"loom: failed to protect the guard page "
"(base address %p)\r\n",
u3a_into(gar_pag_p));
goto fail;
}
return 1;
bail:
u3m_signal(c3__meme);
fail:
return 0;
}
#endif /* ifdef U3_GUARD_PAGE */
/* u3e_fault(): handle a memory event with libsigsegv protocol.
*/
c3_i
@ -193,40 +261,38 @@ u3e_fault(void* adr_v, c3_i ser_i)
c3_assert(0);
return 0;
}
else {
c3_w off_w = u3a_outa(adr_w);
c3_w pag_w = off_w >> u3a_page;
c3_w blk_w = (pag_w >> 5);
c3_w bit_w = (pag_w & 31);
#if 0
if ( pag_w == 131041 ) {
u3l_log("dirty page %d (at %p); unprotecting %p to %p\r\n",
pag_w,
adr_v,
(u3_Loom + (pag_w << u3a_page)),
(u3_Loom + (pag_w << u3a_page) + (1 << u3a_page)));
}
#endif
u3p(c3_w) adr_p = u3a_outa(adr_w);
c3_w pag_w = adr_p >> u3a_page;
c3_w blk_w = (pag_w >> 5);
c3_w bit_w = (pag_w & 31);
if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) {
fprintf(stderr, "strange page: %d, at %p, off %x\r\n",
pag_w, adr_w, off_w);
c3_assert(0);
return 0;
}
u3P.dit_w[blk_w] |= (1 << bit_w);
if ( -1 == mprotect((void *)(u3_Loom + (pag_w << u3a_page)),
(1 << (u3a_page + 2)),
(PROT_READ | PROT_WRITE)) )
{
fprintf(stderr, "loom: fault mprotect: %s\r\n", strerror(errno));
c3_assert(0);
#ifdef U3_GUARD_PAGE
// The fault happened in the guard page.
if ( gar_pag_p <= adr_p && adr_p < gar_pag_p + pag_wiz_i ) {
if ( 0 == _ce_center_guard_page() ) {
return 0;
}
}
else
#endif /* ifdef U3_GUARD_PAGE */
if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) {
fprintf(stderr, "strange page: %d, at %p, off %x\r\n", pag_w, adr_w, adr_p);
c3_assert(0);
return 0;
}
u3P.dit_w[blk_w] |= (1 << bit_w);
if ( -1 == mprotect((void *)(u3_Loom + (pag_w << u3a_page)),
pag_siz_i,
(PROT_READ | PROT_WRITE)) )
{
fprintf(stderr, "loom: fault mprotect: %s\r\n", strerror(errno));
c3_assert(0);
return 0;
}
return 1;
}
@ -262,7 +328,7 @@ _ce_image_open(u3e_image* img_u)
}
else {
c3_d siz_d = buf_u.st_size;
c3_d pgs_d = (siz_d + (c3_d)((1 << (u3a_page + 2)) - 1)) >>
c3_d pgs_d = (siz_d + (c3_d)(pag_siz_i - 1)) >>
(c3_d)(u3a_page + 2);
if ( !siz_d ) {
@ -388,12 +454,12 @@ _ce_patch_verify(u3_ce_patch* pat_u)
fprintf(stderr, "loom: patch seek: %s\r\n", strerror(errno));
return c3n;
}
if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
if ( -1 == read(pat_u->mem_i, mem_w, pag_siz_i) ) {
fprintf(stderr, "loom: patch read: %s\r\n", strerror(errno));
return c3n;
}
{
c3_w nug_w = u3r_mug_words(mem_w, (1 << u3a_page));
c3_w nug_w = u3r_mug_words(mem_w, pag_wiz_i);
if ( mug_w != nug_w ) {
fprintf(stderr, "loom: patch mug mismatch %d/%d; (%x, %x)\r\n",
@ -476,14 +542,8 @@ _ce_patch_write_page(u3_ce_patch* pat_u,
c3_w pgc_w,
c3_w* mem_w)
{
if ( -1 == lseek(pat_u->mem_i, (pgc_w << (u3a_page + 2)), SEEK_SET) ) {
c3_assert(0);
}
if ( (1 << (u3a_page + 2)) !=
write(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) )
{
c3_assert(0);
}
c3_assert(-1 != lseek(pat_u->mem_i, pgc_w * pag_siz_i, SEEK_SET));
c3_assert(pag_siz_i == write(pat_u->mem_i, mem_w, pag_siz_i));
}
/* _ce_patch_count_page(): count a page, producing new counter.
@ -515,8 +575,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u,
c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
pat_u->con_u->mem_u[pgc_w].pag_w = pag_w;
pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w,
(1 << u3a_page));
pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, pag_wiz_i);
#if 0
u3l_log("protect a: page %d\r\n", pag_w);
@ -524,7 +583,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u,
_ce_patch_write_page(pat_u, pgc_w, mem_w);
if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
(1 << (u3a_page + 2)),
pag_siz_i,
PROT_READ) )
{
c3_assert(0);
@ -552,8 +611,8 @@ _ce_patch_compose(void)
u3m_water(&nwr_w, &swu_w);
nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page;
sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page;
}
#ifdef U3_SNAPSHOT_VALIDATION
@ -676,7 +735,7 @@ _ce_patch_apply(u3_ce_patch* pat_u)
//
for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) {
c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w;
c3_w mem_w[1 << u3a_page];
c3_w mem_w[pag_wiz_i];
c3_i fid_i;
c3_w off_w;
@ -689,7 +748,7 @@ _ce_patch_apply(u3_ce_patch* pat_u)
off_w = (u3a_pages - (pag_w + 1));
}
if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
if ( -1 == read(pat_u->mem_i, mem_w, pag_siz_i) ) {
fprintf(stderr, "loom: patch apply read: %s\r\n", strerror(errno));
c3_assert(0);
}
@ -698,13 +757,13 @@ _ce_patch_apply(u3_ce_patch* pat_u)
fprintf(stderr, "loom: patch apply seek: %s\r\n", strerror(errno));
c3_assert(0);
}
if ( -1 == write(fid_i, mem_w, (1 << (u3a_page + 2))) ) {
if ( -1 == write(fid_i, mem_w, pag_siz_i) ) {
fprintf(stderr, "loom: patch apply write: %s\r\n", strerror(errno));
c3_assert(0);
}
}
#if 0
u3l_log("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, (1 << u3a_page)));
u3l_log("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, pag_wiz_i));
#endif
}
}
@ -721,7 +780,7 @@ _ce_image_blit(u3e_image* img_u,
}
c3_w i_w;
c3_w siz_w = 1 << (u3a_page + 2);
c3_w siz_w = pag_siz_i;
lseek(img_u->fid_i, 0, SEEK_SET);
for ( i_w = 0; i_w < img_u->pgs_w; i_w++ ) {
@ -753,18 +812,18 @@ _ce_image_fine(u3e_image* img_u,
c3_ws stp_ws)
{
c3_w i_w;
c3_w buf_w[1 << u3a_page];
c3_w buf_w[pag_wiz_i];
lseek(img_u->fid_i, 0, SEEK_SET);
for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
c3_w mem_w, fil_w;
if ( -1 == read(img_u->fid_i, buf_w, (1 << (u3a_page + 2))) ) {
if ( -1 == read(img_u->fid_i, buf_w, pag_siz_i) ) {
fprintf(stderr, "loom: image fine read: %s\r\n", strerror(errno));
c3_assert(0);
}
mem_w = u3r_mug_words(ptr_w, (1 << u3a_page));
fil_w = u3r_mug_words(buf_w, (1 << u3a_page));
mem_w = u3r_mug_words(ptr_w, pag_wiz_i);
fil_w = u3r_mug_words(buf_w, pag_wiz_i);
if ( mem_w != fil_w ) {
c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page;
@ -804,10 +863,10 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u)
// copy pages into destination image
//
for ( i_w = 0; i_w < fom_u->pgs_w; i_w++ ) {
c3_w mem_w[1 << u3a_page];
c3_w mem_w[pag_wiz_i];
c3_w off_w = i_w;
if ( -1 == read(fom_u->fid_i, mem_w, (1 << (u3a_page + 2))) ) {
if ( -1 == read(fom_u->fid_i, mem_w, pag_siz_i) ) {
fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno));
return c3n;
}
@ -816,7 +875,7 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u)
fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno));
return c3n;
}
if ( -1 == write(tou_u->fid_i, mem_w, (1 << (u3a_page + 2))) ) {
if ( -1 == write(tou_u->fid_i, mem_w, pag_siz_i) ) {
fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno));
return c3n;
}
@ -921,11 +980,11 @@ u3e_save(void)
{
_ce_image_fine(&u3P.nor_u,
u3_Loom,
(1 << u3a_page));
pag_wiz_i);
_ce_image_fine(&u3P.sou_u,
(u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
-(1 << u3a_page));
(u3_Loom + (1 << u3a_bits) - pag_wiz_i),
-(ssize_t)pag_wiz_i);
c3_assert(u3P.nor_u.pgs_w == u3K.nor_w);
c3_assert(u3P.sou_u.pgs_w == u3K.sou_w);
@ -991,11 +1050,11 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
{
_ce_image_blit(&u3P.nor_u,
u3_Loom,
(1 << u3a_page));
pag_wiz_i);
_ce_image_blit(&u3P.sou_u,
(u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
-(1 << u3a_page));
(u3_Loom + (1 << u3a_bits) - pag_wiz_i),
-(ssize_t)pag_wiz_i);
u3l_log("boot: protected loom\r\n");
}
@ -1012,6 +1071,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
}
}
}
return nuu_o;
}
@ -1036,3 +1096,11 @@ u3e_foul(void)
{
memset((void*)u3P.dit_w, 0xff, sizeof(u3P.dit_w));
}
void
u3e_init(void)
{
#ifdef U3_GUARD_PAGE
_ce_center_guard_page();
#endif
}

View File

@ -361,7 +361,9 @@ _cm_signal_deep(c3_w mil_w)
// go utterly haywire.
//
if ( 0 == u3H->rod_u.bug.mer ) {
u3H->rod_u.bug.mer = u3i_string("emergency buffer");
u3H->rod_u.bug.mer = u3i_string(
"emergency buffer with sufficient space to cons the trace and bail"
);
}
if ( mil_w ) {
@ -731,6 +733,11 @@ u3m_bail(u3_noun how)
u3m_signal(how);
}
// release the emergency buffer, ensuring space for cells
//
u3z(u3R->bug.mer);
u3R->bug.mer = 0;
/* Reconstruct a correct error ball.
*/
if ( _(u3ud(how)) ) {
@ -900,6 +907,10 @@ u3m_hate(c3_w pad_w)
u3R->ear_p = u3R->cap_p;
u3m_leap(pad_w);
u3R->bug.mer = u3i_string(
"emergency buffer with sufficient space to cons the trace and bail"
);
}
/* u3m_love(): return product from leap.
@ -1290,20 +1301,32 @@ u3m_soft(c3_w mil_w,
return why;
}
else {
// don't use .^ at the top level!
//
c3_assert(1 != u3h(why));
u3_noun tax, cod, pro;
switch ( u3h(why) ) {
case 2: {
cod = c3__exit;
tax = u3t(why);
} break;
case 3: {
cod = u3h(u3t(why));
tax = u3t(u3t(why));
} break;
// don't use .^ at the top level!
//
default: {
u3m_p("invalid mot", u3h(why));
c3_assert(0);
}
}
// don't call +mook if we have no kernel
//
// This is required to soft the boot sequence.
// XX produce specific error motes instead of %2?
//
if ( 0 == u3A->roc ) {
u3_noun tax = u3t(why);
u3m_p("tone", u3h(why));
while ( u3_nul != tax ) {
u3_noun dat, mot, val;
u3x_cell(tax, &dat, &tax);
@ -1323,31 +1346,16 @@ u3m_soft(c3_w mil_w,
}
}
u3z(why);
return u3nc(c3__fail, u3_nul);
pro = u3nc(u3k(cod), u3_nul);
}
else {
u3_noun tax, cod, pro, mok;
if ( 2 == u3h(why) ) {
cod = c3__exit;
tax = u3k(u3t(why));
}
else {
c3_assert(3 == u3h(why));
cod = u3k(u3h(u3t(why)));
tax = u3k(u3t(u3t(why)));
}
mok = u3dc("mook", 2, tax);
pro = u3nc(cod, u3k(u3t(mok)));
u3_noun mok = u3dc("mook", 2, u3k(tax));
pro = u3nc(u3k(cod), u3k(u3t(mok)));
u3z(mok);
u3z(why);
return pro;
}
u3z(why);
return pro;
}
}
@ -1796,6 +1804,10 @@ u3m_boot(c3_c* dir_c)
*/
u3m_pave(nuu_o);
/* Place the guard page.
*/
u3e_init();
/* Initialize the jet system.
*/
{

View File

@ -1444,9 +1444,9 @@ _n_push(c3_ys mov, c3_ys off, u3_noun a)
{
u3R->cap_p += mov;
// XX stack sanity-check disabled for performance
// XX switch to u3a_push()
//
#if 0
#ifndef U3_GUARD_PAGE
if ( 0 == off ) {
if( !(u3R->cap_p > u3R->hat_p) ) {
u3m_bail(c3__meme);

View File

@ -864,7 +864,7 @@ u3r_p(u3_noun a,
if ( (c3y == u3r_cell(a, &feg, &nux)) &&
(c3y == u3r_sing(feg, b)) )
{
*c = nux;
if ( c ) *c = nux;
return c3y;
}
else return c3n;
@ -1732,10 +1732,6 @@ _cr_mug_next(u3a_pile* pil_u, u3_noun veb)
u3a_cell* cel_u = (u3a_cell*)veb_u;
_cr_mugf* fam_u = u3a_push(pil_u);
// check for overflow
//
u3a_pile_sane(pil_u);
fam_u->mug_l = 0;
fam_u->cel = veb;

View File

@ -158,15 +158,9 @@ u3s_jam_fib(u3i_slab* sab_u, u3_noun a)
fib_u.bit_w = 0;
u3i_slab_init(sab_u, 0, fib_u.a_w);
// as this is a hot path, we unsafely elide overflow checks
//
// a page-fault overflow detection system is urgently needed ...
//
u3a_walk_fore_unsafe(a, &fib_u, _cs_jam_fib_atom_cb,
_cs_jam_fib_cell_cb);
u3a_walk_fore(a, &fib_u, _cs_jam_fib_atom_cb, _cs_jam_fib_cell_cb);
u3h_free(fib_u.har_p);
return fib_u.bit_w;
}
@ -270,18 +264,11 @@ u3s_jam_xeno(u3_noun a, c3_d* len_d, c3_y** byt_y)
{
_jam_xeno_t jam_u = {0};
ur_bsw_init(&jam_u.rit_u, ur_fib11, ur_fib12);
jam_u.har_p = u3h_new();
// as this is a hot path, we unsafely elide overflow checks
//
// a page-fault overflow detection system is urgently needed ...
//
u3a_walk_fore_unsafe(a, &jam_u, _cs_jam_xeno_atom,
_cs_jam_xeno_cell);
u3a_walk_fore(a, &jam_u, _cs_jam_xeno_atom, _cs_jam_xeno_cell);
u3h_free(jam_u.har_p);
return ur_bsw_done(&jam_u.rit_u, len_d, byt_y);
}
@ -360,7 +347,6 @@ _cs_cue_next(u3a_pile* pil_u,
//
else {
_cs_cue* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
// NB: fam_u->wid unused in head-frame
//
@ -472,7 +458,6 @@ _cs_cue_xeno_next(u3a_pile* pil_u,
case ur_jam_cell: {
_cue_frame_t* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
fam_u->ref = u3_none;
fam_u->bit_d = bit_d;
@ -731,7 +716,6 @@ _cs_cue_bytes_next(u3a_pile* pil_u,
case ur_jam_cell: {
_cue_frame_t* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
fam_u->ref = u3_none;
fam_u->bit_d = bit_d;

View File

@ -0,0 +1,83 @@
#include "all.h"
/* _setup(): prepare for tests.
*/
static void
_setup(void)
{
u3m_init();
u3m_pave(c3y);
u3e_init();
}
static u3_noun
_nock_fol(u3_noun fol)
{
return u3n_nock_on(u3_nul, fol);
}
static c3_i
_test_nock_meme(void)
{
// (jam !=(=(~ =|(i=@ |-(?:(=(i ^~((bex 32))) ~ [i $(i +(i))]))))))
//
const c3_y buf_y[] = {
0xe1, 0x16, 0x1b, 0x4, 0x1b, 0xe1, 0x20, 0x58, 0x1c, 0x76, 0x4d, 0x96, 0xd8,
0x31, 0x60, 0x0, 0x0, 0x0, 0x0, 0xd8, 0x8, 0x37, 0xce, 0xd, 0x92, 0x21,
0x83, 0x68, 0x61, 0x87, 0x39, 0xce, 0x4d, 0xe, 0x92, 0x21, 0x87, 0x19, 0x8
};
u3_noun fol = u3s_cue_bytes(sizeof(buf_y), buf_y);
u3_noun gon;
c3_w i_w;
c3_i ret_i = 1;
for ( i_w = 0; i_w < 3; i_w++ ) {
gon = u3m_soft(0, _nock_fol, u3k(fol));
if ( c3n == u3r_p(gon, c3__meme, 0) ) {
u3m_p("nock meme unexpected mote", u3h(gon));
ret_i = 0;
u3z(gon);
break;
}
u3z(gon);
}
u3z(fol);
return ret_i;
}
static c3_i
_test_nock(void)
{
c3_i ret_i = 1;
if ( !_test_nock_meme() ) {
fprintf(stderr, "test nock meme: failed\r\n");
ret_i = 0;
}
return ret_i;
}
/* main(): run all test cases.
*/
int
main(int argc, char* argv[])
{
_setup();
if ( !_test_nock() ) {
fprintf(stderr, "test nock: failed\r\n");
exit(1);
}
// GC
//
u3m_grab(u3_none);
fprintf(stderr, "test nock: ok\r\n");
return 0;
}