u3: adds new, batch page tracking implementations + tests

This commit is contained in:
Joe Bryan 2022-12-02 09:19:14 -05:00
parent d1d1860ac7
commit c111129a5e
2 changed files with 323 additions and 0 deletions

View File

@ -775,6 +775,91 @@ _ce_loom_pure_south(c3_w pgs_w)
u3P.dit_w[bas_w - 1] &= 0xffffffff >> bit_w;
}
/* _ce_loom_track_north(): [pgs_w] clean, followed by [dif_w] dirty.
*/
void
_ce_loom_track_north(c3_w pgs_w, c3_w dif_w)
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
c3_w off_w;
memset((void*)u3P.dit_w, 0, blk_w << 2);
if ( bit_w ) {
c3_w tib_w = 32 - bit_w;
c3_w dat_w = u3P.dit_w[blk_w];
dat_w &= 0xffffffff << bit_w;
if ( dif_w <= tib_w ) {
dat_w |= ((1 << dif_w) - 1) << bit_w;
dif_w = 0;
}
else {
dat_w |= 0xffffffff << bit_w;
dif_w -= tib_w;
}
u3P.dit_w[blk_w] = dat_w;
blk_w += 1;
}
off_w = blk_w;
blk_w = dif_w >> 5;
bit_w = dif_w & 31;
memset((void*)(u3P.dit_w + off_w), 0xff, blk_w << 2);
if ( bit_w ) {
u3P.dit_w[off_w + blk_w] |= (1 << bit_w) - 1;
}
}
/* _ce_loom_track_south(): [pgs_w] clean, preceded by [dif_w] dirty.
*/
void
_ce_loom_track_south(c3_w pgs_w, c3_w dif_w)
{
c3_w blk_w = pgs_w >> 5;
c3_w bit_w = pgs_w & 31;
c3_w bas_w = ((u3P.pag_w - pgs_w) + 31) >> 5;
c3_w off_w;
memset((void*)(u3P.dit_w + bas_w), 0, blk_w << 2);
// the following index subtractions (bas_w, off) are safe,
// so long as the south segment never includes all pages
//
if ( bit_w ) {
c3_w tib_w = 32 - bit_w;
c3_w dat_w = u3P.dit_w[--bas_w];
dat_w &= 0xffffffff >> bit_w;
if ( dif_w <= tib_w ) {
dat_w |= ((1 << dif_w) - 1) << (tib_w - dif_w);
dif_w = 0;
}
else {
dat_w |= 0xffffffff >> bit_w;
dif_w -= tib_w;
}
u3P.dit_w[bas_w] = dat_w;
}
blk_w = dif_w >> 5;
bit_w = dif_w & 31;
off_w = bas_w - blk_w;
memset((void*)(u3P.dit_w + off_w), 0xff, blk_w << 2);
if ( bit_w ) {
u3P.dit_w[off_w - 1] |= ((1 << bit_w) - 1) << (32 - bit_w);
}
}
/* _ce_loom_protect_north(): protect/track pages from the bottom of memory.
*/
static void

View File

