u3: coalesces memory protection when saving a snapshot

This commit is contained in:
Joe Bryan 2022-11-02 22:46:12 -04:00
parent 0682cc2864
commit a04521585c

View File

@ -507,21 +507,6 @@ _ce_patch_open(void)
return pat_u; return pat_u;
} }
/* _ce_patch_write_page(): write a page of patch memory.
*/
static void
_ce_patch_write_page(u3_ce_patch* pat_u,
c3_w pgc_w,
c3_w* mem_w)
{
size_t off_i = (size_t)pgc_w << (u3a_page + 2);
if ( 0 > c3_pwrite(pat_u->mem_i, mem_w, pag_siz_i, off_i) ) {
fprintf(stderr, "loom: patch write: %s\r\n", strerror(errno));
c3_assert(0);
}
}
/* _ce_patch_count_page(): count a page, producing new counter. /* _ce_patch_count_page(): count a page, producing new counter.
*/ */
static c3_w static c3_w
@ -549,24 +534,16 @@ _ce_patch_save_page(u3_ce_patch* pat_u,
if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
c3_w* mem_w = u3_Loom + (pag_w << u3a_page); c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
size_t off_i = (size_t)pgc_w << (u3a_page + 2);
pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; 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, pag_wiz_i); pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w, pag_wiz_i);
#if 0 if ( 0 > c3_pwrite(pat_u->mem_i, mem_w, pag_siz_i, off_i) ) {
u3l_log("protect a: page %d\r\n", pag_w); fprintf(stderr, "loom: patch save: %s\r\n", strerror(errno));
#endif
_ce_patch_write_page(pat_u, pgc_w, mem_w);
if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
pag_siz_i,
PROT_READ) )
{
fprintf(stderr, "loom: patch mprotect: %s\r\n", strerror(errno));
c3_assert(0); c3_assert(0);
} }
u3P.dit_w[blk_w] &= ~(1 << bit_w);
pgc_w += 1; pgc_w += 1;
} }
return pgc_w; return pgc_w;
@ -749,6 +726,62 @@ _ce_patch_apply(u3_ce_patch* pat_u)
} }
} }
/* _ce_loom_protect_north(): protect/track pages from the bottom of memory.
*/
static void
_ce_loom_protect_north(c3_w pgs_w)
{
if ( pgs_w ) {
if ( 0 != mprotect((void*)u3_Loom,
(size_t)pgs_w << (u3a_page + 2),
PROT_READ) )
{
fprintf(stderr, "loom: protect north (%u pages): %s\r\n",
pgs_w, strerror(errno));
c3_assert(0);
}
}
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
memset((void*)u3P.dit_w, 0, blk_w << 2);
u3P.dit_w[blk_w] &= 0xffffffff << bit_w;
}
}
/* _ce_loom_protect_south(): protect/track pages from the top of memory.
*/
static void
_ce_loom_protect_south(c3_w pgs_w)
{
c3_w lof_w = u3P.pag_w - pgs_w;
if ( pgs_w ) {
if ( 0 != mprotect((void*)(u3_Loom + (lof_w << u3a_page)),
(size_t)pgs_w << (u3a_page + 2),
PROT_READ) )
{
fprintf(stderr, "loom: protect south (%u pages): %s\r\n",
pgs_w, strerror(errno));
c3_assert(0);
}
}
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
c3_w bas_w = (lof_w + 31) >> 5;
memset((void*)(u3P.dit_w + bas_w), 0, blk_w << 2);
// this is safe so long as the south segment never includes all pages
//
u3P.dit_w[bas_w - 1] &= 0xffffffff >> bit_w;
}
}
/* _ce_loom_blit_north(): apply pages, in order, from the bottom of memory. /* _ce_loom_blit_north(): apply pages, in order, from the bottom of memory.
*/ */
static void static void
@ -770,21 +803,7 @@ _ce_loom_blit_north(c3_i fid_i, c3_w pgs_w)
} }
} }
if ( 0 != mprotect((void*)u3_Loom, _ce_loom_protect_north(pgs_w);
(size_t)pgs_w << (u3a_page + 2),
PROT_READ) )
{
fprintf(stderr, "loom: protect north: %s\r\n", strerror(errno));
c3_assert(0);
}
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
memset((void*)u3P.dit_w, 0, blk_w << 2);
u3P.dit_w[blk_w] &= 0xffffffff << bit_w;
}
} }
/* _ce_loom_blit_south(): apply pages, reversed, from the top of memory. /* _ce_loom_blit_south(): apply pages, reversed, from the top of memory.
@ -792,15 +811,14 @@ _ce_loom_blit_north(c3_i fid_i, c3_w pgs_w)
static void static void
_ce_loom_blit_south(c3_i fid_i, c3_w pgs_w) _ce_loom_blit_south(c3_i fid_i, c3_w pgs_w)
{ {
c3_w lof_w, i_w; c3_w i_w;
c3_w* ptr_w; c3_w* ptr_w;
size_t off_i; size_t off_i;
ssize_t ret_i; ssize_t ret_i;
for ( i_w = 0; i_w < pgs_w; i_w++ ) { for ( i_w = 0; i_w < pgs_w; i_w++ ) {
off_i = (size_t)i_w << (u3a_page + 2); off_i = (size_t)i_w << (u3a_page + 2);
lof_w = u3P.pag_w - (i_w + 1); ptr_w = u3_Loom + ((u3P.pag_w - (i_w + 1)) << u3a_page);
ptr_w = u3_Loom + (lof_w << u3a_page);
if ( pag_siz_i != (ret_i = c3_pread(fid_i, ptr_w, pag_siz_i, off_i)) ) { if ( pag_siz_i != (ret_i = c3_pread(fid_i, ptr_w, pag_siz_i, off_i)) ) {
if ( 0 < ret_i ) { if ( 0 < ret_i ) {
@ -814,27 +832,7 @@ _ce_loom_blit_south(c3_i fid_i, c3_w pgs_w)
} }
} }
c3_assert ( (u3P.pag_w - pgs_w) == lof_w ); _ce_loom_protect_south(pgs_w);
if ( 0 != mprotect((void*)(u3_Loom + (lof_w << u3a_page)),
(size_t)pgs_w << (u3a_page + 2),
PROT_READ) )
{
fprintf(stderr, "loom: protect south: %s\r\n", strerror(errno));
c3_assert(0);
}
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
c3_w bas_w = (lof_w + 31) >> 5;
memset((void*)(u3P.dit_w + bas_w), 0, blk_w << 2);
// this is safe so long as the south segment never includes all pages
//
u3P.dit_w[bas_w - 1] &= 0xffffffff >> bit_w;
}
} }
#ifdef U3_SNAPSHOT_VALIDATION #ifdef U3_SNAPSHOT_VALIDATION
@ -1034,6 +1032,9 @@ u3e_save(void)
} }
#endif #endif
_ce_loom_protect_north(u3P.nor_u.pgs_w);
_ce_loom_protect_south(u3P.sou_u.pgs_w);
_ce_image_sync(&u3P.nor_u); _ce_image_sync(&u3P.nor_u);
_ce_image_sync(&u3P.sou_u); _ce_image_sync(&u3P.sou_u);
_ce_patch_free(pat_u); _ce_patch_free(pat_u);