@@ -42,7 +42,7 @@ extern void prints_hello_world() {
4242
4343 // Make machine forkable (no working memory)
4444 machine.prepare_copy_on_write (65536 );
45- REQUIRE (machine.banked_memory_pages () == 4 );
45+ REQUIRE (machine.banked_memory_pages () == 5 );
4646 REQUIRE (machine.is_forkable ());
4747 REQUIRE (!machine.is_forked ());
4848
@@ -249,7 +249,7 @@ extern int get_value() {
249249
250250 // Make machine forkable (with working memory)
251251 machine.prepare_copy_on_write (65536 );
252- REQUIRE (machine.banked_memory_pages () == 4 );
252+ REQUIRE (machine.banked_memory_pages () == 5 );
253253 REQUIRE (machine.is_forkable ());
254254 REQUIRE (!machine.is_forked ());
255255
@@ -293,10 +293,10 @@ extern int get_value() {
293293
294294 // Value now starts at 1 due to the change in main VM
295295 fork1.timed_vmcall (funcaddr, 4 .0f );
296- REQUIRE (fork1.return_value () == 2 );
296+ REQUIRE (fork1.return_value () == 1 );
297297
298298 fork2.timed_vmcall (funcaddr, 4 .0f );
299- REQUIRE (fork2.return_value () == 2 );
299+ REQUIRE (fork2.return_value () == 1 );
300300}
301301
302302TEST_CASE (" Fork sanity checks w/crashes" , " [Fork]" )
@@ -363,7 +363,9 @@ extern void crash() {
363363TEST_CASE (" Fork and run main()" , " [Fork]" )
364364{
365365 const auto binary = build_and_load (R"M(
366+ #include <stdio.h>
366367int main() {
368+ printf("Hello World!\n");
367369 return 666;
368370}
369371static unsigned value = 12345;
@@ -378,17 +380,20 @@ int func2() {
378380}
379381)M" );
380382
381- tinykvm::Machine machine { binary, { .max_mem = MAX_MEMORY } };
383+ tinykvm::Machine machine { binary, {
384+ .max_mem = MAX_MEMORY,
385+ .master_direct_memory_writes = true
386+ } };
382387
383388 // We need to create a Linux environment for runtimes to work well
384389 machine.setup_linux ({" fork" }, env);
385390 REQUIRE (machine.banked_memory_pages () == 0 );
386391
387- // Make machine forkable (with *NO* working memory)
392+ // Make machine forkable (with 4MB working memory)
388393 machine.prepare_copy_on_write (4ULL << 20 );
394+ REQUIRE (machine.banked_memory_capacity_bytes () == 4ULL << 20 );
389395 REQUIRE (machine.is_forkable ());
390396 REQUIRE (!machine.is_forked ());
391- REQUIRE (machine.return_value () == 0 ); // Initial register value
392397
393398 // Run for at most 4 seconds before giving up
394399 machine.run (4 .0f );
@@ -397,11 +402,10 @@ int func2() {
397402 // We only gave it 4MB working memory, so lets mmap allocate that and verify
398403 // that if we write more than that, we get an exception thrown
399404 REQUIRE_THROWS ([&] () {
400- const size_t size = 5ULL << 20 ;
401- uint64_t addr = machine.mmap_allocate (5ULL << 20 );
405+ const size_t size = 8ULL << 20 ;
406+ uint64_t addr = machine.mmap_allocate (size );
402407 char buffer[4096 ];
403- for (int i = 0 ; i < 4096 ; i++)
404- buffer[i] = ' a' ;
408+ memset (buffer, ' a' , sizeof (buffer));
405409 for (size_t i = 0 ; i < size; i += 4096 )
406410 {
407411 machine.copy_to_guest (addr + i, buffer, 4096 );
@@ -411,11 +415,33 @@ int func2() {
411415 }());
412416
413417 // There are banked pages now
414- const auto banked_pages_before = machine.banked_memory_pages ();
418+ const auto banked_pages_before = machine.main_memory (). unlocked_memory_pages ();
415419 REQUIRE (banked_pages_before > 500 );
416420
421+ // We have no free memory now, so make another VM
422+ tinykvm::Machine machine2 { binary, {
423+ .max_mem = MAX_MEMORY,
424+ .master_direct_memory_writes = true
425+ } };
426+
427+ // We need to create a Linux environment for runtimes to work well
428+ machine2.setup_linux ({" fork" }, env);
429+ REQUIRE (machine2.banked_memory_pages () == 0 );
430+
431+ // Make machine forkable (with 4MB working memory)
432+ machine2.prepare_copy_on_write (4ULL << 20 );
433+ REQUIRE (machine2.banked_memory_capacity_bytes () == 4ULL << 20 );
434+ REQUIRE (machine2.is_forkable ());
435+ REQUIRE (!machine2.is_forked ());
436+
437+ // Run for at most 4 seconds before giving up
438+ machine2.run (4 .0f );
439+ REQUIRE (machine2.return_value () == 666 ); // Main() return value
440+
441+ machine2.prepare_copy_on_write (0 );
442+
417443 // Create fork
418- auto fork1 = tinykvm::Machine { machine , {
444+ auto fork1 = tinykvm::Machine { machine2 , {
419445 .max_mem = MAX_MEMORY, .max_cow_mem = MAX_COWMEM
420446 } };
421447 REQUIRE (fork1.return_value () == 666 ); // Main() return value
@@ -425,25 +451,17 @@ int func2() {
425451
426452 fork1.vmcall (" func2" );
427453 REQUIRE (fork1.return_value () == 54321 );
428-
429- // This is problematic, but we will try to fix this later
430- // Forked VM is supposed to diverge from the main VM, regardless of mode
431- machine.vmcall (" set_value" , 99999 );
432- fork1.vmcall (" func1" );
433- REQUIRE (fork1.return_value () == 99999 );
434-
435- REQUIRE (machine.banked_memory_pages () == banked_pages_before);
436454 REQUIRE (fork1.banked_memory_pages () > 0 );
437455
438456 for (int i = 0 ; i < 20 ; i++)
439457 {
440- fork1.reset_to (machine , {
458+ fork1.reset_to (machine2 , {
441459 .max_mem = MAX_MEMORY,
442460 .max_cow_mem = MAX_COWMEM,
443461 });
444462
445463 fork1.vmcall (" func1" );
446- REQUIRE (fork1.return_value () == 99999 );
464+ REQUIRE (fork1.return_value () == 12345 );
447465
448466 fork1.vmcall (" func2" );
449467 REQUIRE (fork1.return_value () == 54321 );
0 commit comments