@ -0,0 +1,238 @@
#include "all.h"
/* _setup(): prepare for tests.
*/
static void
_setup(void)
{
// NB: no loom
//
u3P.pag_w = u3a_pages;
}
static c3_w
_check_north_clean(void)
{
c3_w i_w, pag_w, blk_w, bit_w;
for ( i_w = 0; i_w < u3P.pag_w; i_w++ ) {
pag_w = i_w;
blk_w = pag_w >> 5;
bit_w = pag_w & 31;
if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
break;
}
}
return i_w;
}
static c3_w
_check_north_dirty(c3_w pgs_w, c3_w max_w)
{
c3_w i_w, pag_w, blk_w, bit_w;
for ( i_w = 0; i_w < max_w; i_w++ ) {
pag_w = i_w + pgs_w;
blk_w = pag_w >> 5;
bit_w = pag_w & 31;
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
break;
}
}
return i_w;
}
static c3_w
_check_south_clean(void)
{
c3_w i_w, pag_w, blk_w, bit_w;
for ( i_w = 0; i_w < u3P.pag_w; i_w++ ) {
pag_w = u3P.pag_w - (i_w + 1);
blk_w = pag_w >> 5;
bit_w = pag_w & 31;
if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
break;
}
}
return i_w;
}
static c3_w
_check_south_dirty(c3_w pgs_w, c3_w max_w)
{
c3_w i_w, pag_w, blk_w, bit_w;
for ( i_w = 0; i_w < max_w; i_w++ ) {
pag_w = u3P.pag_w - (i_w + pgs_w + 1);
blk_w = pag_w >> 5;
bit_w = pag_w & 31;
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
break;
}
}
return i_w;
}
void
_ce_loom_track_north(c3_w pgs_w, c3_w dif_w);
void
_ce_loom_track_south(c3_w pgs_w, c3_w dif_w);
static c3_i
_test_tracking(void)
{
c3_w ret_w;
u3e_foul();
if ( 0 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north init %u\r\n", ret_w);
return 0;
}
if ( 0 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south init %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(100, 0);
_ce_loom_track_south(1, 0);
if ( 100 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean a %u\r\n", ret_w);
return 0;
}
if ( 1 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean a %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(75, 25);
_ce_loom_track_south(2, 0);
if ( 75 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean b %u\r\n", ret_w);
return 0;
}
if ( 25 != (ret_w = _check_north_dirty(75, 25)) ) {
fprintf(stderr, "test events track north dirty b %u\r\n", ret_w);
return 0;
}
if ( 2 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean b %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(55, 20);
_ce_loom_track_south(1, 1);
if ( 55 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean c %u\r\n", ret_w);
return 0;
}
if ( 20 != (ret_w = _check_north_dirty(55, 20)) ) {
fprintf(stderr, "test events track north dirty c %u\r\n", ret_w);
return 0;
}
if ( 1 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean c %u\r\n", ret_w);
return 0;
}
if ( 1 != (ret_w = _check_south_dirty(1, 1)) ) {
fprintf(stderr, "test events track north dirty c %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(255, 0);
_ce_loom_track_south(48, 0);
if ( 255 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean d %u\r\n", ret_w);
return 0;
}
if ( 48 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean d %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(213, 42);
_ce_loom_track_south(15, 33);
if ( 213 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean e %u\r\n", ret_w);
return 0;
}
if ( 42 != (ret_w = _check_north_dirty(213, 42)) ) {
fprintf(stderr, "test events track north dirty e %u\r\n", ret_w);
return 0;
}
if ( 15 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean e %u\r\n", ret_w);
return 0;
}
if ( 33 != (ret_w = _check_south_dirty(15, 33)) ) {
fprintf(stderr, "test events track north dirty e %u\r\n", ret_w);
return 0;
}
_ce_loom_track_north(200, 13);
_ce_loom_track_south(10, 5);
if ( 200 != (ret_w = _check_north_clean()) ) {
fprintf(stderr, "test events track north clean f %u\r\n", ret_w);
return 0;
}
if ( 13 != (ret_w = _check_north_dirty(200, 13)) ) {
fprintf(stderr, "test events track north dirty f %u\r\n", ret_w);
return 0;
}
if ( 10 != (ret_w = _check_south_clean()) ) {
fprintf(stderr, "test events track south clean f %u\r\n", ret_w);
return 0;
}
if ( 5 != (ret_w = _check_south_dirty(10, 5)) ) {
fprintf(stderr, "test events track north dirty f %u\r\n", ret_w);
return 0;
}
return 1;
}
/* main(): run all test cases.
*/
int
main(int argc, char* argv[])
{
_setup();
if ( !_test_tracking() ) {
fprintf(stderr, "test_events: tracking: failed\r\n");
exit(1);
}
fprintf(stderr, "test_events: ok\n");
return 0;
}