u3: reimplements guard page w/out posts

This commit is contained in:
Joe Bryan 2022-12-12 21:49:36 -05:00
parent 4659b92d26
commit d043a42128
2 changed files with 76 additions and 67 deletions

View File

@ -42,6 +42,7 @@
c3_c* dir_c; // checkpoint dir c3_c* dir_c; // checkpoint dir
c3_w dit_w[u3a_pages >> 5]; // touched since last save c3_w dit_w[u3a_pages >> 5]; // touched since last save
c3_w pag_w; // number of pages (<= u3a_pages) c3_w pag_w; // number of pages (<= u3a_pages)
c3_w gar_w; // guard page
u3e_image nor_u; // north segment u3e_image nor_u; // north segment
u3e_image sou_u; // south segment u3e_image sou_u; // south segment
} u3e_pool; } u3e_pool;

View File

@ -55,7 +55,7 @@
//! definitions: //! definitions:
//! - a clean page is PROT_READ and 0 in the bitmap //! - a clean page is PROT_READ and 0 in the bitmap
//! - a dirty page is (PROT_READ|PROT_WRITE) and 1 in the bitmap //! - a dirty page is (PROT_READ|PROT_WRITE) and 1 in the bitmap
//! - the guard page is PROT_NONE and 1 in the bitmap (XX assumed) //! - the guard page is PROT_NONE and 1 in the bitmap
//! //!
//! assumptions: //! assumptions:
//! - all memory access patterns are outside-in, a page at a time //! - all memory access patterns are outside-in, a page at a time
@ -96,9 +96,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.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. //! Urbit page size in 4-byte words.
#define pag_wiz_i ((size_t)1 << u3a_page) #define pag_wiz_i ((size_t)1 << u3a_page)
@ -190,61 +187,71 @@ _ce_flaw_protect(c3_w pag_w)
static inline c3_i static inline c3_i
_ce_ward_protect(void) _ce_ward_protect(void)
{ {
if ( 0 != mprotect(u3a_into(gar_pag_p), pag_siz_i, PROT_NONE) ) { if ( 0 != mprotect((void *)(u3_Loom + (u3P.gar_w << u3a_page)),
pag_siz_i,
PROT_NONE) )
{
fprintf(stderr, "loom: failed to protect guard page (%u): %s\r\n", fprintf(stderr, "loom: failed to protect guard page (%u): %s\r\n",
gar_pag_p >> u3a_page, strerror(errno)); u3P.gar_w, strerror(errno));
return 1; return 1;
} }
return 0; return 0;
} }
//! Place a guard page at the (approximate) middle of the free space between /* _ce_ward_post(): set the guard page.
//! the heap and stack of the current road, bailing if memory has been */
//! exhausted. static inline c3_i
static c3_i _ce_ward_post(c3_w nop_w, c3_w sop_w)
_ce_center_guard_page(void)
{ {
u3p(c3_w) bot_p, top_p; u3P.gar_w = nop_w + ((sop_w - nop_w) / 2);
if ( !u3R ) { return _ce_ward_protect();
top_p = u3a_outa(u3_Loom + u3C.wor_i); }
bot_p = u3a_outa(u3_Loom);
} /* _ce_ward_clip(): hit the guard page.
else if ( c3y == u3a_is_north(u3R) ) { */
top_p = c3_rod(u3R->cap_p, pag_wiz_i); static inline c3_i
bot_p = c3_rop(u3R->hat_p, pag_wiz_i); _ce_ward_clip(void)
} {
else { const c3_w old_w = u3P.gar_w;
top_p = c3_rod(u3R->hat_p, pag_wiz_i); c3_w nop_w, sop_w;
bot_p = c3_rop(u3R->cap_p, pag_wiz_i); {
u3_post low_p, hig_p;
if ( !u3R ) {
low_p = 1;
hig_p = u3C.wor_i - 1;
}
else if ( c3y == u3a_is_north(u3R) ) {
low_p = u3R->hat_p;
hig_p = u3R->cap_p;
}
else {
low_p = u3R->cap_p;
hig_p = u3R->hat_p;
}
nop_w = (low_p - 1) >> u3a_page;
sop_w = hig_p >> u3a_page;
} }
if ( top_p < bot_p + pag_wiz_i ) { if ( !u3P.gar_w || ((nop_w < u3P.gar_w) && (sop_w > u3P.gar_w)) ) {
fprintf(stderr, fprintf(stderr, "loom: ward bogus (>%u %u %u<)\r\n",
"loom: not enough memory to recenter the guard page\r\n"); nop_w, u3P.gar_w, sop_w);
goto bail; return 0;
}
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 ( _ce_ward_protect() ) { if ( sop_w <= (nop_w + 1) ) {
goto fail; u3m_signal(c3__meme); // doesn't return
return 1;
} }
if ( _ce_ward_post(nop_w, sop_w) ) {
return 0;
}
c3_assert( old_w != u3P.gar_w );
return 1; return 1;
bail:
u3m_signal(c3__meme);
fail:
return 0;
} }
#endif /* ifdef U3_GUARD_PAGE */ #endif /* ifdef U3_GUARD_PAGE */
@ -276,14 +283,20 @@ u3e_fault(void* adr_v, c3_i ser_i)
c3_w bit_w = (pag_w & 31); c3_w bit_w = (pag_w & 31);
#ifdef U3_GUARD_PAGE #ifdef U3_GUARD_PAGE
// The fault happened in the guard page. if ( pag_w == u3P.gar_w ) {
if ( gar_pag_p <= adr_p && adr_p < gar_pag_p + pag_wiz_i ) { if ( !_ce_ward_clip() ) {
if ( 0 == _ce_center_guard_page() ) { c3_assert(0);
return 0;
}
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
fprintf(stderr, "loom: strange guard (%d)\r\n", pag_w);
c3_assert(0);
return 0; return 0;
} }
} }
else else
#endif /* ifdef U3_GUARD_PAGE */ #endif
if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) { 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); fprintf(stderr, "strange page: %d, at %p, off %x\r\n", pag_w, adr_w, adr_p);
c3_assert(0); c3_assert(0);
@ -591,8 +604,8 @@ _ce_patch_compose(void)
nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page; nor_w = (nwr_w + (pag_wiz_i - 1)) >> u3a_page;
sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page; sou_w = (swu_w + (pag_wiz_i - 1)) >> u3a_page;
c3_assert( ((gar_pag_p >> u3a_page) >= nor_w) c3_assert( (u3P.gar_w >= nor_w)
&& ((gar_pag_p >> u3a_page) <= (u3P.pag_w - (sou_w + 1))) ); && (u3P.gar_w <= (u3P.pag_w - (sou_w + 1))) );
} }
#ifdef U3_SNAPSHOT_VALIDATION #ifdef U3_SNAPSHOT_VALIDATION
@ -867,7 +880,7 @@ _ce_loom_protect_north(c3_w pgs_w, c3_w old_w)
// //
// NB: < pgs_w is precluded by assertion in _ce_patch_compose() // NB: < pgs_w is precluded by assertion in _ce_patch_compose()
// //
if ( (gar_pag_p >> u3a_page) < old_w ) { if ( u3P.gar_w < old_w ) {
fprintf(stderr, "loom: guard on reprotect\r\n"); fprintf(stderr, "loom: guard on reprotect\r\n");
c3_assert( !_ce_ward_protect() ); c3_assert( !_ce_ward_protect() );
} }
@ -914,7 +927,7 @@ _ce_loom_protect_south(c3_w pgs_w, c3_w old_w)
// //
// NB: >= pgs_w is precluded by assertion in _ce_patch_compose() // NB: >= pgs_w is precluded by assertion in _ce_patch_compose()
// //
if ( (gar_pag_p >> u3a_page) >= off_w ) { if ( u3P.gar_w >= off_w ) {
fprintf(stderr, "loom: guard on reprotect\r\n"); fprintf(stderr, "loom: guard on reprotect\r\n");
c3_assert( !_ce_ward_protect() ); c3_assert( !_ce_ward_protect() );
} }
@ -973,7 +986,7 @@ _ce_loom_mapf_north(c3_i fid_i, c3_w pgs_w, c3_w old_w)
// //
// NB: < pgs_w is precluded by assertion in _ce_patch_compose() // NB: < pgs_w is precluded by assertion in _ce_patch_compose()
// //
if ( (gar_pag_p >> u3a_page) < old_w ) { if ( u3P.gar_w < old_w ) {
fprintf(stderr, "loom: guard on remap\r\n"); fprintf(stderr, "loom: guard on remap\r\n");
c3_assert( !_ce_ward_protect() ); c3_assert( !_ce_ward_protect() );
} }
@ -1361,7 +1374,7 @@ u3e_live(c3_c* dir_c)
} }
#ifdef U3_GUARD_PAGE #ifdef U3_GUARD_PAGE
_ce_center_guard_page(); c3_assert( !_ce_ward_post(nor_w, u3P.pag_w - sou_w) );
#endif #endif
} }
} }
@ -1405,7 +1418,7 @@ u3e_init(void)
u3P.pag_w = u3C.wor_i >> u3a_page; u3P.pag_w = u3C.wor_i >> u3a_page;
#ifdef U3_GUARD_PAGE #ifdef U3_GUARD_PAGE
_ce_center_guard_page(); c3_assert( !_ce_ward_post(0, u3P.pag_w) );
#endif #endif
_ce_loom_track_north(0, u3P.pag_w); _ce_loom_track_north(0, u3P.pag_w);
@ -1417,19 +1430,14 @@ void
u3e_ward(u3_post low_p, u3_post hig_p) u3e_ward(u3_post low_p, u3_post hig_p)
{ {
#ifdef U3_GUARD_PAGE #ifdef U3_GUARD_PAGE
const u3p(c3_w) gar_p = gar_pag_p; c3_w nop_w = (low_p - 1) >> u3a_page;
c3_w sop_w = hig_p >> u3a_page;
c3_w pag_w = u3P.gar_w;
if ( (low_p > gar_p) || (hig_p < gar_p) ) { if ( !((pag_w > nop_w) && (pag_w < hig_p)) ) {
_ce_center_guard_page(); c3_assert( !_ce_ward_post(nop_w, sop_w) );
c3_assert( !_ce_flaw_protect(gar_p >> u3a_page) ); c3_assert( !_ce_flaw_protect(pag_w) );
c3_assert( u3P.dit_w[pag_w >> 5] & (1 << (pag_w & 31)) );
{
c3_w pag_w = gar_p >> u3a_page;
c3_w blk_w = (pag_w >> 5);
c3_w bit_w = (pag_w & 31);
u3P.dit_w[blk_w] |= (1 << bit_w);
}
} }
#endif #endif
} }