From ce60cb0f6a542d7ccfb6d0c07b8e818ee5e30694 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Fri, 19 Apr 2024 18:56:33 +0200 Subject: [PATCH 01/14] try enable gc --- src/phantom/isomem/main.c | 20 ++++++++++++++++++++ src/phantom/vm/alloc.c | 2 +- src/phantom/vm/gc.c | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index 7869bf8c4..ad07f47a1 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -579,6 +579,26 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) //init_wins(u_int32_t ip_addr); + { + hal_sleep_msec(2000); + + ph_printf("\ndumpo:\n"); + pvm_object_t p = get_root_object_storage(); + dumpo(p); + + unsigned i; + + for (i = 0; i < da_po_limit(p); i++) { + dumpo(da_po_ptr(p->da)[i]); + } + + + ph_printf("\nGC started:\n"); + phantom_snapper_wait_4_threads(); + run_gc(); + ph_printf("\nGC end:\n"); + phantom_snapper_reenable_threads(); + } ph_printf("\n\x1b[33m\x1b[44mPhantom " PHANTOM_VERSION_STR " (SVN rev %s) @ %s started\x1b[0m\n\n", svn_version(), phantom_uname.machine ); diff --git a/src/phantom/vm/alloc.c b/src/phantom/vm/alloc.c index 16e352fc3..50b883fbb 100755 --- a/src/phantom/vm/alloc.c +++ b/src/phantom/vm/alloc.c @@ -433,7 +433,7 @@ static pvm_object_t pvm_find(unsigned int size, int arena) -#define PVM_GC_ENABLE 0 +#define PVM_GC_ENABLE 1 static pvm_object_storage_t * pool_alloc(unsigned int size, int arena) diff --git a/src/phantom/vm/gc.c b/src/phantom/vm/gc.c index fddaa850f..f911d3890 100644 --- a/src/phantom/vm/gc.c +++ b/src/phantom/vm/gc.c @@ -166,6 +166,7 @@ static int free_unmarked() static void mark_tree(pvm_object_storage_t * p) { + ph_printf("\nGC: process another object\n"); p->_ah.gc_flags = gc_flags_last_generation; // set From 3c936f335a021e85dbea9a54ef3235adfa18963e Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Fri, 3 May 2024 15:03:22 +0200 Subject: [PATCH 02/14] try to implement gc on snap --- src/include/kernel/config.h | 1 + src/include/vm/alloc.h | 1 + src/phantom/vm/create.c | 85 +++++++----- src/phantom/vm/gc_on_snap.c | 249 ++++++++++++++++++++++++++++++++++++ src/phantom/vm/vm.cmake | 1 + 5 files changed, 302 insertions(+), 35 deletions(-) create mode 100644 src/phantom/vm/gc_on_snap.c diff --git a/src/include/kernel/config.h b/src/include/kernel/config.h index 4fc5d2d79..0941d693b 100644 --- a/src/include/kernel/config.h +++ b/src/include/kernel/config.h @@ -17,6 +17,7 @@ #define NEW_TASK_BAR 1 +#define N_OBJMEM_PAGES ((1024L*1024*32)/4096) #define UHCI_INTERRUPT 0 #define OHCI_INTERRUPT 1 diff --git a/src/include/vm/alloc.h b/src/include/vm/alloc.h index bff54dfd0..137d88d2c 100755 --- a/src/include/vm/alloc.h +++ b/src/include/vm/alloc.h @@ -44,6 +44,7 @@ void debug_catch_object(const char *msg, pvm_object_storage_t *p); // gc void run_gc(void); +void run_gc_on_snap(); // Make sure this object won't be deleted with refcount dec // used on sys global objects diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index 616857aaa..b2445c55c 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -43,6 +43,10 @@ * **/ +static pvm_object_t shift_ptr( pvm_object_t o, long long shift ) +{ + return (pvm_object_t)( (char*)o + shift ); +} static pvm_object_t pvm_object_create_fixed( pvm_object_t object_class ) @@ -365,11 +369,12 @@ void pvm_gc_iter_page(gc_iterator_call_t func, pvm_object_t os, void *arg) { int n_slots = (os->_da_size) / sizeof(pvm_object_t ); pvm_object_t * data_area = (pvm_object_t *)&(os->da); + long long shift = *(long long*)arg; int i; for( i = 0; i < n_slots; i++ ) { - func( data_area[i], arg ); + func( shift_ptr(data_area[i], shift), arg ); } } @@ -411,11 +416,12 @@ void pvm_internal_init_call_frame(pvm_object_t os) void pvm_gc_iter_call_frame(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_call_frame *da = (struct data_area_4_call_frame *)&(os->da); - gc_fcall( func, arg, da->this_object ); - gc_fcall( func, arg, da->prev ); // FYI - shall never be followed in normal situation, must contain zero data ptr if being considered by refcount - gc_fcall( func, arg, da->istack ); - gc_fcall( func, arg, da->ostack ); - gc_fcall( func, arg, da->estack ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->this_object, shift) ); + gc_fcall( func, arg, shift_ptr(da->prev, shift) ); // FYI - shall never be followed in normal situation, must contain zero data ptr if being considered by refcount + gc_fcall( func, arg, shift_ptr(da->istack, shift) ); + gc_fcall( func, arg, shift_ptr(da->ostack, shift) ); + gc_fcall( func, arg, shift_ptr(da->estack, shift) ); } @@ -527,15 +533,17 @@ void pvm_internal_init_class(pvm_object_t os) void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_class *da = (struct data_area_4_class *)&(os->da); - gc_fcall( func, arg, da->object_default_interface ); - gc_fcall( func, arg, da->class_name ); - gc_fcall( func, arg, da->class_parent ); + long long shift = *(long long*)arg; - gc_fcall( func, arg, da->static_vars ); + gc_fcall( func, arg, shift_ptr(da->object_default_interface, shift) ); + gc_fcall(func, arg, shift_ptr(da->class_name, shift)); + gc_fcall(func, arg, shift_ptr(da->class_parent, shift)); - gc_fcall( func, arg, da->ip2line_maps ); - gc_fcall( func, arg, da->method_names ); - gc_fcall( func, arg, da->field_names ); + gc_fcall(func, arg, shift_ptr(da->static_vars, shift)); + + gc_fcall(func, arg, shift_ptr(da->ip2line_maps, shift)); + gc_fcall(func, arg, shift_ptr(da->method_names, shift)); + gc_fcall(func, arg, shift_ptr(da->field_names, shift)); } @@ -571,9 +579,10 @@ void pvm_internal_init_thread(pvm_object_t os) void pvm_gc_iter_thread(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_thread *da = (struct data_area_4_thread *)&(os->da); - gc_fcall( func, arg, da->call_frame ); - gc_fcall( func, arg, da->owner ); - gc_fcall( func, arg, da->environment ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->call_frame, shift) ); + gc_fcall( func, arg, shift_ptr(da->owner, shift) ); + gc_fcall( func, arg, shift_ptr(da->environment, shift) ); } @@ -607,8 +616,9 @@ void pvm_internal_init_array(pvm_object_t os) void pvm_gc_iter_array(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_array *da = (struct data_area_4_array *)&(os->da); + long long shift = *(long long*)arg; if(da->page != 0) - gc_fcall( func, arg, da->page ); + gc_fcall( func, arg, shift_ptr(da->page, shift) ); } @@ -648,13 +658,15 @@ void pvm_gc_iter_mutex(gc_iterator_call_t func, pvm_object_t os, void *arg) //pvm_spin_init( &da->pvm_lock ); // in_method = 0; - gc_fcall( func, arg, da->waiting_threads_array ); + long long shift = *(long long*)arg; + + gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); - gc_fcall( func, arg, pvm_da_to_object(da->owner_thread) ); + gc_fcall( func, arg, shift_ptr(pvm_da_to_object(da->owner_thread), shift) ); } @@ -672,8 +684,8 @@ void pvm_gc_iter_cond(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_cond * da = (struct data_area_4_cond *)os->da; //int i; - - gc_fcall( func, arg, da->waiting_threads_array ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); @@ -697,12 +709,13 @@ void pvm_gc_iter_sema(gc_iterator_call_t func, pvm_object_t os, void *arg) struct data_area_4_sema * da = (struct data_area_4_sema *)os->da; //int i; - gc_fcall( func, arg, da->waiting_threads_array ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); - gc_fcall( func, arg, pvm_da_to_object(da->owner_thread) ); + gc_fcall( func, arg, shift_ptr(pvm_da_to_object(da->owner_thread), shift) ); } @@ -750,8 +763,9 @@ void pvm_internal_init_bitmap(pvm_object_t os) void pvm_gc_iter_bitmap(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_bitmap *da = (struct data_area_4_bitmap *)&(os->da); + long long shift = *(long long*)arg; if(da->image != 0) - gc_fcall( func, arg, da->image ); + gc_fcall( func, arg, shift_ptr(da->image, shift) ); } @@ -783,7 +797,8 @@ void pvm_gc_iter_closure(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_closure * da = (struct data_area_4_closure *)os->da; //if(da->image.object != 0) - gc_fcall( func, arg, da->object ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->object, shift) ); } @@ -946,9 +961,9 @@ void pvm_internal_init_window(pvm_object_t os) void pvm_gc_iter_window(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_window *da = (struct data_area_4_window *)os->da; - - gc_fcall( func, arg, da->connector ); - gc_fcall( func, arg, da->o_pixels ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(da->connector, shift) ); + gc_fcall( func, arg, shift_ptr(da->o_pixels, shift) ); } @@ -1098,9 +1113,9 @@ pvm_object_t pvm_create_directory_object(void) void pvm_gc_iter_directory(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_directory *da = (struct data_area_4_directory *)os->da; - - gc_fcall( func, arg, da->keys ); - gc_fcall( func, arg, da->values ); + long long shift = *((long long*)arg); + gc_fcall( func, arg, shift_ptr(da->keys, shift) ); + gc_fcall( func, arg, shift_ptr(da->values, shift) ); } @@ -1136,10 +1151,10 @@ void pvm_gc_iter_connection(gc_iterator_call_t func, pvm_object_t os, void *arg pvm_object_t ot; //ot.interface = 0; ot = (void *) (((addr_t)da->owner)-DA_OFFSET()); - - gc_fcall( func, arg, ot ); - gc_fcall( func, arg, da->p_kernel_state_object ); - gc_fcall( func, arg, da->callback ); + long long shift = *(long long*)arg; + gc_fcall( func, arg, shift_ptr(ot, shift) ); + gc_fcall( func, arg, shift_ptr(da->p_kernel_state_object, shift) ); + gc_fcall( func, arg, shift_ptr(da->callback, shift) ); } diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c new file mode 100644 index 000000000..90a172911 --- /dev/null +++ b/src/phantom/vm/gc_on_snap.c @@ -0,0 +1,249 @@ +/** + * + * Phantom OS + * + * Copyright (C) 2005-2009 Dmitry Zavalishin, dz@dz.ru + * + * Fast and dirty garbage collection + * +**/ + +#define DEBUG_MSG_PREFIX "vm.gc" +#include +#define debug_level_flow 10 +#define debug_level_error 10 +#define debug_level_info 10 + +#include +#include +#include +#include + +#include "../isomem/vm_map.h" +#include "../isomem/pager.h" +#include "../isomem/pagelist.h" + +#include +#include +#include + +#include + +#include + +static pvm_object_t shift_ptr(pvm_object_t o, long long shift) +{ + return (pvm_object_t)((char*)o + shift); +} + +static unsigned char gc_flags_last_generation = 0; + +static char* load_snap() { + unsigned long page_count = N_OBJMEM_PAGES + 1; + SHOW_FLOW0(1, "Started"); + + disk_page_no_t snap_start = 0; + + if (pager_superblock_ptr()->last_snap != 0) { + hal_printf("-- Use last snap\n"); + snap_start = pager_superblock_ptr()->last_snap; + } + else if (pager_superblock_ptr()->prev_snap != 0) { + hal_printf("-- Missing last snap, use previous snap\n"); + snap_start = pager_superblock_ptr()->prev_snap; + } + + char* snapshot = 0; + + if (snap_start == 0) { + hal_printf("\n!!! No pagelist to load !!!\n"); + } + else { + hal_printf("Loading pagelist from %d...\n", snap_start); + + pagelist loader; + pagelist_init(&loader, snap_start, 0, DISK_STRUCT_MAGIC_SNAP_LIST); + pagelist_seek(&loader); + + + disk_page_no_t curr_block; + snapshot = ph_calloc(page_count, PAGE_SIZE); + unsigned int np; + + for (np = 0; np < page_count; np++) { + if (!pagelist_read_seq(&loader, &curr_block)) { + ph_printf("\n!!! Incomplete pagelist !!!\n"); + //panic("Incomplete pagelist\n"); + break; + } + + if (curr_block == 0) { + continue; + } + + disk_page_io sb; + disk_page_io_init(&sb); + errno_t rc = disk_page_io_load_sync(&sb, curr_block); + + if (rc) { + panic("failed to load snapshot in gc\n"); + } + + ph_memcpy(snapshot, disk_page_io_data(&sb), PAGE_SIZE); + snapshot += PAGE_SIZE; + } + + pagelist_finish(&loader); + } + + return snapshot; +} + +static void mark_tree(pvm_object_storage_t *p, long long shift); + +static pvm_object_storage_t **collect_unmarked(char *start, long long shift); + +static int free_unmarked(pvm_object_storage_t **to_free); + +static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t *p, void *arg); + +static void mark_tree_o(pvm_object_t o, void *arg); + +void run_gc_on_snap() { + // synchonization? + + gc_flags_last_generation++; // bump generation + if (gc_flags_last_generation == 0) gc_flags_last_generation++; // != 0 'cause allocation reset gc_flags to zero + + //phantom_virtual_machine_threads_stopped++; // pretend we are stopped + //TODO: refine synchronization + + // First pass - tree walk, mark visited. + // Root is always used. All other objects, including pvm_root and pvm_root.threads_list, should be reached from root... + // char* snapshot = load_snap(pager_superblock_ptr()->disk_page_count); + char* snapshot = load_snap(); + if (snapshot == 0) { + ph_printf("\n!!! No snapshot loaded !!!\n"); + return; + } + + long long shift = snapshot - (char*)get_pvm_object_space_start(); + + mark_tree((pvm_object_storage_t*)snapshot, shift); + pvm_object_storage_t** to_free = collect_unmarked(snapshot, shift); + + // Second pass - linear walk to free unused objects. + int freed = free_unmarked(to_free); + + if (freed > 0) + ph_printf("\ngc: %i objects freed\n", freed); +} + +static void mark_tree(pvm_object_storage_t* p, long long shift) +{ + ph_printf("\nGC: process another object\n"); + p->_ah.gc_flags = gc_flags_last_generation; // set + + assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); + assert(p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); + + // Fast skip if no children - + if (!(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE)) { + gc_process_children(mark_tree_o, p, &shift); + } +} + +static void mark_tree_o(pvm_object_t o, void* arg) { + long long shift = *((long long*)arg); + + if (o == 0) // Don't try to process null objects + return; + + if (o->_ah.gc_flags != gc_flags_last_generation) + mark_tree(o, shift); + + //if (o.interface->_ah.gc_flags != gc_flags_last_generation) mark_tree( o.interface ); +} + +static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* p, void* arg) { + f(p->_class, arg); + + long long shift = *((long long*)arg); + + // Fast skip if no children - done! + //if( p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE ) + // return; + + // plain non internal objects - + if (!(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) + { + unsigned i; + + for (i = 0; i < da_po_limit(p); i++) + { + f(shift_ptr(da_po_ptr(p->da)[i], shift), arg); + } + return; + } + + // We're here if object is internal. + + // Now find and call class-specific function: pvm_gc_iter_* + + gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].iter; + + iter(f, p, arg); +} + +static pvm_object_storage_t** collect_unmarked(char* start, long long shift) { + char* end = (char*)start + N_OBJMEM_PAGES * 4096L; + char* curr; + + int freed = 0; + for (curr = start; curr < end; curr += ((pvm_object_storage_t*)curr)->_ah.exact_size) { + pvm_object_storage_t* p = (pvm_object_storage_t*)curr; + assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); + + if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) //touch not accessed but allocated objects + { + ++freed; + } + } + + pvm_object_storage_t** to_free = ph_calloc((freed + 1), sizeof(pvm_object_storage_t*)); + + int i = 0; + for (curr = start; curr < end; curr += ((pvm_object_storage_t*)curr)->_ah.exact_size) { + pvm_object_storage_t* p = (pvm_object_storage_t*)curr; + assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); + + if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) //touch not accessed but allocated objects + { + to_free[i++] = shift_ptr(p, -shift); + } + } + + to_free[i] = 0; + return to_free; +} + +static int free_unmarked(pvm_object_storage_t** to_free) { + int i = 0; + while (to_free[i] != 0) { + pvm_object_storage_t* p = to_free[i]; + + if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) + { + // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? + gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; + + if (func != 0) + func(p); + + // should run ref_dec for children? + } + + p->_ah.refCount = 0; // free now + p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now + } +} diff --git a/src/phantom/vm/vm.cmake b/src/phantom/vm/vm.cmake index bffae2f3b..4f83dec52 100644 --- a/src/phantom/vm/vm.cmake +++ b/src/phantom/vm/vm.cmake @@ -33,6 +33,7 @@ set (PHANTOM_PVM_SOURCE internal.c bulk.c gc.c + gc_on_snap.c wpaint.c syscall_net.c directory.c From 886579149ee815430a911668177024420715a2e8 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Fri, 3 May 2024 16:07:43 +0200 Subject: [PATCH 03/14] fix npe in connection for gc --- src/phantom/vm/create.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index b2445c55c..eda512773 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -1150,6 +1150,10 @@ void pvm_gc_iter_connection(gc_iterator_call_t func, pvm_object_t os, void *arg pvm_object_t ot; //ot.interface = 0; + // TODO: find out why it could be 0? fix? + if (da->owner == 0) { + return; + } ot = (void *) (((addr_t)da->owner)-DA_OFFSET()); long long shift = *(long long*)arg; gc_fcall( func, arg, shift_ptr(ot, shift) ); From 3594c6edcd890da0fc96b46d27377a48f9867e0d Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Mon, 6 May 2024 11:00:02 +0200 Subject: [PATCH 04/14] refactor --- src/phantom/isomem/main.c | 4 +- src/phantom/vm/create.c | 85 +++++++++++++++---------------------- src/phantom/vm/gc_on_snap.c | 20 +++++---- 3 files changed, 49 insertions(+), 60 deletions(-) diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index ad07f47a1..7e671b962 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -580,7 +580,7 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) //init_wins(u_int32_t ip_addr); { - hal_sleep_msec(2000); + hal_sleep_msec(10000); ph_printf("\ndumpo:\n"); pvm_object_t p = get_root_object_storage(); @@ -595,7 +595,7 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) ph_printf("\nGC started:\n"); phantom_snapper_wait_4_threads(); - run_gc(); + run_gc(); ph_printf("\nGC end:\n"); phantom_snapper_reenable_threads(); } diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index eda512773..c6f139824 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -43,10 +43,6 @@ * **/ -static pvm_object_t shift_ptr( pvm_object_t o, long long shift ) -{ - return (pvm_object_t)( (char*)o + shift ); -} static pvm_object_t pvm_object_create_fixed( pvm_object_t object_class ) @@ -369,12 +365,11 @@ void pvm_gc_iter_page(gc_iterator_call_t func, pvm_object_t os, void *arg) { int n_slots = (os->_da_size) / sizeof(pvm_object_t ); pvm_object_t * data_area = (pvm_object_t *)&(os->da); - long long shift = *(long long*)arg; int i; for( i = 0; i < n_slots; i++ ) { - func( shift_ptr(data_area[i], shift), arg ); + func( data_area[i], arg ); } } @@ -416,12 +411,11 @@ void pvm_internal_init_call_frame(pvm_object_t os) void pvm_gc_iter_call_frame(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_call_frame *da = (struct data_area_4_call_frame *)&(os->da); - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->this_object, shift) ); - gc_fcall( func, arg, shift_ptr(da->prev, shift) ); // FYI - shall never be followed in normal situation, must contain zero data ptr if being considered by refcount - gc_fcall( func, arg, shift_ptr(da->istack, shift) ); - gc_fcall( func, arg, shift_ptr(da->ostack, shift) ); - gc_fcall( func, arg, shift_ptr(da->estack, shift) ); + gc_fcall( func, arg, da->this_object ); + gc_fcall( func, arg, da->prev ); // FYI - shall never be followed in normal situation, must contain zero data ptr if being considered by refcount + gc_fcall( func, arg, da->istack ); + gc_fcall( func, arg, da->ostack ); + gc_fcall( func, arg, da->estack ); } @@ -533,17 +527,15 @@ void pvm_internal_init_class(pvm_object_t os) void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_class *da = (struct data_area_4_class *)&(os->da); - long long shift = *(long long*)arg; + gc_fcall( func, arg, da->object_default_interface ); + gc_fcall( func, arg, da->class_name ); + gc_fcall( func, arg, da->class_parent ); - gc_fcall( func, arg, shift_ptr(da->object_default_interface, shift) ); - gc_fcall(func, arg, shift_ptr(da->class_name, shift)); - gc_fcall(func, arg, shift_ptr(da->class_parent, shift)); + gc_fcall( func, arg, da->static_vars ); - gc_fcall(func, arg, shift_ptr(da->static_vars, shift)); - - gc_fcall(func, arg, shift_ptr(da->ip2line_maps, shift)); - gc_fcall(func, arg, shift_ptr(da->method_names, shift)); - gc_fcall(func, arg, shift_ptr(da->field_names, shift)); + gc_fcall( func, arg, da->ip2line_maps ); + gc_fcall( func, arg, da->method_names ); + gc_fcall( func, arg, da->field_names ); } @@ -579,10 +571,9 @@ void pvm_internal_init_thread(pvm_object_t os) void pvm_gc_iter_thread(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_thread *da = (struct data_area_4_thread *)&(os->da); - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->call_frame, shift) ); - gc_fcall( func, arg, shift_ptr(da->owner, shift) ); - gc_fcall( func, arg, shift_ptr(da->environment, shift) ); + gc_fcall( func, arg, da->call_frame ); + gc_fcall( func, arg, da->owner ); + gc_fcall( func, arg, da->environment ); } @@ -616,9 +607,8 @@ void pvm_internal_init_array(pvm_object_t os) void pvm_gc_iter_array(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_array *da = (struct data_area_4_array *)&(os->da); - long long shift = *(long long*)arg; if(da->page != 0) - gc_fcall( func, arg, shift_ptr(da->page, shift) ); + gc_fcall( func, arg, da->page ); } @@ -658,15 +648,13 @@ void pvm_gc_iter_mutex(gc_iterator_call_t func, pvm_object_t os, void *arg) //pvm_spin_init( &da->pvm_lock ); // in_method = 0; - long long shift = *(long long*)arg; - - gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); + gc_fcall( func, arg, da->waiting_threads_array ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); - gc_fcall( func, arg, shift_ptr(pvm_da_to_object(da->owner_thread), shift) ); + gc_fcall( func, arg, pvm_da_to_object(da->owner_thread) ); } @@ -684,8 +672,8 @@ void pvm_gc_iter_cond(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_cond * da = (struct data_area_4_cond *)os->da; //int i; - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); + + gc_fcall( func, arg, da->waiting_threads_array ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); @@ -709,13 +697,12 @@ void pvm_gc_iter_sema(gc_iterator_call_t func, pvm_object_t os, void *arg) struct data_area_4_sema * da = (struct data_area_4_sema *)os->da; //int i; - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->waiting_threads_array, shift) ); + gc_fcall( func, arg, da->waiting_threads_array ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); - gc_fcall( func, arg, shift_ptr(pvm_da_to_object(da->owner_thread), shift) ); + gc_fcall( func, arg, pvm_da_to_object(da->owner_thread) ); } @@ -763,9 +750,8 @@ void pvm_internal_init_bitmap(pvm_object_t os) void pvm_gc_iter_bitmap(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_bitmap *da = (struct data_area_4_bitmap *)&(os->da); - long long shift = *(long long*)arg; if(da->image != 0) - gc_fcall( func, arg, shift_ptr(da->image, shift) ); + gc_fcall( func, arg, da->image ); } @@ -797,8 +783,7 @@ void pvm_gc_iter_closure(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_closure * da = (struct data_area_4_closure *)os->da; //if(da->image.object != 0) - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->object, shift) ); + gc_fcall( func, arg, da->object ); } @@ -961,9 +946,9 @@ void pvm_internal_init_window(pvm_object_t os) void pvm_gc_iter_window(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_window *da = (struct data_area_4_window *)os->da; - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(da->connector, shift) ); - gc_fcall( func, arg, shift_ptr(da->o_pixels, shift) ); + + gc_fcall( func, arg, da->connector ); + gc_fcall( func, arg, da->o_pixels ); } @@ -1113,9 +1098,9 @@ pvm_object_t pvm_create_directory_object(void) void pvm_gc_iter_directory(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_directory *da = (struct data_area_4_directory *)os->da; - long long shift = *((long long*)arg); - gc_fcall( func, arg, shift_ptr(da->keys, shift) ); - gc_fcall( func, arg, shift_ptr(da->values, shift) ); + + gc_fcall( func, arg, da->keys ); + gc_fcall( func, arg, da->values ); } @@ -1155,10 +1140,10 @@ void pvm_gc_iter_connection(gc_iterator_call_t func, pvm_object_t os, void *arg return; } ot = (void *) (((addr_t)da->owner)-DA_OFFSET()); - long long shift = *(long long*)arg; - gc_fcall( func, arg, shift_ptr(ot, shift) ); - gc_fcall( func, arg, shift_ptr(da->p_kernel_state_object, shift) ); - gc_fcall( func, arg, shift_ptr(da->callback, shift) ); + + gc_fcall( func, arg, ot ); + gc_fcall( func, arg, da->p_kernel_state_object ); + gc_fcall( func, arg, da->callback ); } diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 90a172911..01202d78b 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -128,15 +128,19 @@ void run_gc_on_snap() { } long long shift = snapshot - (char*)get_pvm_object_space_start(); + ph_printf("snapshot is loaded\n"); + ph_printf("shift: %d", shift); + ph_printf("snapshot addr: %p\n", snapshot); + dumpo((addr_t)snapshot); - mark_tree((pvm_object_storage_t*)snapshot, shift); - pvm_object_storage_t** to_free = collect_unmarked(snapshot, shift); +// mark_tree((pvm_object_storage_t*)snapshot, shift); +// pvm_object_storage_t** to_free = collect_unmarked(snapshot, shift); // Second pass - linear walk to free unused objects. - int freed = free_unmarked(to_free); - - if (freed > 0) - ph_printf("\ngc: %i objects freed\n", freed); +// int freed = free_unmarked(to_free); +// +// if (freed > 0) +// ph_printf("\ngc: %i objects freed\n", freed); } static void mark_tree(pvm_object_storage_t* p, long long shift) @@ -160,7 +164,7 @@ static void mark_tree_o(pvm_object_t o, void* arg) { return; if (o->_ah.gc_flags != gc_flags_last_generation) - mark_tree(o, shift); + mark_tree(shift_ptr(o, shift), shift); //if (o.interface->_ah.gc_flags != gc_flags_last_generation) mark_tree( o.interface ); } @@ -181,7 +185,7 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* p, v for (i = 0; i < da_po_limit(p); i++) { - f(shift_ptr(da_po_ptr(p->da)[i], shift), arg); + f(da_po_ptr(p->da)[i], arg); } return; } From af96ab0550701289355a005750682d4816cf40b1 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Mon, 6 May 2024 21:30:12 +0200 Subject: [PATCH 05/14] unresolvable exception --- src/phantom/isomem/main.c | 6 +- src/phantom/vm/gc_on_snap.c | 118 +++++++++++++++++++++--------------- 2 files changed, 72 insertions(+), 52 deletions(-) diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index 7e671b962..6be599316 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -580,9 +580,9 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) //init_wins(u_int32_t ip_addr); { - hal_sleep_msec(10000); + hal_sleep_msec(2000); - ph_printf("\ndumpo:\n"); + ph_printf("\nsleep done:\n"); pvm_object_t p = get_root_object_storage(); dumpo(p); @@ -595,7 +595,7 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) ph_printf("\nGC started:\n"); phantom_snapper_wait_4_threads(); - run_gc(); + run_gc_on_snap(); ph_printf("\nGC end:\n"); phantom_snapper_reenable_threads(); } diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 01202d78b..06534147b 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -31,6 +31,8 @@ #include +static long long shift; + static pvm_object_t shift_ptr(pvm_object_t o, long long shift) { return (pvm_object_t)((char*)o + shift); @@ -68,12 +70,13 @@ static char* load_snap() { disk_page_no_t curr_block; snapshot = ph_calloc(page_count, PAGE_SIZE); + char* snapshot_seeker = snapshot; unsigned int np; for (np = 0; np < page_count; np++) { if (!pagelist_read_seq(&loader, &curr_block)) { ph_printf("\n!!! Incomplete pagelist !!!\n"); - //panic("Incomplete pagelist\n"); + snapshot = 0; break; } @@ -89,8 +92,8 @@ static char* load_snap() { panic("failed to load snapshot in gc\n"); } - ph_memcpy(snapshot, disk_page_io_data(&sb), PAGE_SIZE); - snapshot += PAGE_SIZE; + ph_memcpy(snapshot_seeker, disk_page_io_data(&sb), PAGE_SIZE); + snapshot_seeker += PAGE_SIZE; } pagelist_finish(&loader); @@ -99,9 +102,9 @@ static char* load_snap() { return snapshot; } -static void mark_tree(pvm_object_storage_t *p, long long shift); +static void mark_tree(pvm_object_storage_t *p); -static pvm_object_storage_t **collect_unmarked(char *start, long long shift); +static pvm_object_storage_t **collect_unmarked(char *start); static int free_unmarked(pvm_object_storage_t **to_free); @@ -127,65 +130,81 @@ void run_gc_on_snap() { return; } - long long shift = snapshot - (char*)get_pvm_object_space_start(); + shift = snapshot - (char*)get_pvm_object_space_start(); + ph_printf("real space start: %p\n", get_pvm_object_space_start()); + ph_printf("real space end: %p\n", get_pvm_object_space_end()); ph_printf("snapshot is loaded\n"); - ph_printf("shift: %d", shift); + ph_printf("shift: %d\n", shift); ph_printf("snapshot addr: %p\n", snapshot); - dumpo((addr_t)snapshot); + ph_printf("reference start marker: %d\n", PVM_OBJECT_START_MARKER); -// mark_tree((pvm_object_storage_t*)snapshot, shift); -// pvm_object_storage_t** to_free = collect_unmarked(snapshot, shift); + mark_tree((pvm_object_storage_t*)snapshot); + pvm_object_storage_t** to_free = collect_unmarked(snapshot); // Second pass - linear walk to free unused objects. -// int freed = free_unmarked(to_free); -// -// if (freed > 0) -// ph_printf("\ngc: %i objects freed\n", freed); + int freed = free_unmarked(to_free); + + if (freed > 0) + ph_printf("\ngc: %i objects freed\n", freed); } -static void mark_tree(pvm_object_storage_t* p, long long shift) +static void mark_tree(pvm_object_storage_t* obj_in_snap) { ph_printf("\nGC: process another object\n"); - p->_ah.gc_flags = gc_flags_last_generation; // set - - assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); - assert(p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); - + ph_printf("Flags: '"); + print_object_flags(obj_in_snap); + ph_printf("'\n"); + printf("object class:\n"); + dumpo(obj_in_snap->_class); + + ph_printf("p: %p, p->ah: %p\n", obj_in_snap, &obj_in_snap->_ah); + obj_in_snap->_ah.gc_flags = gc_flags_last_generation; // set + + ph_printf("assert start marker and allocated\n"); + ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); + + assert(obj_in_snap->_ah.object_start_marker == PVM_OBJECT_START_MARKER); + assert(obj_in_snap->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); + + ph_printf("check if childfree\n"); // Fast skip if no children - - if (!(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE)) { - gc_process_children(mark_tree_o, p, &shift); + if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE)) { + ph_printf("not childfree, call gc_process_children\n"); + ph_printf("shift addr: %p\n", &shift); + ph_printf("p addr: %p\n", &obj_in_snap); + gc_process_children(mark_tree_o, obj_in_snap, 0); } } -static void mark_tree_o(pvm_object_t o, void* arg) { - long long shift = *((long long*)arg); - - if (o == 0) // Don't try to process null objects +static void mark_tree_o(pvm_object_t obj_in_pvm, void* arg) { + if (obj_in_pvm == 0) // Don't try to process null objects return; - if (o->_ah.gc_flags != gc_flags_last_generation) - mark_tree(shift_ptr(o, shift), shift); + pvm_object_t obj_in_snap = shift_ptr(obj_in_pvm, shift); + + if (obj_in_snap->_ah.gc_flags != gc_flags_last_generation) + mark_tree(obj_in_snap); //if (o.interface->_ah.gc_flags != gc_flags_last_generation) mark_tree( o.interface ); } -static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* p, void* arg) { - f(p->_class, arg); - - long long shift = *((long long*)arg); +static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_in_snap, void* arg) { + ph_printf("GC: process children\n"); + f(obj_in_snap->_class, arg); // Fast skip if no children - done! //if( p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE ) // return; // plain non internal objects - - if (!(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) + if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) { + ph_printf("External object, normal iter\n"); unsigned i; - for (i = 0; i < da_po_limit(p); i++) + for (i = 0; i < da_po_limit(obj_in_snap); i++) { - f(da_po_ptr(p->da)[i], arg); + f(da_po_ptr(obj_in_snap->da)[i], arg); } return; } @@ -193,13 +212,13 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* p, v // We're here if object is internal. // Now find and call class-specific function: pvm_gc_iter_* + ph_printf("Internal object, get iter method\n"); + gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(shift_ptr(obj_in_snap->_class, shift), class)->sys_table_id].iter; - gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].iter; - - iter(f, p, arg); + iter(f, obj_in_snap, arg); } -static pvm_object_storage_t** collect_unmarked(char* start, long long shift) { +static pvm_object_storage_t** collect_unmarked(char* start) { char* end = (char*)start + N_OBJMEM_PAGES * 4096L; char* curr; @@ -235,19 +254,20 @@ static int free_unmarked(pvm_object_storage_t** to_free) { int i = 0; while (to_free[i] != 0) { pvm_object_storage_t* p = to_free[i]; + ph_printf("Freeing object %p\n", p); - if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) - { - // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? - gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; + // if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) + // { + // // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? + // gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; - if (func != 0) - func(p); + // if (func != 0) + // func(p); - // should run ref_dec for children? - } + // // should run ref_dec for children? + // } - p->_ah.refCount = 0; // free now - p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now + // p->_ah.refCount = 0; // free now + // p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now } } From 5f552a61df5b520252f7bf5796f13ed02a71cb07 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Wed, 15 May 2024 14:25:16 +0200 Subject: [PATCH 06/14] dump: collection on snapshot --- src/genode_env/disk_backend.h | 4 +-- src/genode_env/main.cc | 7 +++- src/include/vm/alloc.h | 2 +- src/phantom/isomem/main.c | 10 +++--- src/phantom/isomem/vm_map.c | 1 + src/phantom/vm/create.c | 1 + src/phantom/vm/gc_on_snap.c | 34 ++++++++++--------- .../src/ru.dz/ru.dz.phantom.system.shell.ph | 8 ++++- 8 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/genode_env/disk_backend.h b/src/genode_env/disk_backend.h index ab392fd1c..61528da59 100644 --- a/src/genode_env/disk_backend.h +++ b/src/genode_env/disk_backend.h @@ -39,7 +39,7 @@ class Phantom::Disk_backend Genode::Env &_env; Genode::Heap &_heap; - Genode::Entrypoint _ep{_env, 2*1024*sizeof(long) , "disk_ep", Genode::Affinity::Location()}; + Genode::Entrypoint _ep{_env, 30*1024*sizeof(long) , "disk_ep", Genode::Affinity::Location()}; Genode::Allocator_avl _block_alloc{&_heap}; struct DJob : Block::Connection::Job @@ -315,4 +315,4 @@ class Phantom::Disk_backend // } }; -#endif \ No newline at end of file +#endif diff --git a/src/genode_env/main.cc b/src/genode_env/main.cc index f2e76e79c..bbfda8c12 100644 --- a/src/genode_env/main.cc +++ b/src/genode_env/main.cc @@ -36,6 +36,11 @@ void setup_adapters(Env &env) Phantom::main_obj = &local_main; } +Genode::size_t Component::stack_size() { + return 60 * 1024 * sizeof(long); +} + + void test_adapters() { log("Checking if main_obj is initialized"); @@ -209,4 +214,4 @@ void Component::construct(Env &env) // int main() // { // log("What are we doing here???"); -// } \ No newline at end of file +// } diff --git a/src/include/vm/alloc.h b/src/include/vm/alloc.h index 137d88d2c..14b58c250 100755 --- a/src/include/vm/alloc.h +++ b/src/include/vm/alloc.h @@ -44,7 +44,7 @@ void debug_catch_object(const char *msg, pvm_object_storage_t *p); // gc void run_gc(void); -void run_gc_on_snap(); +void run_gc_on_snap(void); // Make sure this object won't be deleted with refcount dec // used on sys global objects diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index 6be599316..c1669c980 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -593,11 +593,11 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) } - ph_printf("\nGC started:\n"); - phantom_snapper_wait_4_threads(); - run_gc_on_snap(); - ph_printf("\nGC end:\n"); - phantom_snapper_reenable_threads(); + // ph_printf("\nGC started:\n"); + // phantom_snapper_wait_4_threads(); + // run_gc_on_snap(); + // ph_printf("\nGC end:\n"); + // phantom_snapper_reenable_threads(); } ph_printf("\n\x1b[33m\x1b[44mPhantom " PHANTOM_VERSION_STR " (SVN rev %s) @ %s started\x1b[0m\n\n", svn_version(), phantom_uname.machine ); diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index 6babe0c00..add06c578 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -1657,6 +1657,7 @@ static int request_snap_flag = 0; static int seconds_between_snaps = 5; static void free_old_snapshot() { + return; if (pager_superblock_ptr()->snap_to_free == 0) return; disk_page_no_t to_free = pager_superblock_ptr()->snap_to_free; diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index c6f139824..e9af059e0 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -526,6 +526,7 @@ void pvm_internal_init_class(pvm_object_t os) void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void *arg) { + ph_printf("iter class called on %p\n", os); struct data_area_4_class *da = (struct data_area_4_class *)&(os->da); gc_fcall( func, arg, da->object_default_interface ); gc_fcall( func, arg, da->class_name ); diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 06534147b..e8a5673b4 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -81,7 +81,8 @@ static char* load_snap() { } if (curr_block == 0) { - continue; + snapshot_seeker += PAGE_SIZE; + continue; // change } disk_page_io sb; @@ -154,15 +155,15 @@ static void mark_tree(pvm_object_storage_t* obj_in_snap) ph_printf("Flags: '"); print_object_flags(obj_in_snap); ph_printf("'\n"); - printf("object class:\n"); - dumpo(obj_in_snap->_class); + // ph_printf("object class:\n"); + // dumpo(obj_in_snap->_class); + + ph_printf("p: %p, p->ah: %p, p->da: %p\n", obj_in_snap, &obj_in_snap->_ah, obj_in_snap->da); + ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); - ph_printf("p: %p, p->ah: %p\n", obj_in_snap, &obj_in_snap->_ah); obj_in_snap->_ah.gc_flags = gc_flags_last_generation; // set ph_printf("assert start marker and allocated\n"); - ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); - assert(obj_in_snap->_ah.object_start_marker == PVM_OBJECT_START_MARKER); assert(obj_in_snap->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); @@ -256,18 +257,19 @@ static int free_unmarked(pvm_object_storage_t** to_free) { pvm_object_storage_t* p = to_free[i]; ph_printf("Freeing object %p\n", p); - // if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) - // { - // // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? - // gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; + if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) + { + // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? + gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; - // if (func != 0) - // func(p); + if (func != 0) + func(p); - // // should run ref_dec for children? - // } + // should run ref_dec for children? + } - // p->_ah.refCount = 0; // free now - // p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now + p->_ah.refCount = 0; // free now + p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now + i++; } } diff --git a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph index 27ca1739e..4a33074b2 100755 --- a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph +++ b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph @@ -54,7 +54,7 @@ class shell extends runnable //var mtx : .internal.mutex; - var demo : .ru.dz.demo.wasm; + //var demo : .ru.dz.demo.wasm; // var demo : .ru.dz.demo.start; // var demo : .ru.dz.phantom.persistence_test; /* @@ -114,10 +114,16 @@ class shell extends runnable stat_conn = new .internal.connection(); stat_conn.connect("stt:"); +<<<<<<< HEAD // demo = new .ru.dz.demo.start(); demo = new .ru.dz.demo.wasm(); // demo = new .ru.dz.phantom.persistence_test(); demo.run(console); +======= + //demo = new .ru.dz.demo.start(); + //demo = new .ru.dz.demo.wasm(); + //demo.run(console); +>>>>>>> 925597fc (dump: collection on snapshot) while(1) { From 2f917d09facc4b8b8eda16cf17d9afba43a55e47 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Thu, 16 May 2024 01:46:02 +0200 Subject: [PATCH 07/14] try to preserve snap during loading --- src/include/phantom_disk.h | 3 +++ src/phantom/isomem/fsck.c | 5 +++-- src/phantom/isomem/pager.c | 7 +++++++ src/phantom/isomem/pager.h | 3 ++- src/phantom/isomem/vm_map.c | 22 ++++++++++++++++++---- src/phantom/vm/gc_on_snap.c | 10 ++++++++++ src/run/img/phantom.superblock | Bin 1024 -> 1024 bytes 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/include/phantom_disk.h b/src/include/phantom_disk.h index 0d1dc4402..f292980b0 100755 --- a/src/include/phantom_disk.h +++ b/src/include/phantom_disk.h @@ -102,6 +102,9 @@ typedef struct phantom_disk_superblock disk_page_no_t snap_to_free; // snap that is yet to free + disk_page_no_t snap_reading; + disk_page_no_t snap_already_read; + u_int32_t magic2; // 32 bits - DISK_STRUCT_MAGIC_SUPER_2 disk_page_no_t boot_list; // List of blocks with bootloader image or 0. diff --git a/src/phantom/isomem/fsck.c b/src/phantom/isomem/fsck.c index 8e6a9dba5..7795fac7e 100755 --- a/src/phantom/isomem/fsck.c +++ b/src/phantom/isomem/fsck.c @@ -596,7 +596,8 @@ static void free_blocklist_page_snap_worker(disk_page_no_t toFree, int flags) void phantom_free_snap( disk_page_no_t old_snap_start, disk_page_no_t curr_snap_start, - disk_page_no_t new_snap_start + disk_page_no_t new_snap_start, + disk_page_no_t snap_reading ) { if( old_snap_start == 0 ) @@ -611,7 +612,7 @@ void phantom_free_snap( fsck_list_justadd_as_free( old_snap_start ); fsck_list_justadd_as_used( curr_snap_start ); fsck_list_justadd_as_used( new_snap_start ); - + fsck_list_justadd_as_used( snap_reading ); // go through list, free pages that are finally free in map iterate_map(free_snap_worker, MAP_FREE); diff --git a/src/phantom/isomem/pager.c b/src/phantom/isomem/pager.c index 77b4e6e03..6abb59733 100755 --- a/src/phantom/isomem/pager.c +++ b/src/phantom/isomem/pager.c @@ -205,6 +205,13 @@ void partition_pager_init(phantom_disk_partition_t *p) if (freed_list_blocks == NULL) panic("Out of memory"); #endif + { + phantom_disk_format(&superblock, 0x50000, "Unnamed Phantom System"); + phantom_sync_write_block(pp, &superblock, 0, 1); + ph_printf("SUPERBLOCK WRITTEN"); + hal_sleep_msec(60 * 1000); + } + SHOW_FLOW0( 1, "Pager get superblock" ); pager_get_superblock(); diff --git a/src/phantom/isomem/pager.h b/src/phantom/isomem/pager.h index 00b36ca26..7672cdf6a 100755 --- a/src/phantom/isomem/pager.h +++ b/src/phantom/isomem/pager.h @@ -131,7 +131,8 @@ void phantom_fsck(int do_rebuild ); void phantom_free_snap( disk_page_no_t old_snap_start, disk_page_no_t curr_snap_start, - disk_page_no_t new_snap_start + disk_page_no_t new_snap_start, + disk_page_no_t snap_reading_start ); diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index add06c578..40754898f 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -1657,15 +1657,29 @@ static int request_snap_flag = 0; static int seconds_between_snaps = 5; static void free_old_snapshot() { - return; - if (pager_superblock_ptr()->snap_to_free == 0) return; - disk_page_no_t to_free = pager_superblock_ptr()->snap_to_free; + disk_page_no_t snap_reading = pager_superblock_ptr()->snap_reading; + + if (to_free == 0 || to_free == snap_reading) return; + disk_page_no_t actual1 = pager_superblock_ptr()->prev_snap; disk_page_no_t actual2 = pager_superblock_ptr()->last_snap; + disk_page_no_t actual3 = (snap_reading == actual1 || snap_reading == actual2) ? 0 : snap_reading; - phantom_free_snap( to_free, actual1, actual2 ); + phantom_free_snap( to_free, actual1, actual2, actual3 ); + pager_superblock_ptr()->snap_to_free = 0; + pager_fence(); + pager_update_superblock(); + + disk_page_no_t snap_already_read = pager_superblock_ptr()->snap_already_read; + if (snap_already_read != 0) { + if (snap_already_read != to_free) { + phantom_free_snap(snap_already_read, actual1, actual2, actual3); + } + + pager_superblock_ptr()->snap_already_read = 0; + } // Force all io to complete BEFORE updating superblock pager_fence(); diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index e8a5673b4..b2f1b0378 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -61,6 +61,13 @@ static char* load_snap() { hal_printf("\n!!! No pagelist to load !!!\n"); } else { + if (pager_superblock_ptr()->snap_already_read != 0) { + ph_printf("\n!!! Previously loaded snapshot not cleaned yet !!!\n"); + return snapshot; + } + + pager_superblock_ptr()->snap_reading = snap_start; + hal_printf("Loading pagelist from %d...\n", snap_start); pagelist loader; @@ -98,6 +105,9 @@ static char* load_snap() { } pagelist_finish(&loader); + + pager_superblock_ptr()->snap_reading = 0; + pager_superblock_ptr()->snap_already_read = snap_start; } return snapshot; diff --git a/src/run/img/phantom.superblock b/src/run/img/phantom.superblock index 52433ea14eeb2aa7cfaaf722a1bcf5a50b50f679..ae51bd357534d6c770f9e6b450fee7af8c380d27 100644 GIT binary patch literal 1024 zcmb1L!+3z1fsx@NF9QRE01!g~gvkn&fq?%o2?F%mwHr1NP(pX<(7e3F+|(3>fQ-bv zlKfnS;L75X)LgndW7NW76aqJHrGtIb@KW9Z#L!b`24@u*A0|HmD$jnG2`qmB%3psA zl@B%yiHP{Y#R$@{Vje$O^n{`iSii$7h<)NLkgTZy)w4ia2+D#`Oi&&Rl;%LAp Date: Sat, 17 Aug 2024 14:57:02 +0200 Subject: [PATCH 08/14] gc on snap fixes --- src/phantom/isomem/main.c | 29 +++++++++++++++-------------- src/phantom/isomem/pager.c | 7 ------- src/phantom/vm/create.c | 19 ++++++++++--------- src/phantom/vm/gc_on_snap.c | 1 + 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index c1669c980..aa86dac21 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -580,24 +580,25 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) //init_wins(u_int32_t ip_addr); { - hal_sleep_msec(2000); + // hal_sleep_msec(2000); - ph_printf("\nsleep done:\n"); - pvm_object_t p = get_root_object_storage(); - dumpo(p); + // ph_printf("\nsleep done:\n"); + // pvm_object_t p = get_root_object_storage(); + // dumpo(p); - unsigned i; - - for (i = 0; i < da_po_limit(p); i++) { - dumpo(da_po_ptr(p->da)[i]); - } + // unsigned i; + // for (i = 0; i < da_po_limit(p); i++) { + // dumpo(da_po_ptr(p->da)[i]); + // } - // ph_printf("\nGC started:\n"); - // phantom_snapper_wait_4_threads(); - // run_gc_on_snap(); - // ph_printf("\nGC end:\n"); - // phantom_snapper_reenable_threads(); + ph_printf("\nGC started:\n"); + // pvm_object_t obj = (void*)0x80a55740; + // dumpo(obj); + phantom_snapper_wait_4_threads(); + run_gc_on_snap(); + ph_printf("\nGC end:\n"); + phantom_snapper_reenable_threads(); } ph_printf("\n\x1b[33m\x1b[44mPhantom " PHANTOM_VERSION_STR " (SVN rev %s) @ %s started\x1b[0m\n\n", svn_version(), phantom_uname.machine ); diff --git a/src/phantom/isomem/pager.c b/src/phantom/isomem/pager.c index 6abb59733..77b4e6e03 100755 --- a/src/phantom/isomem/pager.c +++ b/src/phantom/isomem/pager.c @@ -205,13 +205,6 @@ void partition_pager_init(phantom_disk_partition_t *p) if (freed_list_blocks == NULL) panic("Out of memory"); #endif - { - phantom_disk_format(&superblock, 0x50000, "Unnamed Phantom System"); - phantom_sync_write_block(pp, &superblock, 0, 1); - ph_printf("SUPERBLOCK WRITTEN"); - hal_sleep_msec(60 * 1000); - } - SHOW_FLOW0( 1, "Pager get superblock" ); pager_get_superblock(); diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index e9af059e0..a7a1dd3c8 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -524,19 +524,20 @@ void pvm_internal_init_class(pvm_object_t os) } -void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void *arg) +void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void* arg) { ph_printf("iter class called on %p\n", os); - struct data_area_4_class *da = (struct data_area_4_class *)&(os->da); - gc_fcall( func, arg, da->object_default_interface ); - gc_fcall( func, arg, da->class_name ); - gc_fcall( func, arg, da->class_parent ); + struct data_area_4_class* da = (struct data_area_4_class*)&(os->da); + gc_fcall(func, arg, da->object_default_interface); + gc_fcall(func, arg, da->class_name); + gc_fcall(func, arg, da->class_parent); - gc_fcall( func, arg, da->static_vars ); + gc_fcall(func, arg, da->static_vars); - gc_fcall( func, arg, da->ip2line_maps ); - gc_fcall( func, arg, da->method_names ); - gc_fcall( func, arg, da->field_names ); + gc_fcall(func, arg, da->ip2line_maps); + gc_fcall(func, arg, da->method_names); + gc_fcall(func, arg, da->field_names); + gc_fcall(func, arg, da->const_pool); } diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index b2f1b0378..3a20c7ddb 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -81,6 +81,7 @@ static char* load_snap() { unsigned int np; for (np = 0; np < page_count; np++) { + ph_printf("np: %d/%d\n", np, page_count); if (!pagelist_read_seq(&loader, &curr_block)) { ph_printf("\n!!! Incomplete pagelist !!!\n"); snapshot = 0; From 04ca2142acad8668a8135ffe1af51e8ec55982f3 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Thu, 22 Aug 2024 23:44:44 +0200 Subject: [PATCH 09/14] fixing bugs, dump --- src/phantom/isomem/fsck.c | 62 ++++++++++++++++++++--------- src/phantom/isomem/genode_threads.c | 3 +- src/phantom/isomem/main.c | 10 +++-- src/phantom/isomem/vm_map.c | 23 ++++------- src/phantom/vm/backtrace.c | 4 +- src/phantom/vm/create.c | 1 + src/phantom/vm/gc_on_snap.c | 31 ++++++++------- src/phantom/vm/object.c | 19 ++++++--- src/phantom/vm/sys/i_wasm.c | 14 ++++++- src/phantom/vm/sys/i_wasm.h | 2 + src/phantom/vm/wasm-micro-runtime | 2 +- 11 files changed, 108 insertions(+), 63 deletions(-) diff --git a/src/phantom/isomem/fsck.c b/src/phantom/isomem/fsck.c index 7795fac7e..09c9a32f4 100755 --- a/src/phantom/isomem/fsck.c +++ b/src/phantom/isomem/fsck.c @@ -593,36 +593,60 @@ static void free_blocklist_page_snap_worker(disk_page_no_t toFree, int flags) pager_free_blocklist_page_locked( toFree ); } -void phantom_free_snap( - disk_page_no_t old_snap_start, - disk_page_no_t curr_snap_start, - disk_page_no_t new_snap_start, - disk_page_no_t snap_reading - ) -{ - if( old_snap_start == 0 ) - { - SHOW_FLOW0( 0, "*** No old snap, skip list deletion ***"); - return; - } - SHOW_FLOW0( 0, "*** freeing old snap ***"); +void phantom_free_snap( + disk_page_no_t* to_free_arr, int to_free_arr_len, + disk_page_no_t* actual_arr, int actual_arr_len +) { fsck_create_map(); - fsck_list_justadd_as_free( old_snap_start ); - fsck_list_justadd_as_used( curr_snap_start ); - fsck_list_justadd_as_used( new_snap_start ); - fsck_list_justadd_as_used( snap_reading ); + for (int i = 0; i < to_free_arr_len; i++) { + if (to_free_arr[i] != 0) + fsck_list_justadd_as_free(to_free_arr[i]); + } + + for (int i = 0; i < actual_arr_len; i++) { + if (actual_arr[i] != 0) + fsck_list_justadd_as_used(actual_arr[i]); + } - // go through list, free pages that are finally free in map iterate_map(free_snap_worker, MAP_FREE); iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE); pager_commit_active_free_list(); fsck_delete_map(); - } +// void phantom_free_snap( +// disk_page_no_t old_snap_start, +// disk_page_no_t curr_snap_start, +// disk_page_no_t new_snap_start, +// disk_page_no_t snap_reading +// ) +// { +// if( old_snap_start == 0 ) +// { +// SHOW_FLOW0( 0, "*** No old snap, skip list deletion ***"); +// return; +// } + +// SHOW_FLOW0( 0, "*** freeing old snap ***"); +// fsck_create_map(); + +// fsck_list_justadd_as_free( old_snap_start ); +// fsck_list_justadd_as_used( curr_snap_start ); +// fsck_list_justadd_as_used( new_snap_start ); +// fsck_list_justadd_as_used( snap_reading ); + +// // go through list, free pages that are finally free in map +// iterate_map(free_snap_worker, MAP_FREE); +// iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE); +// pager_commit_active_free_list(); + +// fsck_delete_map(); + +// } + diff --git a/src/phantom/isomem/genode_threads.c b/src/phantom/isomem/genode_threads.c index 291f7fe71..b13a3fbf0 100644 --- a/src/phantom/isomem/genode_threads.c +++ b/src/phantom/isomem/genode_threads.c @@ -65,6 +65,7 @@ phantom_thread_t *get_current_thread() tid_t get_current_tid(void) { + ph_printf("get_current_tid\n"); _stub_print(); return (int)pthread_self(); } @@ -191,4 +192,4 @@ errno_t t_set_snapper_flag(void) // // Threads do not work in this mode // } -#endif \ No newline at end of file +#endif diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index aa86dac21..b7d3b05fc 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -593,12 +593,14 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) // } ph_printf("\nGC started:\n"); - // pvm_object_t obj = (void*)0x80a55740; - // dumpo(obj); - phantom_snapper_wait_4_threads(); + // phantom_snapper_wait_4_threads(); run_gc_on_snap(); ph_printf("\nGC end:\n"); - phantom_snapper_reenable_threads(); + // ph_printf("before reenable threads:\n"); + // pvm_object_t obj = (void*)0x413f4fb8; + // dumpo(obj); + // phantom_snapper_reenable_threads(); + // ph_printf("after reenable threads:\n"); } ph_printf("\n\x1b[33m\x1b[44mPhantom " PHANTOM_VERSION_STR " (SVN rev %s) @ %s started\x1b[0m\n\n", svn_version(), phantom_uname.machine ); diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index 40754898f..f36709391 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -1658,6 +1658,7 @@ static int seconds_between_snaps = 5; static void free_old_snapshot() { disk_page_no_t to_free = pager_superblock_ptr()->snap_to_free; + disk_page_no_t snap_already_read = pager_superblock_ptr()->snap_already_read; disk_page_no_t snap_reading = pager_superblock_ptr()->snap_reading; if (to_free == 0 || to_free == snap_reading) return; @@ -1665,25 +1666,17 @@ static void free_old_snapshot() { disk_page_no_t actual1 = pager_superblock_ptr()->prev_snap; disk_page_no_t actual2 = pager_superblock_ptr()->last_snap; disk_page_no_t actual3 = (snap_reading == actual1 || snap_reading == actual2) ? 0 : snap_reading; + disk_page_no_t[] actual_arr = { actual1, acutal2, actual3 }; + + disk_page_no_t free1 = to_free; + disk_page_no_t free2 = (snap_already_read != free1) ? snap_already_read : 0; + disk_page_no_t[] free_arr = { free1, free2 }; - phantom_free_snap( to_free, actual1, actual2, actual3 ); + phantom_free_snap(free_arr, 2, actual_arr, 3); pager_superblock_ptr()->snap_to_free = 0; - pager_fence(); - pager_update_superblock(); - - disk_page_no_t snap_already_read = pager_superblock_ptr()->snap_already_read; - if (snap_already_read != 0) { - if (snap_already_read != to_free) { - phantom_free_snap(snap_already_read, actual1, actual2, actual3); - } - - pager_superblock_ptr()->snap_already_read = 0; - } - // Force all io to complete BEFORE updating superblock pager_fence(); - pager_update_superblock(); pager_free_blocklist_pages(); @@ -1701,7 +1694,7 @@ static void vm_map_snapshot_thread(void) SHOW_FLOW0( 1, "Snapshot loop"); SHOW_FLOW(0, "%d %d %d", stop_lazy_pageout_thread, vm_regular_snaps_enabled, request_snap_flag); - free_old_snapshot(); + // free_old_snapshot(); if( stop_lazy_pageout_thread ) { diff --git a/src/phantom/vm/backtrace.c b/src/phantom/vm/backtrace.c index f70a8481d..57a470ebc 100644 --- a/src/phantom/vm/backtrace.c +++ b/src/phantom/vm/backtrace.c @@ -83,7 +83,8 @@ void pvm_exec_panic( const char *reason, struct data_area_4_thread *tda ) void pvm_backtrace_current_thread(void) -{ +{ + ph_printf("in backtrace\n"); errno_t e = ENOENT; int tid = get_current_tid(); if( tid < 0 ) @@ -131,6 +132,7 @@ void pvm_backtrace_current_thread(void) void pvm_backtrace(struct data_area_4_thread *tda) { + ph_printf("inside inner backtrace\n"); struct pvm_code_handler *code = &tda->code; if(code->IP > code->IP_max) diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index a7a1dd3c8..b78fb0fde 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -1103,6 +1103,7 @@ void pvm_gc_iter_directory(gc_iterator_call_t func, pvm_object_t os, void *arg) gc_fcall( func, arg, da->keys ); gc_fcall( func, arg, da->values ); + gc_fcall( func, arg, da->flags_container ); } diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 3a20c7ddb..888cacfb0 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -81,7 +81,9 @@ static char* load_snap() { unsigned int np; for (np = 0; np < page_count; np++) { - ph_printf("np: %d/%d\n", np, page_count); + if (np % 500 == 0) + ph_printf("np: %d/%d\n", np, page_count); + if (!pagelist_read_seq(&loader, &curr_block)) { ph_printf("\n!!! Incomplete pagelist !!!\n"); snapshot = 0; @@ -162,28 +164,27 @@ void run_gc_on_snap() { static void mark_tree(pvm_object_storage_t* obj_in_snap) { - ph_printf("\nGC: process another object\n"); - ph_printf("Flags: '"); - print_object_flags(obj_in_snap); - ph_printf("'\n"); + // ph_printf("\nGC: process another object\n"); + // ph_printf("Flags: '"); + // print_object_flags(obj_in_snap); + // ph_printf("'\n"); // ph_printf("object class:\n"); // dumpo(obj_in_snap->_class); - ph_printf("p: %p, p->ah: %p, p->da: %p\n", obj_in_snap, &obj_in_snap->_ah, obj_in_snap->da); - ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); + // ph_printf("p: %p, p->ah: %p, p->da: %p\n", obj_in_snap, &obj_in_snap->_ah, obj_in_snap->da); + // ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); obj_in_snap->_ah.gc_flags = gc_flags_last_generation; // set - ph_printf("assert start marker and allocated\n"); + // ph_printf("assert start marker and allocated\n"); assert(obj_in_snap->_ah.object_start_marker == PVM_OBJECT_START_MARKER); assert(obj_in_snap->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); - ph_printf("check if childfree\n"); + // ph_printf("check if childfree\n"); // Fast skip if no children - if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE)) { - ph_printf("not childfree, call gc_process_children\n"); - ph_printf("shift addr: %p\n", &shift); - ph_printf("p addr: %p\n", &obj_in_snap); + // ph_printf("not childfree, call gc_process_children\n"); + // ph_printf("p addr: %p\n", &obj_in_snap); gc_process_children(mark_tree_o, obj_in_snap, 0); } } @@ -201,7 +202,7 @@ static void mark_tree_o(pvm_object_t obj_in_pvm, void* arg) { } static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_in_snap, void* arg) { - ph_printf("GC: process children\n"); + // ph_printf("GC: process children\n"); f(obj_in_snap->_class, arg); // Fast skip if no children - done! @@ -211,7 +212,7 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_ // plain non internal objects - if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) { - ph_printf("External object, normal iter\n"); + // ph_printf("External object, normal iter\n"); unsigned i; for (i = 0; i < da_po_limit(obj_in_snap); i++) @@ -224,7 +225,7 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_ // We're here if object is internal. // Now find and call class-specific function: pvm_gc_iter_* - ph_printf("Internal object, get iter method\n"); + // ph_printf("Internal object, get iter method\n"); gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(shift_ptr(obj_in_snap->_class, shift), class)->sys_table_id].iter; iter(f, obj_in_snap, arg); diff --git a/src/phantom/vm/object.c b/src/phantom/vm/object.c index abad83f7e..c09065549 100755 --- a/src/phantom/vm/object.c +++ b/src/phantom/vm/object.c @@ -58,8 +58,10 @@ pvm_object_t pvm_get_array_ofield(pvm_object_t o, unsigned int slot ) if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) - ) - pvm_exec_panic0( "attempt to do an array op to non-array" ); + ) { + dumpo(o); + pvm_exec_panic0( "attempt to do get_ofield to non-array" ); + } struct data_area_4_array *da = (struct data_area_4_array *)&(o->da); @@ -77,8 +79,10 @@ void pvm_set_array_ofield(pvm_object_t o, unsigned int slot, pvm_object_t value if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) - ) - pvm_exec_panic0( "attempt to do an array op to non-array" ); + ) { + dumpo(o); + pvm_exec_panic0( "attempt to do set_ofield to non-array" ); + } if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (o->_flags) ) pvm_exec_panic0( "attempt to set_array_ofield for immutable" ); @@ -137,8 +141,10 @@ void pvm_pop_array(pvm_object_t array, pvm_object_t value_to_pop ) if( !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (array->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (array->_flags) ) - ) - pvm_exec_panic0( "attempt to do an array op to non-array" ); + ) { + pvm_exec_panic0( "attempt to do pop to non-array" ); + dumpo(array); + } if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (array->_flags) ) pvm_exec_panic0( "attempt to pop_array for immutable" ); @@ -481,6 +487,7 @@ void dumpo( addr_t addr ) ph_printf("Flags: '"); print_object_flags(o); ph_printf("', "); + ph_printf("refCnt: %d\n", o->_ah.refCount); //ph_printf("', da size: %ld, ", (long)(o->_da_size) ); if(o->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_STRING) diff --git a/src/phantom/vm/sys/i_wasm.c b/src/phantom/vm/sys/i_wasm.c index b8e2863c0..9ce487778 100644 --- a/src/phantom/vm/sys/i_wasm.c +++ b/src/phantom/vm/sys/i_wasm.c @@ -476,6 +476,7 @@ static bool initialize_wasm(pvm_object_t o) { ) { master_instance = da; + da->is_master = true; } hal_mutex_unlock(vm_alloc_mutex); @@ -898,11 +899,14 @@ void pvm_gc_iter_wasm(gc_iterator_call_t func, pvm_object_t self, void *arg) { func(wasm_da->env_vars_array, arg); func(wasm_da->wasm_sandboxed_objects, arg); - if (wasm_da != master_instance) { + if (!wasm_da->is_master) { + ph_printf("mutex and cond arrays are not marked\n"); func(pvm_da_to_object(master_instance), arg); return; } + ph_printf("marking mutex and cond arrays\n"); + func(master_instance->wasm_native_symbols, arg); func(master_instance->wasm_runtime_objects, arg); func(master_instance->wasm_mutex_array, arg); @@ -931,6 +935,14 @@ void pvm_restart_wasm(pvm_object_t o) { assert(master_instance == NULL); r_assert(initialize_wasm(o)); // sets master_instance + ph_printf("mutex array allocated: %d\n", pvm_object_is_allocated(master_instance->wasm_mutex_array)); + dumpo(master_instance->wasm_mutex_array); + ph_printf("cond array allocated: %d\n", pvm_object_is_allocated(master_instance->wasm_cond_array)); + dumpo(master_instance->wasm_cond_array); + dump_uarray(master_instance->wasm_mutex_array, "Mutexes"); + dump_uarray(master_instance->wasm_cond_array, "Conds"); + + foreach_in_uarray(master_instance->wasm_mutex_array, entry) { if (*entry) { if (hal_mutex_init((hal_mutex_t*) *entry, NULL) < 0) diff --git a/src/phantom/vm/sys/i_wasm.h b/src/phantom/vm/sys/i_wasm.h index 20716199c..caae0dd72 100644 --- a/src/phantom/vm/sys/i_wasm.h +++ b/src/phantom/vm/sys/i_wasm.h @@ -5,6 +5,8 @@ struct data_area_4_wasm { + bool is_master; + // .internal.array, stores objects containing description of wasm native symbols pvm_object_t wasm_native_symbols; // .internal.array, stores objects allocated by wasm runtime using malloc diff --git a/src/phantom/vm/wasm-micro-runtime b/src/phantom/vm/wasm-micro-runtime index ea15ac519..dd9eb5f34 160000 --- a/src/phantom/vm/wasm-micro-runtime +++ b/src/phantom/vm/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit ea15ac5191e7922fbdb6ee0c0a80d1027736cb86 +Subproject commit dd9eb5f34e3c1e493b97173827567fb8e1aa101d From ee9209478fc68b656ad31619f3434cc0f15a7105 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Sat, 24 Aug 2024 18:20:25 +0200 Subject: [PATCH 10/14] dump --- src/include/vm/alloc.h | 3 + src/phantom/isomem/amap.c | 6 + src/phantom/isomem/fsck.c | 19 ++- src/phantom/isomem/main.c | 1 + src/phantom/isomem/pager.h | 9 +- src/phantom/isomem/vm_map.c | 23 ++-- src/phantom/vm/gc_on_snap.c | 185 ++++++++++++++++-------------- src/phantom/vm/wasm-micro-runtime | 2 +- 8 files changed, 139 insertions(+), 109 deletions(-) diff --git a/src/include/vm/alloc.h b/src/include/vm/alloc.h index 14b58c250..30640f203 100755 --- a/src/include/vm/alloc.h +++ b/src/include/vm/alloc.h @@ -61,12 +61,15 @@ void do_ref_dec_p(pvm_object_storage_t *p); // for deferred refdec + // ------------------------------------------------------------ // shared between alloc.c and gc.c // Gigant lock for now. TODO extern hal_mutex_t *vm_alloc_mutex; +extern hal_mutex_t *vm_read_snap_mutex; +void init_gc(); void * get_pvm_object_space_start(void); void * get_pvm_object_space_end(void); diff --git a/src/phantom/isomem/amap.c b/src/phantom/isomem/amap.c index 49d172683..d254f11ad 100755 --- a/src/phantom/isomem/amap.c +++ b/src/phantom/isomem/amap.c @@ -125,9 +125,15 @@ amap_iterate_all( amap_t *map, void (*f)( amap_elem_addr_t from, amap_elem_size_ void amap_iterate_flags( amap_t *map, void (*f)( amap_elem_addr_t from, amap_elem_size_t n_elem, u_int32_t flags, void *arg ), void *arg, u_int32_t flags ) { + ph_printf("map: %p, f: %p, arg: %p\n", map, f, arg); + ph_printf("queue addr: %p\n", &(map->queue)); + ph_printf("queue next addr: %p\n", map->queue.next); + ph_printf("queue prev addr: %p\n", map->queue.prev); + amap_entry_t *ie; queue_iterate(&(map->queue), ie, amap_entry_t *, chain) { + ph_printf("ie: %p\n", ie); if( ie->flags == flags ) f(ie->start, ie->n_elem, ie->flags, arg); } diff --git a/src/phantom/isomem/fsck.c b/src/phantom/isomem/fsck.c index 09c9a32f4..fbe1fffcc 100755 --- a/src/phantom/isomem/fsck.c +++ b/src/phantom/isomem/fsck.c @@ -582,6 +582,7 @@ static void free_snap_worker(disk_page_no_t toFree, int flags) //SHOW_FLOW( 0, "Free old snap blk: %ld", (long)toFree ); //ph_printf( " %ld", (long)toFree ); + ph_printf("snap worker free page page_no_t: %ld\n", (long)toFree); pager_free_page( toFree ); } @@ -601,20 +602,28 @@ void phantom_free_snap( fsck_create_map(); for (int i = 0; i < to_free_arr_len; i++) { - if (to_free_arr[i] != 0) + if (to_free_arr[i] != 0) { + ph_printf("Free old snap blk: %ld\n", (long)to_free_arr[i]); fsck_list_justadd_as_free(to_free_arr[i]); + } } for (int i = 0; i < actual_arr_len; i++) { - if (actual_arr[i] != 0) + if (actual_arr[i] != 0) { + ph_printf("Mark new snap blk: %ld\n", (long)actual_arr[i]); fsck_list_justadd_as_used(actual_arr[i]); + } } - + + ph_printf("iterate_map(free_snap_worker, MAP_FREE)\n"); iterate_map(free_snap_worker, MAP_FREE); + ph_printf("iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE)\n"); iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE); + ph_printf("pager_commit_active_free_list()\n"); pager_commit_active_free_list(); - + ph_printf("fsck_delete_map()\n"); fsck_delete_map(); + ph_printf("return from phantom_free_snap()\n"); } // void phantom_free_snap( @@ -631,7 +640,7 @@ void phantom_free_snap( // } // SHOW_FLOW0( 0, "*** freeing old snap ***"); -// fsck_create_map(); + // fsck_create_map(); // fsck_list_justadd_as_free( old_snap_start ); // fsck_list_justadd_as_used( curr_snap_start ); diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index b7d3b05fc..1f6a03d99 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -244,6 +244,7 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) // heap_init_mutex(); // After threads // OK pvm_alloc_threaded_init(); // After threads // OK + init_gc(); // Scheduler is contolled by Genode /* diff --git a/src/phantom/isomem/pager.h b/src/phantom/isomem/pager.h index 7672cdf6a..423893967 100755 --- a/src/phantom/isomem/pager.h +++ b/src/phantom/isomem/pager.h @@ -128,13 +128,10 @@ void pager_start_io(); void phantom_fsck(int do_rebuild ); -void phantom_free_snap( - disk_page_no_t old_snap_start, - disk_page_no_t curr_snap_start, - disk_page_no_t new_snap_start, - disk_page_no_t snap_reading_start +void phantom_free_snap( + disk_page_no_t* to_free_arr, int to_free_arr_len, + disk_page_no_t* actual_arr, int actual_arr_len ); - #endif // PAGER_H diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index f36709391..3408fe85d 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -1657,23 +1657,29 @@ static int request_snap_flag = 0; static int seconds_between_snaps = 5; static void free_old_snapshot() { + hal_mutex_lock(vm_read_snap_mutex); disk_page_no_t to_free = pager_superblock_ptr()->snap_to_free; disk_page_no_t snap_already_read = pager_superblock_ptr()->snap_already_read; + ph_printf("snap_to_free: %d, snap_already_read: %d\n", to_free, snap_already_read); + if (to_free == 0 && snap_already_read == 0) { + hal_mutex_unlock(vm_read_snap_mutex); + return; + } disk_page_no_t snap_reading = pager_superblock_ptr()->snap_reading; - - if (to_free == 0 || to_free == snap_reading) return; - + ph_printf("snap_reading: %d\n", snap_reading); + disk_page_no_t actual1 = pager_superblock_ptr()->prev_snap; disk_page_no_t actual2 = pager_superblock_ptr()->last_snap; disk_page_no_t actual3 = (snap_reading == actual1 || snap_reading == actual2) ? 0 : snap_reading; - disk_page_no_t[] actual_arr = { actual1, acutal2, actual3 }; + disk_page_no_t actual_arr[] = { actual1, actual2, actual3 }; disk_page_no_t free1 = to_free; disk_page_no_t free2 = (snap_already_read != free1) ? snap_already_read : 0; - disk_page_no_t[] free_arr = { free1, free2 }; + disk_page_no_t free_arr[] = { free1, free2 }; phantom_free_snap(free_arr, 2, actual_arr, 3); - + + ph_printf("we returned from phantom_free_snap\n"); pager_superblock_ptr()->snap_to_free = 0; // Force all io to complete BEFORE updating superblock pager_fence(); @@ -1682,6 +1688,7 @@ static void free_old_snapshot() { pager_free_blocklist_pages(); pager_commit_active_free_list(); pager_update_superblock(); + hal_mutex_unlock(vm_read_snap_mutex); } static void vm_map_snapshot_thread(void) @@ -1693,8 +1700,8 @@ static void vm_map_snapshot_thread(void) { SHOW_FLOW0( 1, "Snapshot loop"); SHOW_FLOW(0, "%d %d %d", stop_lazy_pageout_thread, vm_regular_snaps_enabled, request_snap_flag); - - // free_old_snapshot(); + + //free_old_snapshot(); if( stop_lazy_pageout_thread ) { diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 888cacfb0..0ecee7145 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -32,92 +32,100 @@ #include static long long shift; +hal_mutex_t *vm_read_snap_mutex; +static hal_mutex_t _vm_read_snap_mutex; -static pvm_object_t shift_ptr(pvm_object_t o, long long shift) -{ - return (pvm_object_t)((char*)o + shift); +void init_gc() { + if (hal_mutex_init(&_vm_read_snap_mutex, "ReadSnap")) + panic("Can't init read snap mutex"); + + vm_read_snap_mutex = &_vm_read_snap_mutex; +} + + +static pvm_object_t shift_ptr(pvm_object_t o, long long shift) { + return (pvm_object_t) ((char *) o + shift); } -static unsigned char gc_flags_last_generation = 0; +static unsigned char gc_flags_last_generation = 0; -static char* load_snap() { +static void mark_tree(pvm_object_storage_t *p); + +static char *load_snap() { unsigned long page_count = N_OBJMEM_PAGES + 1; SHOW_FLOW0(1, "Started"); + hal_mutex_lock(vm_read_snap_mutex); + + if (pager_superblock_ptr()->snap_already_read != 0) { + ph_printf("\n!!! Previously loaded snapshot not cleaned yet !!!\n"); + return 0; + } + disk_page_no_t snap_start = 0; if (pager_superblock_ptr()->last_snap != 0) { hal_printf("-- Use last snap\n"); snap_start = pager_superblock_ptr()->last_snap; - } - else if (pager_superblock_ptr()->prev_snap != 0) { + } else if (pager_superblock_ptr()->prev_snap != 0) { hal_printf("-- Missing last snap, use previous snap\n"); snap_start = pager_superblock_ptr()->prev_snap; } - char* snapshot = 0; + pager_superblock_ptr()->snap_reading = snap_start; + hal_mutex_unlock(vm_read_snap_mutex); if (snap_start == 0) { hal_printf("\n!!! No pagelist to load !!!\n"); + return 0; } - else { - if (pager_superblock_ptr()->snap_already_read != 0) { - ph_printf("\n!!! Previously loaded snapshot not cleaned yet !!!\n"); - return snapshot; - } - - pager_superblock_ptr()->snap_reading = snap_start; - - hal_printf("Loading pagelist from %d...\n", snap_start); - - pagelist loader; - pagelist_init(&loader, snap_start, 0, DISK_STRUCT_MAGIC_SNAP_LIST); - pagelist_seek(&loader); + hal_printf("Loading pagelist from %d...\n", snap_start); + pagelist loader; + pagelist_init(&loader, snap_start, 0, DISK_STRUCT_MAGIC_SNAP_LIST); + pagelist_seek(&loader); + + disk_page_no_t curr_block; + char *snapshot = ph_calloc(page_count, PAGE_SIZE); + char *snapshot_seeker = snapshot; + unsigned int np; + for (np = 0; np < page_count; np++) { + if (np % 500 == 0) + ph_printf("np: %d/%d\n", np, page_count); + + if (!pagelist_read_seq(&loader, &curr_block)) { + ph_printf("\n!!! Incomplete pagelist !!!\n"); + snapshot = 0; + break; + } - disk_page_no_t curr_block; - snapshot = ph_calloc(page_count, PAGE_SIZE); - char* snapshot_seeker = snapshot; - unsigned int np; - - for (np = 0; np < page_count; np++) { - if (np % 500 == 0) - ph_printf("np: %d/%d\n", np, page_count); - - if (!pagelist_read_seq(&loader, &curr_block)) { - ph_printf("\n!!! Incomplete pagelist !!!\n"); - snapshot = 0; - break; - } - - if (curr_block == 0) { - snapshot_seeker += PAGE_SIZE; - continue; // change - } - - disk_page_io sb; - disk_page_io_init(&sb); - errno_t rc = disk_page_io_load_sync(&sb, curr_block); - - if (rc) { - panic("failed to load snapshot in gc\n"); - } - - ph_memcpy(snapshot_seeker, disk_page_io_data(&sb), PAGE_SIZE); + if (curr_block == 0) { snapshot_seeker += PAGE_SIZE; + continue; // change } - pagelist_finish(&loader); + disk_page_io sb; + disk_page_io_init(&sb); + errno_t rc = disk_page_io_load_sync(&sb, curr_block); + + if (rc) { + panic("failed to load snapshot in gc\n"); + } - pager_superblock_ptr()->snap_reading = 0; - pager_superblock_ptr()->snap_already_read = snap_start; + ph_memcpy(snapshot_seeker, disk_page_io_data(&sb), PAGE_SIZE); + snapshot_seeker += PAGE_SIZE; } + pagelist_finish(&loader); + + hal_mutex_lock(vm_read_snap_mutex); + pager_superblock_ptr()->snap_reading = 0; + pager_superblock_ptr()->snap_already_read = snap_start; + hal_mutex_unlock(vm_read_snap_mutex); + return snapshot; } -static void mark_tree(pvm_object_storage_t *p); - static pvm_object_storage_t **collect_unmarked(char *start); static int free_unmarked(pvm_object_storage_t **to_free); @@ -130,7 +138,7 @@ void run_gc_on_snap() { // synchonization? gc_flags_last_generation++; // bump generation - if (gc_flags_last_generation == 0) gc_flags_last_generation++; // != 0 'cause allocation reset gc_flags to zero + if (gc_flags_last_generation == 0) gc_flags_last_generation++; // != 0 'cause allocation reset gc_flags to zero //phantom_virtual_machine_threads_stopped++; // pretend we are stopped //TODO: refine synchronization @@ -138,13 +146,13 @@ void run_gc_on_snap() { // First pass - tree walk, mark visited. // Root is always used. All other objects, including pvm_root and pvm_root.threads_list, should be reached from root... // char* snapshot = load_snap(pager_superblock_ptr()->disk_page_count); - char* snapshot = load_snap(); + char *snapshot = load_snap(); if (snapshot == 0) { ph_printf("\n!!! No snapshot loaded !!!\n"); return; } - shift = snapshot - (char*)get_pvm_object_space_start(); + shift = snapshot - (char *) get_pvm_object_space_start(); ph_printf("real space start: %p\n", get_pvm_object_space_start()); ph_printf("real space end: %p\n", get_pvm_object_space_end()); ph_printf("snapshot is loaded\n"); @@ -152,18 +160,17 @@ void run_gc_on_snap() { ph_printf("snapshot addr: %p\n", snapshot); ph_printf("reference start marker: %d\n", PVM_OBJECT_START_MARKER); - mark_tree((pvm_object_storage_t*)snapshot); - pvm_object_storage_t** to_free = collect_unmarked(snapshot); + mark_tree((pvm_object_storage_t *) snapshot); + pvm_object_storage_t **to_free = collect_unmarked(snapshot); // Second pass - linear walk to free unused objects. - int freed = free_unmarked(to_free); + int freed = free_unmarked(to_free); - if (freed > 0) - ph_printf("\ngc: %i objects freed\n", freed); + if (freed > 0) + ph_printf("\ngc: %i objects freed\n", freed); } -static void mark_tree(pvm_object_storage_t* obj_in_snap) -{ +static void mark_tree(pvm_object_storage_t *obj_in_snap) { // ph_printf("\nGC: process another object\n"); // ph_printf("Flags: '"); // print_object_flags(obj_in_snap); @@ -174,7 +181,7 @@ static void mark_tree(pvm_object_storage_t* obj_in_snap) // ph_printf("p: %p, p->ah: %p, p->da: %p\n", obj_in_snap, &obj_in_snap->_ah, obj_in_snap->da); // ph_printf("start marker: %d\n", obj_in_snap->_ah.object_start_marker); - obj_in_snap->_ah.gc_flags = gc_flags_last_generation; // set + obj_in_snap->_ah.gc_flags = gc_flags_last_generation; // set // ph_printf("assert start marker and allocated\n"); assert(obj_in_snap->_ah.object_start_marker == PVM_OBJECT_START_MARKER); @@ -189,7 +196,7 @@ static void mark_tree(pvm_object_storage_t* obj_in_snap) } } -static void mark_tree_o(pvm_object_t obj_in_pvm, void* arg) { +static void mark_tree_o(pvm_object_t obj_in_pvm, void *arg) { if (obj_in_pvm == 0) // Don't try to process null objects return; @@ -201,7 +208,7 @@ static void mark_tree_o(pvm_object_t obj_in_pvm, void* arg) { //if (o.interface->_ah.gc_flags != gc_flags_last_generation) mark_tree( o.interface ); } -static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_in_snap, void* arg) { +static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t *obj_in_snap, void *arg) { // ph_printf("GC: process children\n"); f(obj_in_snap->_class, arg); @@ -210,13 +217,11 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_ // return; // plain non internal objects - - if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) - { + if (!(obj_in_snap->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL)) { // ph_printf("External object, normal iter\n"); unsigned i; - for (i = 0; i < da_po_limit(obj_in_snap); i++) - { + for (i = 0; i < da_po_limit(obj_in_snap); i++) { f(da_po_ptr(obj_in_snap->da)[i], arg); } return; @@ -226,34 +231,37 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t* obj_ // Now find and call class-specific function: pvm_gc_iter_* // ph_printf("Internal object, get iter method\n"); - gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(shift_ptr(obj_in_snap->_class, shift), class)->sys_table_id].iter; + gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(shift_ptr(obj_in_snap->_class, shift), class)-> + sys_table_id].iter; iter(f, obj_in_snap, arg); } -static pvm_object_storage_t** collect_unmarked(char* start) { - char* end = (char*)start + N_OBJMEM_PAGES * 4096L; - char* curr; +static pvm_object_storage_t **collect_unmarked(char *start) { + char *end = (char *) start + N_OBJMEM_PAGES * 4096L; + char *curr; int freed = 0; - for (curr = start; curr < end; curr += ((pvm_object_storage_t*)curr)->_ah.exact_size) { - pvm_object_storage_t* p = (pvm_object_storage_t*)curr; + for (curr = start; curr < end; curr += ((pvm_object_storage_t *) curr)->_ah.exact_size) { + pvm_object_storage_t *p = (pvm_object_storage_t *) curr; assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); - if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) //touch not accessed but allocated objects + if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) + //touch not accessed but allocated objects { ++freed; } } - pvm_object_storage_t** to_free = ph_calloc((freed + 1), sizeof(pvm_object_storage_t*)); + pvm_object_storage_t **to_free = ph_calloc((freed + 1), sizeof(pvm_object_storage_t *)); int i = 0; - for (curr = start; curr < end; curr += ((pvm_object_storage_t*)curr)->_ah.exact_size) { - pvm_object_storage_t* p = (pvm_object_storage_t*)curr; + for (curr = start; curr < end; curr += ((pvm_object_storage_t *) curr)->_ah.exact_size) { + pvm_object_storage_t *p = (pvm_object_storage_t *) curr; assert(p->_ah.object_start_marker == PVM_OBJECT_START_MARKER); - if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) //touch not accessed but allocated objects + if ((p->_ah.gc_flags != gc_flags_last_generation) && (p->_ah.alloc_flags != PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE)) + //touch not accessed but allocated objects { to_free[i++] = shift_ptr(p, -shift); } @@ -263,16 +271,15 @@ static pvm_object_storage_t** collect_unmarked(char* start) { return to_free; } -static int free_unmarked(pvm_object_storage_t** to_free) { +static int free_unmarked(pvm_object_storage_t **to_free) { int i = 0; while (to_free[i] != 0) { - pvm_object_storage_t* p = to_free[i]; + pvm_object_storage_t *p = to_free[i]; ph_printf("Freeing object %p\n", p); - if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) - { + if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) { // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? - gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; + gc_finalizer_func_t func = pvm_internal_classes[pvm_object_da(p->_class, class)->sys_table_id].finalizer; if (func != 0) func(p); @@ -280,7 +287,7 @@ static int free_unmarked(pvm_object_storage_t** to_free) { // should run ref_dec for children? } - p->_ah.refCount = 0; // free now + p->_ah.refCount = 0; // free now p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now i++; } diff --git a/src/phantom/vm/wasm-micro-runtime b/src/phantom/vm/wasm-micro-runtime index dd9eb5f34..ea15ac519 160000 --- a/src/phantom/vm/wasm-micro-runtime +++ b/src/phantom/vm/wasm-micro-runtime @@ -1 +1 @@ -Subproject commit dd9eb5f34e3c1e493b97173827567fb8e1aa101d +Subproject commit ea15ac5191e7922fbdb6ee0c0a80d1027736cb86 From 7dbc0bb9c0e170ac402b3f3d98b4c32ab0f6aa21 Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Sat, 24 Aug 2024 23:27:20 +0200 Subject: [PATCH 11/14] dump --- src/phantom/isomem/amap.c | 1 - src/phantom/isomem/fsck.c | 6 ------ src/phantom/isomem/main.c | 4 ++-- src/phantom/isomem/vm_map.c | 3 ++- src/plib/bin/classes | Bin 6500662 -> 6499645 bytes src/plib/sys/classes | Bin 6500662 -> 6499645 bytes src/plib/sys/classes.ar | Bin 6472242 -> 6471224 bytes .../src/ru.dz/ru.dz.phantom.system.shell.ph | 15 ++++----------- 8 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/phantom/isomem/amap.c b/src/phantom/isomem/amap.c index d254f11ad..8776472f8 100755 --- a/src/phantom/isomem/amap.c +++ b/src/phantom/isomem/amap.c @@ -133,7 +133,6 @@ amap_iterate_flags( amap_t *map, void (*f)( amap_elem_addr_t from, amap_elem_siz amap_entry_t *ie; queue_iterate(&(map->queue), ie, amap_entry_t *, chain) { - ph_printf("ie: %p\n", ie); if( ie->flags == flags ) f(ie->start, ie->n_elem, ie->flags, arg); } diff --git a/src/phantom/isomem/fsck.c b/src/phantom/isomem/fsck.c index fbe1fffcc..50e879ca5 100755 --- a/src/phantom/isomem/fsck.c +++ b/src/phantom/isomem/fsck.c @@ -582,7 +582,6 @@ static void free_snap_worker(disk_page_no_t toFree, int flags) //SHOW_FLOW( 0, "Free old snap blk: %ld", (long)toFree ); //ph_printf( " %ld", (long)toFree ); - ph_printf("snap worker free page page_no_t: %ld\n", (long)toFree); pager_free_page( toFree ); } @@ -615,15 +614,10 @@ void phantom_free_snap( } } - ph_printf("iterate_map(free_snap_worker, MAP_FREE)\n"); iterate_map(free_snap_worker, MAP_FREE); - ph_printf("iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE)\n"); iterate_map(free_blocklist_page_snap_worker, MAP_LIST_NODE); - ph_printf("pager_commit_active_free_list()\n"); pager_commit_active_free_list(); - ph_printf("fsck_delete_map()\n"); fsck_delete_map(); - ph_printf("return from phantom_free_snap()\n"); } // void phantom_free_snap( diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index 1f6a03d99..7eb5ae209 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -594,13 +594,13 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) // } ph_printf("\nGC started:\n"); - // phantom_snapper_wait_4_threads(); + phantom_snapper_wait_4_threads(); run_gc_on_snap(); ph_printf("\nGC end:\n"); // ph_printf("before reenable threads:\n"); // pvm_object_t obj = (void*)0x413f4fb8; // dumpo(obj); - // phantom_snapper_reenable_threads(); + phantom_snapper_reenable_threads(); // ph_printf("after reenable threads:\n"); } diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index 3408fe85d..6bb37c682 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -1681,6 +1681,7 @@ static void free_old_snapshot() { ph_printf("we returned from phantom_free_snap\n"); pager_superblock_ptr()->snap_to_free = 0; + pager_superblock_ptr()->snap_already_read = 0; // Force all io to complete BEFORE updating superblock pager_fence(); pager_update_superblock(); @@ -1701,7 +1702,7 @@ static void vm_map_snapshot_thread(void) SHOW_FLOW0( 1, "Snapshot loop"); SHOW_FLOW(0, "%d %d %d", stop_lazy_pageout_thread, vm_regular_snaps_enabled, request_snap_flag); - //free_old_snapshot(); + free_old_snapshot(); if( stop_lazy_pageout_thread ) { diff --git a/src/plib/bin/classes b/src/plib/bin/classes index cbeb76bc4773facb5da27a7772c0a0e3c41d3a5f..fe8db48c28a03fecf0a9b737d4e6aa711c2579a9 100644 GIT binary patch delta 2237 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 t?}g($tV<&XR23{{ey~2T%Y2 diff --git a/src/plib/sys/classes b/src/plib/sys/classes index cbeb76bc4773facb5da27a7772c0a0e3c41d3a5f..fe8db48c28a03fecf0a9b737d4e6aa711c2579a9 100644 GIT binary patch delta 2237 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 t?}g($tV<&XR23{{ey~2T%Y2 diff --git a/src/plib/sys/classes.ar b/src/plib/sys/classes.ar index 6305bac7889d5f8cce133a7df5926427dcf34fe0..d779304e52324a6c111ec320102d21e2dffb4569 100644 GIT binary patch delta 2357 zcmZYBdrXyO90&089&QSU14o1d%1ulZ3vR`@Oy~ zVSVH~e+B2fD`~1oUl}36NM34eTw=5e$)MqWl12T4q$%=IdQps9m29Yy(ac74BHElJ zOjJJk@<3inOj5Lex}?$b!&W8@H=1kv3g_>0gA`OVJpbT~XvLx^%YxI#k&=&{CPi7C z9Hrg+z90B;CqyuWiI7*vgzhnc124otEW|-PB)|-q35k#dK1c>Xq(CYJU>2moY)FR; z2tp=g!5o+i*^mRdkO%oN4+>yDJO&G(5EjBBD1u^G3?)zsWl#=0*kceu0vQxgK?5BO zsDLH#I4p%_Y)q&;@W4r{Ch#)rEH}r4PLZlf6KjO+sWF$iGptF@3~yp)o!NnWPfe&Y z6=CO_mDQV{W4TN&ILr~RM<)qW5vD^8=9|&!7I~~Cd%78>o4G+eW-uB=53MurIxVS+ zV%SgY_0h!QH<+W|SdrHhdhS<}PJ4!}c-mTT`e|S%Cimf@Zd?-vG_BW=}CB!VGJ99%NiQH!URmi4? z@+)MpCNRSqPYbDZ(yigWx%?l+_a>+`jJ@%jP*AO4g zK5iwZaN*CKIFIK#J(U+qr(f(Q$@CsV`bdtSuCA_4@_JsRRkdc2Zp;rQQd&y<-F!g^ zs$m7Jgc`;dSadIK9JL7AZG-w6s+}+5*l0C#%$X!I}R2sc$?sv~S?ssnnEn9|^ z9vHO3^q)bi+{;~~fqA5WT0<7^<^H69+nIZB+)DOycicGczrGh11!-40@w2l-Ry$WH z;bE*jE`0jH{&{prY+J;-?2Ri|bUmLAT_z>8bJ(hP(#1c(PY+}oq)e~?YDTc(e zE8kncFL&lZlU3T%PckXypovxc$XXn=(apoF&JJPz067}(Y!6v8Cc@ayL9%$3v!@hU zvfJLpUMnWYHoK)W}b5=B%c zrd=U7rX5*|fMNbZZn?J*x+}9qS4ob0^NBjTQGea8D%t}>7Ff*Aq#6`UDu-RYMUtIX1w)f{cKFVNGcHgEkO^y}2u delta 3142 zcmZXW4{#LK9mj9)a+eq`xrE#$q~XqBAcPQ){qy!;D6q+)>?5WUI0a0Q+Z2>(8VC{E z3eyIyZA2&oX5h`(DMcrg{s{vl9i9s4$PDA?C@=~tmX37#FUUAxopuyZ`rEzi+nw=d zK6~H&{@(Am@9o>&_g=pJTxj%}9igM2MWV9E^P->%f-1{HPgPfql@$s>*F}OV31jVd z-70V$0f{QI+YMb2mXDn-ZRXqv;&~*G6_wS5Jx9_I`TRNDH}>1atdMI9k|^_I7p7#{ z#SvI)zTxoQF|VPhOHQ9iE^90qs;_&-ErCQq(#MY1?I>~`QR4Icclvdr=>V%Ds*1$B zJs!HqkFyjQvStTEFcKoM{kPz+20qCg2y3dDdipd6SCQ~+@x z0aOB2z!abw_zqA5Oa+oa3b-4n1*QS_0Cm80UEWIj>rPfD|GW5W4y|>kUsHT&~1y1`D|)s zK@&x1#%Oc9u_aVI@faalB7a+I^i#gWIK&FF?{B;0AtVC|8j+E2jx z!QoDW4tKU}%T4aC4g>|&*ulxyaR)ixrN^s3!$H^AjakBMDZlDe#ftmKfR$LgE zUe8Wjok+?)ZvaBaxC-aQX<-};xaW4T08Z>0v93*BMj{*!I;D;L(az#*dDAg&ILDtD zbpv2k8l`ZY4ir{E)*TSWan6>IGsS6n&4`B&23`*3&50t{4EwTSaP7iy*?73C#g;+n zL8hy9vymu_7dp=U55d3!)$w3F5-)U`IAw!|@>)SfJfzxIv2i$95sx_SxmF_)$!qSh zteqRRo0NkaxpU{6kM|`rk2i+)*%r_SKvym2IHBzvZbJWpY>eSb^6O+KI^Wvi1#-JR zZI$`-kf(Fcd)i8ncaxcPsr7=-OOnr%nM9DY$n9i?C$C;Mi(_2wcfJ-4q$8C{#5k+b zXC5Z2QkiLB@;>t@nO2Ug$j(%zxQ4S7Uu3RNpCEhAn~B++b;@VH?$a$k{f4c{#$+bB zfU_3)0&n_syQg#KJZ+u#>Gw&?fzCvTv)&_bznit3`d$Li|Jlr{noc@z(lE#0VB_!62Ck454+;m=Skoy1Y@Q*!=LXC-;$usNOd z{1BH!kNWb+UoV+eLt7i7LGBxR^02v+n;}BDz#bL+M*;iytr5}nN6gE?Nbww5(`w0{ zUuB!f)={&=y=h33^Gh_nK5CAaGh2c0KY8aGP98sFo^5q)S(K0pAMHN6xCk#{`ws*= z1!vK=*Ll)(1{cw(CHNrQN{E`yJ4+4yM+Kfe*{vq=$g%tAj(YqmTgD_oP!!tHgvI(v z6Dydg%RJq+6ff7jTvbsiY-4)7JRTCAC2L?e?yqrM3JTJc{HoYHf?x8sQM@Y3wB`to zvRw%hWl^KjC|($LuPo_;LZ7C%yufvksPlCH3EUWSuYe?76X=Dv@i;3k=_)M6=U%}* zL^_KH+?JAx6rQ|x7GGtKj%1yVox_XRIFKSLaz1zCMK4#BHC?B-FXDx4HAcLyE98L> z@pV>CmL!zV9sS75MUtY+blxTWDa#d9T}4#-3%<^VF9|BI)AT1e$z~48sx;A;)Bp79 ziHfQ#wEbUrgpF8`HA$o4tN4V^5;d8^L)7S9Re}8-4St5@aHYG+m1U$jp9A~5s*~7N zoH*3|AIx$@NfHoU{{^;!?i@&huF;SGi=SlV9}fVyWdT@&Edm`6!QM5?zR61Yf&@j diff --git a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph index 4a33074b2..34c6d9f68 100755 --- a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph +++ b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph @@ -54,8 +54,8 @@ class shell extends runnable //var mtx : .internal.mutex; - //var demo : .ru.dz.demo.wasm; - // var demo : .ru.dz.demo.start; + // var demo : .ru.dz.demo.wasm; + var demo : .ru.dz.demo.start; // var demo : .ru.dz.phantom.persistence_test; /* void init() @@ -114,16 +114,9 @@ class shell extends runnable stat_conn = new .internal.connection(); stat_conn.connect("stt:"); -<<<<<<< HEAD - // demo = new .ru.dz.demo.start(); - demo = new .ru.dz.demo.wasm(); - // demo = new .ru.dz.phantom.persistence_test(); - demo.run(console); -======= - //demo = new .ru.dz.demo.start(); + demo = new .ru.dz.demo.start(); //demo = new .ru.dz.demo.wasm(); - //demo.run(console); ->>>>>>> 925597fc (dump: collection on snapshot) + demo.run(console); while(1) { From 027c9523ee9ac0c02207bc0b777ae3539eef5d3a Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Sun, 25 Aug 2024 17:47:57 +0200 Subject: [PATCH 12/14] important dump: no errors --- src/phantom/vm/gc_on_snap.c | 3 +++ src/phantom/vm/sys/i_wasm.c | 16 +++++++++------- src/phantom/vm/sys/i_wasm.h | 3 ++- src/plib/bin/classes | Bin 6499645 -> 6499642 bytes src/plib/sys/classes | Bin 6499645 -> 6499642 bytes src/plib/sys/classes.ar | Bin 6471224 -> 6471222 bytes .../src/ru.dz/ru.dz.phantom.system.shell.ph | 8 ++++---- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index 0ecee7145..e647bd88a 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -273,6 +273,8 @@ static pvm_object_storage_t **collect_unmarked(char *start) { static int free_unmarked(pvm_object_storage_t **to_free) { int i = 0; + + vm_lock_persistent_memory(); while (to_free[i] != 0) { pvm_object_storage_t *p = to_free[i]; ph_printf("Freeing object %p\n", p); @@ -291,4 +293,5 @@ static int free_unmarked(pvm_object_storage_t **to_free) { p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; // free now i++; } + vm_unlock_persistent_memory(); } diff --git a/src/phantom/vm/sys/i_wasm.c b/src/phantom/vm/sys/i_wasm.c index 9ce487778..569ff3b86 100644 --- a/src/phantom/vm/sys/i_wasm.c +++ b/src/phantom/vm/sys/i_wasm.c @@ -475,8 +475,10 @@ static bool initialize_wasm(pvm_object_t o) { (pvm_da_to_object(master_instance))->_class != pvm_get_wasm_class() ) { + assert(da->master_ref == 0); master_instance = da; - da->is_master = true; + } else { // master already exists + da->master_ref = master_instance; } hal_mutex_unlock(vm_alloc_mutex); @@ -899,18 +901,18 @@ void pvm_gc_iter_wasm(gc_iterator_call_t func, pvm_object_t self, void *arg) { func(wasm_da->env_vars_array, arg); func(wasm_da->wasm_sandboxed_objects, arg); - if (!wasm_da->is_master) { + if (wasm_da->master_ref) { ph_printf("mutex and cond arrays are not marked\n"); - func(pvm_da_to_object(master_instance), arg); + func(pvm_da_to_object(wasm_da->master_ref), arg); return; } ph_printf("marking mutex and cond arrays\n"); - func(master_instance->wasm_native_symbols, arg); - func(master_instance->wasm_runtime_objects, arg); - func(master_instance->wasm_mutex_array, arg); - func(master_instance->wasm_cond_array, arg); + func(wasm_da->wasm_native_symbols, arg); + func(wasm_da->wasm_runtime_objects, arg); + func(wasm_da->wasm_mutex_array, arg); + func(wasm_da->wasm_cond_array, arg); } syscall_func_t syscall_table_4_wasm[16] = diff --git a/src/phantom/vm/sys/i_wasm.h b/src/phantom/vm/sys/i_wasm.h index caae0dd72..bb86dfd43 100644 --- a/src/phantom/vm/sys/i_wasm.h +++ b/src/phantom/vm/sys/i_wasm.h @@ -5,7 +5,8 @@ struct data_area_4_wasm { - bool is_master; + // 0 if self is master, points to master instance otherwise + struct data_area_4_wasm *master_ref; // .internal.array, stores objects containing description of wasm native symbols pvm_object_t wasm_native_symbols; diff --git a/src/plib/bin/classes b/src/plib/bin/classes index fe8db48c28a03fecf0a9b737d4e6aa711c2579a9..cd0ab756f95f69843d886b1afd92203f5710702e 100644 GIT binary patch delta 1301 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 Date: Tue, 3 Sep 2024 01:51:43 +0200 Subject: [PATCH 13/14] implement bacon's algorithm & fix related bugs --- src/include/vm/alloc.h | 5 + src/include/vm/object.h | 2 + src/include/vm/root.h | 9 +- src/phantom/isomem/amap.c | 5 - src/phantom/isomem/main.c | 23 -- src/phantom/isomem/vm_cn_udp.c | 1 + src/phantom/isomem/vm_connect.c | 9 +- src/phantom/isomem/vm_map.c | 30 ++ src/phantom/isomem/vm_map.h | 3 + src/phantom/vm/alloc.c | 30 +- src/phantom/vm/create.c | 23 +- src/phantom/vm/gc.c | 70 +++-- src/phantom/vm/gc_on_snap.c | 486 +++++++++++++++++++++++++++++++- src/phantom/vm/internal.c | 4 +- src/phantom/vm/object.c | 55 +++- src/phantom/vm/root.c | 28 ++ src/phantom/vm/stacks.c | 2 +- src/phantom/vm/sys/i_io.c | 6 +- src/phantom/vm/syscall_tty.c | 7 +- src/phantom/vm/syscall_win.c | 1 + 20 files changed, 698 insertions(+), 101 deletions(-) diff --git a/src/include/vm/alloc.h b/src/include/vm/alloc.h index 30640f203..9bcc30b67 100755 --- a/src/include/vm/alloc.h +++ b/src/include/vm/alloc.h @@ -43,8 +43,13 @@ void debug_catch_object(const char *msg, pvm_object_storage_t *p); // gc +pvm_object_t pvm_get_gc_buffer(void); +pvm_object_t pvm_consume_gc_buffer_old(void); +void pvm_swap_gc_buffers(void); + void run_gc(void); void run_gc_on_snap(void); +void run_gc_incremental(pvm_object_t cycle_candidates); // Make sure this object won't be deleted with refcount dec // used on sys global objects diff --git a/src/include/vm/object.h b/src/include/vm/object.h index f4e22379b..7532c072b 100755 --- a/src/include/vm/object.h +++ b/src/include/vm/object.h @@ -156,11 +156,13 @@ void pvm_set_field( pvm_object_t , unsigned int no, pvm_object_t val // Need it here? It will be called by usual set field ones... pvm_object_t pvm_get_array_ofield(pvm_object_t o, unsigned int slot ); void pvm_set_array_ofield(pvm_object_t o, unsigned int slot, pvm_object_t value ); +void pvm_set_field_norefdec( pvm_object_t o, unsigned int slot, pvm_object_t value ); int get_array_size(pvm_object_t array); #define pvm_get_array_size get_array_size void pvm_append_array(pvm_object_t array, pvm_object_t value_to_append ); void pvm_pop_array(pvm_object_t array, pvm_object_t value_to_pop ); +void pvm_clear_array(pvm_object_t array); // Debug diff --git a/src/include/vm/root.h b/src/include/vm/root.h index 0db6d762f..0f5615477 100755 --- a/src/include/vm/root.h +++ b/src/include/vm/root.h @@ -108,7 +108,8 @@ struct pvm_root_t pvm_object_t root_dir; // Root object directory pvm_object_t kernel_stats; // Persisent kernel statistics pvm_object_t class_dir; // .internal.directory of all classes used - class load cache - TODO must use weak refs or cleanup on ref cnt == 1 - + pvm_object_t gc_buffer; // array of candidates for garbage collection + pvm_object_t gc_buffer_old; // array of candidates for garbage collection }; extern struct pvm_root_t pvm_root; @@ -267,7 +268,11 @@ extern struct pvm_root_t pvm_root; #define PVM_ROOT_CLASS_DIR 73 -#define PVM_ROOT_OBJECTS_COUNT (PVM_ROOT_CLASS_DIR+30) +#define PVM_ROOT_GC_BUFFER 74 + +#define PVM_ROOT_GC_BUFFER_OLD 75 + +#define PVM_ROOT_OBJECTS_COUNT (PVM_ROOT_GC_BUFFER_OLD+30) diff --git a/src/phantom/isomem/amap.c b/src/phantom/isomem/amap.c index 8776472f8..49d172683 100755 --- a/src/phantom/isomem/amap.c +++ b/src/phantom/isomem/amap.c @@ -125,11 +125,6 @@ amap_iterate_all( amap_t *map, void (*f)( amap_elem_addr_t from, amap_elem_size_ void amap_iterate_flags( amap_t *map, void (*f)( amap_elem_addr_t from, amap_elem_size_t n_elem, u_int32_t flags, void *arg ), void *arg, u_int32_t flags ) { - ph_printf("map: %p, f: %p, arg: %p\n", map, f, arg); - ph_printf("queue addr: %p\n", &(map->queue)); - ph_printf("queue next addr: %p\n", map->queue.next); - ph_printf("queue prev addr: %p\n", map->queue.prev); - amap_entry_t *ie; queue_iterate(&(map->queue), ie, amap_entry_t *, chain) { diff --git a/src/phantom/isomem/main.c b/src/phantom/isomem/main.c index 7eb5ae209..74987f465 100644 --- a/src/phantom/isomem/main.c +++ b/src/phantom/isomem/main.c @@ -580,29 +580,6 @@ int phantom_main_entry_point(int argc, char **argv, char **envp) //init_wins(u_int32_t ip_addr); - { - // hal_sleep_msec(2000); - - // ph_printf("\nsleep done:\n"); - // pvm_object_t p = get_root_object_storage(); - // dumpo(p); - - // unsigned i; - - // for (i = 0; i < da_po_limit(p); i++) { - // dumpo(da_po_ptr(p->da)[i]); - // } - - ph_printf("\nGC started:\n"); - phantom_snapper_wait_4_threads(); - run_gc_on_snap(); - ph_printf("\nGC end:\n"); - // ph_printf("before reenable threads:\n"); - // pvm_object_t obj = (void*)0x413f4fb8; - // dumpo(obj); - phantom_snapper_reenable_threads(); - // ph_printf("after reenable threads:\n"); - } ph_printf("\n\x1b[33m\x1b[44mPhantom " PHANTOM_VERSION_STR " (SVN rev %s) @ %s started\x1b[0m\n\n", svn_version(), phantom_uname.machine ); diff --git a/src/phantom/isomem/vm_cn_udp.c b/src/phantom/isomem/vm_cn_udp.c index af85b6dfb..105dfc161 100755 --- a/src/phantom/isomem/vm_cn_udp.c +++ b/src/phantom/isomem/vm_cn_udp.c @@ -113,6 +113,7 @@ errno_t cn_udp_init( struct data_area_4_connection *c, struct data_area_4_thread SHOW_FLOW( 1, "connect udp %s", suffix ); struct cn_udp_volatile *vp = c->v_kernel_state; + (void) vp; #if HAVE_NET int rc = udp_open( &vp->udp_endpoint ); diff --git a/src/phantom/isomem/vm_connect.c b/src/phantom/isomem/vm_connect.c index e9c617dd0..cd5e618ad 100755 --- a/src/phantom/isomem/vm_connect.c +++ b/src/phantom/isomem/vm_connect.c @@ -424,8 +424,8 @@ errno_t phantom_connect_object( struct data_area_4_connection *da, struct data_a da->v_kernel_state = 0; // now create object for persistent state - - if(te->persistent_state_size) + // since this function also restarts connection, this may already be created + if(te->persistent_state_size && da->p_kernel_state == NULL) { pvm_object_t bo = pvm_create_binary_object( te->persistent_state_size, 0); if( pvm_isnull(bo) ) @@ -436,15 +436,10 @@ errno_t phantom_connect_object( struct data_area_4_connection *da, struct data_a return ENOMEM; } - // XXX : the object is created at each re-connect, so added refdec to free - // old objects. The real question : why do we recreate it in the first place? - // also probably worth to make sure contents of objects are not used anywhere... although it is not incref'ed so... - ref_dec_o(da->p_kernel_state_object); da->p_kernel_state_object = bo; struct data_area_4_binary *bda = pvm_object_da( bo, binary ); da->p_kernel_state = &(bda->data); - } else da->p_kernel_state = 0; diff --git a/src/phantom/isomem/vm_map.c b/src/phantom/isomem/vm_map.c index 6bb37c682..4e6d3b25c 100755 --- a/src/phantom/isomem/vm_map.c +++ b/src/phantom/isomem/vm_map.c @@ -214,6 +214,29 @@ static inline void page_touch_history_arg(vm_page *p, int arg) static void page_fault( vm_page *p, int is_writing ); +// merge with addr_to_vm_page? +long addr_to_page_index(unsigned long addr) +{ + addr -= (addr_t)vm_map_start_of_virtual_address_space; + + if( addr >= (((unsigned long)vm_map_vm_page_count) * __MEM_PAGE)) + return -1; + + return addr / __MEM_PAGE; +} + +int addr_to_page_offset(unsigned long addr) +{ + addr -= (addr_t)vm_map_start_of_virtual_address_space; + + if( addr >= (((unsigned long)vm_map_vm_page_count) * __MEM_PAGE)) + return -1; + + return addr % __MEM_PAGE; +} + +vm_page *get_vm_page(unsigned long index) { return &vm_map_map[index]; } + static vm_page *addr_to_vm_page(unsigned long addr, struct trap_state *ts) { // ph_printf("addr_raw=%X\n", addr); @@ -1458,11 +1481,16 @@ void do_snapshot(void) if(enabled) hal_sti(); + pvm_count_allocated_objects(); + phantom_snapper_reenable_threads(); #if USE_SNAP_WAIT signal_snap_snap_passed(); // or before enabling threads? #endif + pvm_swap_gc_buffers(); // merge into 1 function?? + pvm_object_t cycle_candidates = pvm_consume_gc_buffer_old(); + // YES, YES, YES, Snap is nearly done. // Here we have to wait a little and start processing pages manually @@ -1488,6 +1516,8 @@ void do_snapshot(void) // TODO - free prev snap first! -- (why?) + run_gc_incremental(cycle_candidates); + disk_page_no_t new_snap_head = 0; diff --git a/src/phantom/isomem/vm_map.h b/src/phantom/isomem/vm_map.h index a3aef8b18..31ffcf63f 100755 --- a/src/phantom/isomem/vm_map.h +++ b/src/phantom/isomem/vm_map.h @@ -175,6 +175,9 @@ void vm_page_req_pageout(); void vm_map_wait_for_finish(void); + long addr_to_page_index(unsigned long addr); + int addr_to_page_offset(unsigned long addr); + //extern vm_map_impl vm_map; /* diff --git a/src/phantom/vm/alloc.c b/src/phantom/vm/alloc.c index 50b883fbb..6daa4aded 100755 --- a/src/phantom/vm/alloc.c +++ b/src/phantom/vm/alloc.c @@ -198,7 +198,8 @@ static void init_free_object_header(pvm_object_storage_t *op, unsigned int size) } -#define PVM_MIN_FRAGMENT_SIZE (sizeof(pvm_object_storage_t) + sizeof(int) ) /* should be a minimal object size at least */ +// sizeof(void*) should account for object size aligning (currently 8 byte alignment is used) +#define PVM_MIN_FRAGMENT_SIZE (sizeof(pvm_object_storage_t) + sizeof(void*) ) /* should be a minimal object size at least */ // returns allocated object @@ -402,6 +403,10 @@ static pvm_object_t pvm_find(unsigned int size, int arena) if( PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE != curr->_ah.alloc_flags ) // refcount == 0, but refzero or in buffer or both { DEBUG_PRINT("(c)"); + // not sure why exactly can allocator free objects but it may + // conflict with GC, if this panic ever happens - needs further + // investigation + panic("What is this??"); refzero_process_children( curr ); // Supposed to be free here } @@ -433,7 +438,7 @@ static pvm_object_t pvm_find(unsigned int size, int arena) -#define PVM_GC_ENABLE 1 +#define PVM_GC_ENABLE 0 static pvm_object_storage_t * pool_alloc(unsigned int size, int arena) @@ -463,7 +468,7 @@ static pvm_object_storage_t * pool_alloc(unsigned int size, int arena) * */ if(vm_alloc_mutex) hal_mutex_unlock( vm_alloc_mutex ); - run_gc(); + // run_gc(); if(vm_alloc_mutex) hal_mutex_lock( vm_alloc_mutex ); #else break; //skip GC, until we bring context to the allocator @@ -662,7 +667,7 @@ static int memcheck_one(unsigned int i, void * start, void * end) return 0; } - ph_printf("\n\n-----------------\nMemcheck ERROR: reached out of arena end at 0x%p (%ld bytes size)\n-----------------\n\n", curr, (long) (((void *)curr) - start) ); + ph_printf("\n\n-----------------\nMemcheck ERROR: reached out of arena end at %p (%ld bytes size)\n-----------------\n\n", curr, (long) (((void *)curr) - start) ); return 1; } @@ -676,7 +681,7 @@ static int64_t count_objects(void *start, void *end) int64_t arena_size = ((char*) end) - ((char*) start); int64_t used_bytes = 0; pvm_object_t curr = start; - int int_count = 0, long_count = 0, str_count = 0, arr_count = 0, page_count = 0; + // int int_count = 0, long_count = 0, str_count = 0, arr_count = 0, page_count = 0; while(((void *)curr) < end) { if(!pvm_alloc_is_object(curr)) return -1; @@ -686,19 +691,20 @@ static int64_t count_objects(void *start, void *end) count++; used_bytes += curr->_ah.exact_size; - if (curr->_class == pvm_get_int_class()) int_count++; - if (curr->_class == pvm_get_long_class()) long_count++; - if (curr->_class == pvm_get_string_class()) str_count++; - if (curr->_class == pvm_get_array_class()) arr_count++; - if (curr->_class == pvm_get_page_class()) page_count++; + // if (curr->_class == pvm_get_int_class()) int_count++; + // if (curr->_class == pvm_get_long_class()) long_count++; + // if (curr->_class == pvm_get_string_class()) str_count++; + // if (curr->_class == pvm_get_array_class()) arr_count++; + // if (curr->_class == pvm_get_page_class()) page_count++; } curr = (pvm_object_t)( ((void *)curr) + curr->_ah.exact_size ); } int percent_used = 100 * used_bytes / arena_size; - SHOW_INFO(0, "Arena @%p, ints: %d, longs: %d, strs: %d, arrs: %d, pages: %d | %d%% used", - start, int_count, long_count, str_count, arr_count, page_count, percent_used); + SHOW_INFO(0, "Arena @%p, %d%% used", start, percent_used); + // SHOW_INFO(0, "Arena @%p, ints: %d, longs: %d, strs: %d, arrs: %d, pages: %d | %d%% used", + // start, int_count, long_count, str_count, arr_count, page_count, percent_used); return count; } diff --git a/src/phantom/vm/create.c b/src/phantom/vm/create.c index b78fb0fde..327c43dae 100755 --- a/src/phantom/vm/create.c +++ b/src/phantom/vm/create.c @@ -337,15 +337,13 @@ pvm_create_page_object( int n_slots, pvm_object_t *init, int init_slots ) assert(init_slots < n_slots); - int i; - for( i = 0; i < init_slots; i++ ) { - data_area[i] = *init++; - ref_inc_o(data_area[i]); // XXX : hack to avoid elements to be freed when the original page is deleted + // assuming pvm_object_create_dynamic returns zeroe'd out data area + // init new page + if (init) { + ph_memcpy(data_area, init, init_slots * sizeof(pvm_object_t)); + // clean old one to avoid refdecs on deletion + ph_memset(init, 0, init_slots * sizeof(pvm_object_t)); } - - for( ; i < n_slots; i++ ) - data_area[i] = pvm_get_null_object(); - return _data; } @@ -526,7 +524,6 @@ void pvm_internal_init_class(pvm_object_t os) void pvm_gc_iter_class(gc_iterator_call_t func, pvm_object_t os, void* arg) { - ph_printf("iter class called on %p\n", os); struct data_area_4_class* da = (struct data_area_4_class*)&(os->da); gc_fcall(func, arg, da->object_default_interface); gc_fcall(func, arg, da->class_name); @@ -576,6 +573,9 @@ void pvm_gc_iter_thread(gc_iterator_call_t func, pvm_object_t os, void *arg) gc_fcall( func, arg, da->call_frame ); gc_fcall( func, arg, da->owner ); gc_fcall( func, arg, da->environment ); +#if NEW_VM_SLEEP + gc_fcall( func, arg, da->cond_mutex ); +#endif } @@ -642,6 +642,7 @@ void pvm_internal_init_mutex(pvm_object_t os) //in_method = 0; } +// this iter is turned off right now void pvm_gc_iter_mutex(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_mutex * da = (struct data_area_4_mutex *)os->da; @@ -650,12 +651,14 @@ void pvm_gc_iter_mutex(gc_iterator_call_t func, pvm_object_t os, void *arg) //pvm_spin_init( &da->pvm_lock ); // in_method = 0; + // we don't want mutex to keep other threads alive, so this is not needed gc_fcall( func, arg, da->waiting_threads_array ); //for( i = 0; i < MAX_MUTEX_THREADS; i++ ) // gc_fcall( func, arg, da->waiting_threads[i] ); + // we don't want mutex to keep the owner thread alive, so this is not needed gc_fcall( func, arg, pvm_da_to_object(da->owner_thread) ); } @@ -1165,7 +1168,7 @@ void pvm_gc_finalizer_connection( pvm_object_t os ) void pvm_restart_connection( pvm_object_t o ) { struct data_area_4_connection *da = pvm_object_da( o, connection ); -ph_printf("restarting connection"); + ph_printf("restarting connection"); da->kernel = 0; int ret = pvm_connect_object(o,0); diff --git a/src/phantom/vm/gc.c b/src/phantom/vm/gc.c index f911d3890..e18381706 100644 --- a/src/phantom/vm/gc.c +++ b/src/phantom/vm/gc.c @@ -41,18 +41,38 @@ // see Bacon algorithm (US Patent number 6879991, issued April 12, 2005) or (US Patent number 7216136 issued 8 May 2007) // TODO: not implemented, // Need persistent cycles_root_buffer not collected by usual gc/refcount - new internal object type? +#define get_array_slot_nocheck(arr, i) ((pvm_object_t*)(pvm_data_area(arr, array)->page->da))[i] +static int find_object_in_buffer(pvm_object_t p) { + pvm_object_t array = pvm_get_gc_buffer(); + for (int i = 0; i < pvm_get_array_size(array); i++) { + if (get_array_slot_nocheck(array, i) == p) return i; + } + + return -1; +} static void cycle_root_buffer_add_candidate(pvm_object_storage_t *p) { - (void)p; + if (find_object_in_buffer(p) >= 0) return; + pvm_append_array(pvm_get_gc_buffer(), p); } -static void cycle_root_buffer_rm_candidate(pvm_object_storage_t *p) +void cycle_root_buffer_rm_candidate(pvm_object_storage_t *p) { - (void)p; + if (!pvm_get_gc_buffer()) return; + int index = find_object_in_buffer(p); + if (index < 0) return; + + struct data_area_4_array *da = pvm_data_area(pvm_get_gc_buffer(), array); + pvm_object_t *page = da_po_ptr((da->page)->da); + if (index != da->used_slots - 1) { + page[index] = page[da->used_slots - 1]; + } + page[da->used_slots - 1] = NULL; + da->used_slots--; } static void cycle_root_buffer_clear() { - //just set size to zero, so regular GC will ignore it gracefully + pvm_clear_array(pvm_get_gc_buffer()); } void gc_collect_cycles() { @@ -247,7 +267,8 @@ void refzero_process_children( pvm_object_storage_t *p ) do_refzero_process_children( p ); - if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) + // if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) + if ( !(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE) ) cycle_root_buffer_rm_candidate( p ); p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; @@ -417,18 +438,22 @@ void do_ref_dec_p(pvm_object_storage_t *p) } // if we decrement refcount and stil above zero - mark an object as potential cycle root; // and internal objects can't be a cycle root (sic!) + else { nonzero:; - if ( !(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL) ) - { - if ( !(p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER) ) - { - cycle_root_buffer_add_candidate(p); - p->_ah.alloc_flags |= PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ; - } - p->_ah.alloc_flags |= PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN ; // set down flag + // an internal object *can* form a loop: just put the array in itself (array is an internal object) + // if ( !(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL) ) + //{ + if ( !(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE) ) { + //if ( !(p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER) ) + //{ + cycle_root_buffer_add_candidate(p); + // p->_ah.alloc_flags |= PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ; + //} + //p->_ah.alloc_flags |= PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN ; // set down flag } + //} } //nokill:; } @@ -464,9 +489,10 @@ void ref_inc_p(pvm_object_storage_t *p) { //(p->_ah.refCount)++; ATOMIC_ADD_AND_FETCH( &(p->_ah.refCount), 1 ); - - if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) - p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN ; //clear down flag + if ( !(p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE) ) + cycle_root_buffer_rm_candidate(p); + // if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) + // p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN ; //clear down flag } } @@ -480,12 +506,12 @@ void ref_saturate_p(pvm_object_storage_t *p) STAT_INC_CNT( OBJECT_SATURATE ); // Saturated object can't be a loop collection candidate. Can it? - if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) { - cycle_root_buffer_rm_candidate( p ); - - p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER; - p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN; - } + cycle_root_buffer_rm_candidate( p ); + // if ( p->_ah.alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER ) { +// + // p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_IN_BUFFER; + // p->_ah.alloc_flags &= ~PVM_OBJECT_AH_ALLOCATOR_FLAG_WENT_DOWN; + // } assert( p->_ah.object_start_marker == PVM_OBJECT_START_MARKER ); assert( p->_ah.alloc_flags == PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED ); diff --git a/src/phantom/vm/gc_on_snap.c b/src/phantom/vm/gc_on_snap.c index e647bd88a..c3ba61cb9 100644 --- a/src/phantom/vm/gc_on_snap.c +++ b/src/phantom/vm/gc_on_snap.c @@ -8,7 +8,7 @@ * **/ -#define DEBUG_MSG_PREFIX "vm.gc" +#define DEBUG_MSG_PREFIX "vm.gc_on_snap" #include #define debug_level_flow 10 #define debug_level_error 10 @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -162,12 +163,479 @@ void run_gc_on_snap() { mark_tree((pvm_object_storage_t *) snapshot); pvm_object_storage_t **to_free = collect_unmarked(snapshot); + ph_printf("Collect unmarked finished\n"); // Second pass - linear walk to free unused objects. int freed = free_unmarked(to_free); - if (freed > 0) - ph_printf("\ngc: %i objects freed\n", freed); + // if (freed > 0) + // ph_printf("\ngc: %i objects freed\n", freed); +} + +struct disk_page_io gc_io; + +typedef struct gc_map { + uint64_t *keys; + uint64_t *values; + + uint64_t capacity; + uint64_t count; +} gc_map_t; + +void gc_map_init(gc_map_t *map) { + map->count = 0; + map->capacity = 16; + map->keys = ph_malloc(sizeof(uint64_t) * map->capacity); + map->values = ph_malloc(sizeof(uint64_t) * map->capacity); +} + +void gc_map_release(gc_map_t *map) { + ph_free(map->keys); + ph_free(map->values); +} + +uint64_t *__gc_map_try_get(gc_map_t *map, uint64_t key) { + for (uint64_t i = 0; i < map->count; i++) { + if (map->keys[i] == key) { + return &map->values[i]; + } + } + + return NULL; +} + +// 0 if found, -1 if not +int gc_map_try_get(gc_map_t *map, uint64_t key, uint64_t *out) { + assert(out); + + uint64_t *local_out = __gc_map_try_get(map, key); + if (local_out) { + *out = *local_out; + return 0; + } + + return -1; +} + +void __increase_capacity(void **container, uint64_t prev_capacity, uint64_t new_capacity, size_t elem_size) { + void *new_container = ph_malloc(elem_size * new_capacity); + ph_memcpy(new_container, *container, prev_capacity * elem_size); + ph_free(*container); + *container = new_container; +} + +void gc_map_insert_nocheck(gc_map_t *map, uint64_t key, uint64_t value) { + if (map->count == map->capacity) { + map->capacity *= 2; + __increase_capacity((void**) &map->keys, map->count, map->capacity, sizeof(key)); + __increase_capacity((void**) &map->values, map->count, map->capacity, sizeof(value)); + } + + map->keys[map->count] = key; + map->values[map->count] = value; + map->count++; +} + +// returns previous value (or 0 if none) +uint64_t gc_map_increment(gc_map_t *map, uint64_t key) { + uint64_t *value_ptr = __gc_map_try_get(map, key); + if (value_ptr) { + (*value_ptr)++; + return *value_ptr - 1; + } + + gc_map_insert_nocheck(map, key, 1); + return 0; +} + +// set value if key is present in map. 0 on success, 1 on skip +static int gc_map_set_or_skip(gc_map_t *map, uint64_t key, uint64_t value, uint64_t *old_value) { + uint64_t *value_ptr = __gc_map_try_get(map, key); + if (!value_ptr) return 1; + + *old_value = *value_ptr; + (*value_ptr) = value; + return 0; +} + +extern vm_page *get_vm_page(unsigned long index); + +static unsigned char *load_page(gc_map_t *map, uint64_t page_index) { + unsigned char *page = NULL; + + if (gc_map_try_get(map, page_index, &page) == 0) { + return page; + } + + // page not loaded, load now: + vm_page *page_struct = get_vm_page(page_index); + if (page_struct->make_page) { // non empty page + if (disk_page_io_load_sync(&gc_io, page_struct->make_page)) panic("Could not load from disk"); + page = ph_malloc(PAGE_SIZE); + ph_memcpy(page, disk_page_io_data(&gc_io), PAGE_SIZE); + } + + gc_map_insert_nocheck(map, page_index, page); + return page; +} + +static const unsigned char *extract_header_part(unsigned char **pages, int start, int size) { + static char buffer[8]; + assert(size <= sizeof(buffer)); + + for (int i = 0; i < size; i++) { + long current_offset = start + i; + unsigned char curr_byte; + + if (current_offset < PAGE_SIZE) { + curr_byte = *(unsigned char*)(pages[0] + current_offset); + } else { + curr_byte = *(unsigned char*)(pages[1] + current_offset - PAGE_SIZE); + } + + buffer[i] = curr_byte; + } + + return buffer; +} + +static void write_header_part(unsigned char **pages, int start, int size, const unsigned char *data) +{ + assert(data && size > 0); + + for (int i = 0; i < size; i++) { + long current_offset = start + i; + + if (current_offset < PAGE_SIZE) { + *(pages[0] + current_offset) = data[i]; + } else { + *(pages[1] + current_offset - PAGE_SIZE) = data[i]; + } + } +} + +#define OBJ_FLAGS_OFFSET __offsetof(pvm_object_storage_t, _flags) +#define OBJ_FLAGS_SIZE sizeof(uint32_t) +#define OBJ_REFCNT_OFFSET __offsetof(pvm_object_storage_t, _ah.refCount) +#define OBJ_REFCNT_SIZE sizeof(int32_t) +#define OBJ_MARKER_OFFSET __offsetof(pvm_object_storage_t, _ah.object_start_marker) +#define OBJ_MARKER_SIZE sizeof(unsigned int) +#define OBJ_AFLAGS_OFFSET __offsetof(pvm_object_storage_t, _ah.alloc_flags) +#define OBJ_AFLAGS_SIZE sizeof(unsigned char) +#define OBJ_ESIZE_OFFSET __offsetof(pvm_object_storage_t, _ah.exact_size) +#define OBJ_ESIZE_SIZE sizeof(unsigned int) + +// if the object is childfree return NULL (since why waste time on them?) +static pvm_object_t gc_get_parent_object_image(gc_map_t *map, pvm_object_t real_object, bool *to_free) +{ + long page_index = addr_to_page_index((uintptr_t)real_object); + assert(page_index >= 0); + int object_offset = addr_to_page_offset((uintptr_t)real_object); + int flags_field_offset = object_offset + OBJ_FLAGS_OFFSET; + bool flags_on_first_page = flags_field_offset + OBJ_FLAGS_SIZE <= PAGE_SIZE; + *to_free = false; + + // Assuming object header (including `_flags` and `da_size`) fits on a single page + // (seems like a reasonable assumption tho) + unsigned char *base_pages[] = { + load_page(map, page_index), + !flags_on_first_page ? load_page(map, page_index + 1) : NULL + }; + + assert(base_pages[0]); // empty page cannot contain object header (can it?) + assert(base_pages[1] || flags_on_first_page); + + // check start marker + int start_marker_offset = object_offset + OBJ_MARKER_OFFSET; + unsigned int start_marker = *(unsigned int*)extract_header_part( + base_pages, start_marker_offset, OBJ_MARKER_SIZE); + assert(start_marker == PVM_OBJECT_START_MARKER); + + // check object image is allocated + int alloc_flags_offset = object_offset + OBJ_AFLAGS_OFFSET; + unsigned char alloc_flags = *(unsigned char*)extract_header_part(base_pages, + alloc_flags_offset, OBJ_AFLAGS_SIZE); + assert(alloc_flags & PVM_OBJECT_AH_ALLOCATOR_FLAG_ALLOCATED); + + // childfree check + uint32_t flags = *(uint32_t*)extract_header_part(base_pages, flags_field_offset, + OBJ_FLAGS_SIZE); + if (flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE) return NULL; + + int size_field_offset = object_offset + OBJ_ESIZE_OFFSET; + unsigned int exact_object_size = *(unsigned int*)extract_header_part( + base_pages, size_field_offset, OBJ_ESIZE_SIZE); + + long object_end_offset = object_offset + exact_object_size; + + if (object_end_offset <= PAGE_SIZE) { // whole object is in the first page + return base_pages[0] + object_offset; + } + + int pages_required = (object_end_offset + PAGE_SIZE - 1) / PAGE_SIZE; + unsigned char *obj_image = ph_malloc(exact_object_size); + unsigned char *cur = obj_image; + + ph_memcpy(cur, base_pages[0] + object_offset, PAGE_SIZE - object_offset); + cur += PAGE_SIZE - object_offset; + + for (int curr_page = 1; cur != obj_image + exact_object_size; curr_page++) { + long remaining_size = exact_object_size - (cur - obj_image); + assert(remaining_size > 0); + unsigned char *cur_page = load_page(map, page_index + curr_page); + int to_copy = remaining_size <= PAGE_SIZE ? remaining_size : PAGE_SIZE; + + if (cur_page) + ph_memcpy(cur, cur_page, to_copy); + else + ph_memset(cur, 0, to_copy); + cur += to_copy; + } + + *to_free = true; + return obj_image; +} + +static int32_t extract_real_refcount(gc_map_t *map, pvm_object_t real_object) { + long page_index = addr_to_page_index((uintptr_t)real_object); + assert(page_index >= 0); + int object_offset = addr_to_page_offset((uintptr_t)real_object); + int refcnt_offset = object_offset + OBJ_REFCNT_OFFSET; + bool refcnt_on_first_page = refcnt_offset + OBJ_REFCNT_SIZE <= PAGE_SIZE; + + unsigned char *base_pages[] = { + load_page(map, page_index), + !refcnt_on_first_page ? load_page(map, page_index + 1) : NULL + }; + + assert(base_pages[0]); + assert(base_pages[1] || refcnt_on_first_page); + int32_t refcount = *(int32_t*)extract_header_part( + base_pages, refcnt_offset, sizeof(int32_t)); + + return refcount; +} + +static void load_header_pages(gc_map_t *map, pvm_object_t real_object) { + long page_index = addr_to_page_index((uintptr_t)real_object); + assert(page_index >= 0); + int object_offset = addr_to_page_offset((uintptr_t)real_object); + int flags_field_offset = object_offset + OBJ_FLAGS_OFFSET; + bool flags_on_first_page = flags_field_offset + OBJ_FLAGS_SIZE <= PAGE_SIZE; + + load_page(map, page_index); + if (!flags_on_first_page) load_page(map, page_index + 1); +} + +gc_map_t *new_refcnt_map, *loaded_pages_map; + +static void mark_tree_incremental(pvm_object_t real_object, void *data) { + if (real_object == NULL) return; + int mark_mode = data ? 1 : 0; + + assert(data == NULL || (intptr_t)data == 1); + if (mark_mode == 1) { // reverse pass + uint64_t old_refcnt; // mark object as non-garbage + assert(gc_map_set_or_skip(new_refcnt_map, real_object, 0, &old_refcnt) == 0); + if (old_refcnt == 0) return; // was already marked, return + } else { + // local reference inc + // if refcount was non-zero, the object is already marked - return + if (gc_map_increment(new_refcnt_map, real_object) > 0) return; + } + + bool to_free = false; + // copy of the object + pvm_object_t object_image = gc_get_parent_object_image(loaded_pages_map, real_object, &to_free); + if (object_image == NULL) return; // object is childfree, return + // all the needed asserts and checks are performed in gc_get_parent_object_image + + gc_process_children(mark_tree_incremental, object_image, data); + + if (to_free) ph_free(object_image); +} + +static void gc_free_object_image(gc_map_t *map, pvm_object_t real_object, bool *is_modified) +{ + long page_index = addr_to_page_index((uintptr_t)real_object); + assert(page_index >= 0); + int object_offset = addr_to_page_offset((uintptr_t)real_object); + // assuming flags are further in the object than refcount + int alloc_flags_offset = object_offset + OBJ_AFLAGS_OFFSET; + int refcount_offset = object_offset + OBJ_REFCNT_OFFSET; + bool flags_on_first_page = alloc_flags_offset + OBJ_AFLAGS_SIZE <= PAGE_SIZE; + + uint64_t *in_map_addresses[] = { + __gc_map_try_get(map, page_index), + !flags_on_first_page ? __gc_map_try_get(map, page_index + 1) : NULL + }; + + unsigned char *pages[] = { + *in_map_addresses[0], flags_on_first_page ? NULL : *in_map_addresses[1] + }; + + // free image object + unsigned char new_aflags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; + int32_t new_refcnt = 0; + write_header_part(pages, alloc_flags_offset, OBJ_AFLAGS_SIZE, &new_aflags); + write_header_part(pages, refcount_offset, OBJ_REFCNT_SIZE, &new_refcnt); + + // mark page images dirty + is_modified[in_map_addresses[0] - map->values] = true; + if (!flags_on_first_page) { + is_modified[in_map_addresses[1] - map->values] = true; + } +} + +int freed_size = 0; + +extern void cycle_root_buffer_rm_candidate(pvm_object_storage_t *p); + +static void free_incremetnal(gc_map_t *map, pvm_object_t real_object, bool *is_modified) { + pvm_object_is_allocated_assert(real_object); + + if (real_object->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) { + int syscall_id = pvm_object_da(real_object->_class, class)->sys_table_id; + gc_finalizer_func_t func = pvm_internal_classes[syscall_id].finalizer; + + if (func != 0) + func(real_object); + + // should run ref_dec for children? + // yes, probably + } + + // free real object + real_object->_ah.refCount = 0; + real_object->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; + freed_size += real_object->_ah.exact_size; + + if ( !(real_object->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE) ) + cycle_root_buffer_rm_candidate(real_object); + + gc_free_object_image(map, real_object, is_modified); +} + +#define get_array_slot_nocheck(arr, i) ((pvm_object_t*)(pvm_data_area(arr, array)->page->da))[i] + +// we will run on the unfinished snapshot - no need for protection from deletion +void run_gc_incremental(pvm_object_t cycle_candidates) { + SHOW_INFO0(1, "GC LIGHT: START"); + uint64_t start_time = hal_system_time(); + // gc buffer only contains objects with non-zero refcount (== no invalid/freed objects) + assert(cycle_candidates); + gc_map_t new_refcnt, loaded_pages; + gc_map_init(&new_refcnt); gc_map_init(&loaded_pages); + new_refcnt_map = &new_refcnt; + loaded_pages_map = &loaded_pages; + + disk_page_io_init(&gc_io); + + SHOW_INFO(1, "GC LIGHT: Initialized. Objects to process: %d", pvm_get_array_size(cycle_candidates)); + // recount references (forward pass) + for (int i = 0; i < pvm_get_array_size(cycle_candidates); i++) { + mark_tree_incremental(get_array_slot_nocheck(cycle_candidates, i), 0); + } + + SHOW_INFO(1, "GC LIGHT: Forward pass done. Pages loaded: %d", loaded_pages.count); + // find objects with external references (reverse pass) + for (int i = 0; i < new_refcnt.count; i++) { + pvm_object_t object = (pvm_object_t) new_refcnt.keys[i]; + int64_t counted_refs = new_refcnt.values[i]; + if (counted_refs == 0) continue; // marked as non-garbage in earlier iterations + // all candidates have 1 extra reference counted + for (int i = 0; i < pvm_get_array_size(cycle_candidates); i++) { + if (get_array_slot_nocheck(cycle_candidates, i) == object) { + counted_refs--; + break; + } + } + int32_t actual_refs = extract_real_refcount(loaded_pages_map, object); + if (counted_refs == actual_refs) continue; // potential garbage + if (counted_refs > actual_refs) { + SHOW_ERROR(1, "Too many references counted: %d/%d @%p", + counted_refs, actual_refs, object); + dumpo(object); + continue; // replace with panic later? + } + + // counted less than actual - there is an external reference + mark_tree_incremental(object, 1); // reverse pass + } + + SHOW_INFO0(1, "GC LIGHT: Reverse pass done"); + int freed_count = 0; + freed_size = 0; + // free garbage, mark dirty pages to page out + // +4 for pages that *may* be required for `cycle_candidates` + bool *is_modified = ph_calloc(loaded_pages.count + 4, sizeof(bool)); + for (int i = 0; i < new_refcnt.count; i++) { + pvm_object_t object = (pvm_object_t) new_refcnt.keys[i]; + + if (new_refcnt.values[i] == 0) continue; // not garbage + // ph_printf("Freeing: "); + // pvm_object_print(pvm_data_area(object->_class, class)->class_name); + // ph_printf("\n"); + free_incremetnal(loaded_pages_map, object, is_modified); + freed_count++; + } + + // remove cycle candidates array from snapshot too + pvm_object_t array_page = pvm_data_area(cycle_candidates, array)->page; + if (array_page) { + load_header_pages(loaded_pages_map, array_page); + free_incremetnal(loaded_pages_map, array_page, is_modified); + } + load_header_pages(loaded_pages_map, cycle_candidates); + free_incremetnal(loaded_pages_map, cycle_candidates, is_modified); + + SHOW_INFO0(1, "GC LIGHT: Pageout..."); + // sync pageout of dirty pages + int pages_written = 0; + //void *gc_io_mem = gc_io.mem; + for (int i = 0; i < loaded_pages.count; i++) { + if (!loaded_pages.values[i]) continue; + + if (is_modified[i]) { + vm_page *page_struct = get_vm_page(loaded_pages.keys[i]); + // should figure out if it is possible to directly write from loaded_pages.values[i] + //gc_io.mem = loaded_pages.values[i]; + ph_memcpy(disk_page_io_data(&gc_io), loaded_pages.values[i], PAGE_SIZE); + + if (disk_page_io_save_sync(&gc_io, page_struct->make_page)) panic("Could not save to disk"); + pages_written++; + + assert(page_struct->make_page); + } + + ph_free((void*) loaded_pages.values[i]); + } + //gc_io.mem = gc_io_mem; + + SHOW_INFO(1, "GC LIGHT: Pageout done. Pages written: %d", pages_written); + disk_page_io_finish(&gc_io); + gc_map_release(&new_refcnt); + gc_map_release(&loaded_pages); + + SHOW_INFO0(1, "GC LIGHT: FINISH"); + uint64_t end_time = hal_system_time(); + SHOW_INFO(1, "GC stats: pages loaded: %d, objects freed: %d, objects iterated: %d. Elapsed: %d ms", + loaded_pages.count, freed_count, new_refcnt.count, (end_time - start_time) / 1000); + SHOW_INFO(1, "GC stats: freed %d KB (%d bytes)", freed_size / 1024, freed_size); +} + +// silently delete object +void release_gc_buffer(pvm_object_t gc_buffer) { + if (gc_buffer == NULL) return; + + pvm_object_t p = pvm_data_area(gc_buffer, array)->page; + if (p) { + p->_ah.refCount = 0; + p->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; + } + + gc_buffer->_ah.refCount = 0; + gc_buffer->_ah.alloc_flags = PVM_OBJECT_AH_ALLOCATOR_FLAG_FREE; } static void mark_tree(pvm_object_storage_t *obj_in_snap) { @@ -231,7 +699,7 @@ static void gc_process_children(gc_iterator_call_t f, pvm_object_storage_t *obj_ // Now find and call class-specific function: pvm_gc_iter_* // ph_printf("Internal object, get iter method\n"); - gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(shift_ptr(obj_in_snap->_class, shift), class)-> + gc_iterator_func_t iter = pvm_internal_classes[pvm_object_da(obj_in_snap->_class, class)-> sys_table_id].iter; iter(f, obj_in_snap, arg); @@ -253,6 +721,8 @@ static pvm_object_storage_t **collect_unmarked(char *start) { } } + LOG_INFO_(5, "Found %d objects to free", freed); + pvm_object_storage_t **to_free = ph_calloc((freed + 1), sizeof(pvm_object_storage_t *)); int i = 0; @@ -273,11 +743,13 @@ static pvm_object_storage_t **collect_unmarked(char *start) { static int free_unmarked(pvm_object_storage_t **to_free) { int i = 0; + long long freed_size = 0; vm_lock_persistent_memory(); while (to_free[i] != 0) { pvm_object_storage_t *p = to_free[i]; - ph_printf("Freeing object %p\n", p); + pvm_object_is_allocated_assert(p); + freed_size += p->_ah.exact_size; if (p->_flags & PHANTOM_OBJECT_STORAGE_FLAG_IS_FINALIZER) { // based on the assumption that finalizer is only valid for some internal childfree objects - is it correct? @@ -294,4 +766,8 @@ static int free_unmarked(pvm_object_storage_t **to_free) { i++; } vm_unlock_persistent_memory(); + + LOG_INFO_(5, "GC finished: freed %d KB", freed_size / 1024); + + return i; } diff --git a/src/phantom/vm/internal.c b/src/phantom/vm/internal.c index d3194a7f4..093270323 100755 --- a/src/phantom/vm/internal.c +++ b/src/phantom/vm/internal.c @@ -213,11 +213,11 @@ struct internal_class pvm_internal_classes[] = PVM_ROOT_OBJECT_TTY_CLASS, syscall_table_4_tty, &n_syscall_table_4_tty, pvm_internal_init_tty, - 0 /*pvm_gc_iter_tty*/, + pvm_gc_iter_tty, pvm_gc_finalizer_tty, // no finalizer pvm_restart_tty, sizeof(struct data_area_4_tty), - PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL|PHANTOM_OBJECT_STORAGE_FLAG_IS_CHILDFREE, + PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL, 0 }, /* { diff --git a/src/phantom/vm/object.c b/src/phantom/vm/object.c index c09065549..bff3b6e3f 100755 --- a/src/phantom/vm/object.c +++ b/src/phantom/vm/object.c @@ -59,7 +59,7 @@ pvm_object_t pvm_get_array_ofield(pvm_object_t o, unsigned int slot ) !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) ) { - dumpo(o); + dumpo((addr_t)o); pvm_exec_panic0( "attempt to do get_ofield to non-array" ); } @@ -80,7 +80,7 @@ void pvm_set_array_ofield(pvm_object_t o, unsigned int slot, pvm_object_t value !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) || !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) ) { - dumpo(o); + dumpo((addr_t)o); pvm_exec_panic0( "attempt to do set_ofield to non-array" ); } @@ -143,7 +143,7 @@ void pvm_pop_array(pvm_object_t array, pvm_object_t value_to_pop ) !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (array->_flags) ) ) { pvm_exec_panic0( "attempt to do pop to non-array" ); - dumpo(array); + dumpo((addr_t)array); } if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (array->_flags) ) @@ -168,6 +168,28 @@ void pvm_pop_array(pvm_object_t array, pvm_object_t value_to_pop ) pvm_exec_panic0( "attempt to remove non existing element from array" ); } +void pvm_clear_array(pvm_object_t array) { + struct data_area_4_array *da = (struct data_area_4_array *)&(array->da); + + verify_p(array); + if( + !(PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (array->_flags) ) || + !( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (array->_flags) ) + ) { + pvm_exec_panic0( "attempt to clear non-array" ); + dumpo((addr_t)array); + } + + if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (array->_flags) ) + pvm_exec_panic0( "attempt to clear immutable array" ); + + if (da->page) { + pvm_object_t *p = da_po_ptr((da->page)->da); + ph_memset(p, 0, da->page_size * sizeof(pvm_object_t)); // clean page to avoid refdecs on contained objects + } + da->page_size = 16; + da->used_slots = 0; +} /** @@ -254,6 +276,33 @@ pvm_set_field( pvm_object_t o, unsigned int slot, pvm_object_t value ) if(da_po_ptr(o->da)[slot]) ref_dec_o(da_po_ptr(o->da)[slot]); //decr old value da_po_ptr(o->da)[slot] = value; } + +void +pvm_set_field_norefdec( pvm_object_t o, unsigned int slot, pvm_object_t value ) +{ + verify_p(o); + verify_o(value); + + if( PHANTOM_OBJECT_STORAGE_FLAG_IS_IMMUTABLE & (o->_flags) ) + pvm_exec_panic0( "attempt to set_field for immutable" ); + + if( PHANTOM_OBJECT_STORAGE_FLAG_IS_INTERNAL & (o->_flags) ) + { + if( PHANTOM_OBJECT_STORAGE_FLAG_IS_RESIZEABLE & (o->_flags) ) + { + pvm_set_array_ofield( o, slot, value ); + return; + } + pvm_exec_panic0( "attempt to save to internal" ); + } + + if( slot >= da_po_limit(o) ) + { + pvm_exec_panic0( "set: slot index out of bounds" ); + } + + da_po_ptr(o->da)[slot] = value; +} /* void pvm_set_ofield( pvm_object_t op, unsigned int slot, pvm_object_t value ) diff --git a/src/phantom/vm/root.c b/src/phantom/vm/root.c index a513d9538..d84821e6d 100755 --- a/src/phantom/vm/root.c +++ b/src/phantom/vm/root.c @@ -59,6 +59,7 @@ static void runclass(int, char **); static void process_generic_restarts(pvm_object_t root); static void process_specific_restarts(void); +extern void release_gc_buffer(pvm_object_t gc_buffer); /** * @@ -120,6 +121,12 @@ void pvm_root_init(void) pvm_root.root_dir = pvm_get_field( root, PVM_ROOT_OBJECT_ROOT_DIR ); pvm_root.kernel_stats = pvm_get_field( root, PVM_ROOT_KERNEL_STATISTICS ); pvm_root.class_dir = pvm_get_field( root, PVM_ROOT_CLASS_DIR ); + // currently snapshot contains the old *deleted* buffer, replace with a fresh one + pvm_set_field_norefdec(root, PVM_ROOT_GC_BUFFER, pvm_create_array_object()); // -- + pvm_root.gc_buffer = pvm_get_field( root, PVM_ROOT_GC_BUFFER ); + pvm_root.gc_buffer_old = pvm_get_field( root, PVM_ROOT_GC_BUFFER_OLD ); + assert(pvm_is_null(pvm_root.gc_buffer_old)); + // release_gc_buffer(pvm_consume_gc_buffer_old()); // delete old gc buffer (from reality) process_specific_restarts(); @@ -233,6 +240,8 @@ static void pvm_save_root_objects() pvm_set_field( root, PVM_ROOT_KERNEL_STATISTICS, pvm_root.kernel_stats ); pvm_set_field( root, PVM_ROOT_CLASS_DIR, pvm_root.class_dir ); + pvm_set_field( root, PVM_ROOT_GC_BUFFER, pvm_root.gc_buffer ); + pvm_set_field( root, PVM_ROOT_GC_BUFFER_OLD, pvm_root.gc_buffer_old ); } @@ -321,6 +330,7 @@ static void pvm_create_root_objects() pvm_root.kernel_stats = pvm_create_binary_object( STAT_CNT_PERSISTENT_DA_SIZE, 0 ); pvm_root.class_dir = pvm_create_directory_object(); + pvm_root.gc_buffer = pvm_create_array_object(); ref_saturate_o(pvm_root.threads_list); //Need it? @@ -747,6 +757,24 @@ int pvm_disconnect_object(pvm_object_t o, struct data_area_4_thread *tc) return phantom_disconnect_object( da ); } +pvm_object_t pvm_get_gc_buffer() { + return pvm_root.gc_buffer; +} +pvm_object_t pvm_consume_gc_buffer_old() { + pvm_object_t old_buffer = pvm_root.gc_buffer_old; + pvm_root.gc_buffer_old = NULL; + pvm_object_t root = get_root_object_storage(); + pvm_set_field_norefdec( root, PVM_ROOT_GC_BUFFER_OLD, pvm_root.gc_buffer_old ); + return old_buffer; +} +void pvm_swap_gc_buffers() { + assert(pvm_root.gc_buffer_old == NULL); + pvm_root.gc_buffer_old = pvm_root.gc_buffer; + pvm_root.gc_buffer = pvm_create_array_object(); + pvm_object_t root = get_root_object_storage(); + pvm_set_field_norefdec( root, PVM_ROOT_GC_BUFFER, pvm_root.gc_buffer ); + pvm_set_field_norefdec( root, PVM_ROOT_GC_BUFFER_OLD, pvm_root.gc_buffer_old ); +} diff --git a/src/phantom/vm/stacks.c b/src/phantom/vm/stacks.c index fc1f6d9dd..463b94c43 100755 --- a/src/phantom/vm/stacks.c +++ b/src/phantom/vm/stacks.c @@ -713,7 +713,7 @@ void pvm_internal_init_istack(pvm_object_t os ) void pvm_gc_iter_istack(gc_iterator_call_t func, pvm_object_t os, void *arg) { - struct data_area_4_object_stack *da = (struct data_area_4_object_stack *)&(os->da); + struct data_area_4_integer_stack *da = (struct data_area_4_integer_stack *)&(os->da); // No objects in the integer stack, but please visit linked list ifself diff --git a/src/phantom/vm/sys/i_io.c b/src/phantom/vm/sys/i_io.c index dd7ab9520..903d412d0 100644 --- a/src/phantom/vm/sys/i_io.c +++ b/src/phantom/vm/sys/i_io.c @@ -435,11 +435,7 @@ void pvm_gc_iter_io(gc_iterator_call_t func, pvm_object_t os, void *arg) { struct data_area_4_io *da = (struct data_area_4_io *)os->da; - (void) da; - - //gc_fcall( func, arg, ot ); - //gc_fcall( func, arg, da->p_kernel_state_object ); - //gc_fcall( func, arg, da->callback ); + func(da->name, arg); } diff --git a/src/phantom/vm/syscall_tty.c b/src/phantom/vm/syscall_tty.c index f4fbc855e..c6c793cae 100755 --- a/src/phantom/vm/syscall_tty.c +++ b/src/phantom/vm/syscall_tty.c @@ -360,10 +360,9 @@ void pvm_internal_init_tty( pvm_object_t ttyos ) void pvm_gc_iter_tty(gc_iterator_call_t func, pvm_object_t os, void *arg) { - (void) func; - (void) os; - (void) arg; - // Empty + struct data_area_4_tty *tty = (struct data_area_4_tty *)os->da; + + func(tty->o_pixels, arg); } void pvm_gc_finalizer_tty( pvm_object_t os ) diff --git a/src/phantom/vm/syscall_win.c b/src/phantom/vm/syscall_win.c index 6cdc3b301..1646250af 100755 --- a/src/phantom/vm/syscall_win.c +++ b/src/phantom/vm/syscall_win.c @@ -232,6 +232,7 @@ static int win_setSize_26( pvm_object_t me, pvm_object_t *ret, struct data_area_ struct data_area_4_window *da = pvm_data_area( me, window ); //struct data_area_4_binary *bda = (struct data_area_4_binary *)da->o_pixels->da; //window_handle_t w = (window_handle_t)&bda->data; + (void) da; CHECK_PARAM_COUNT(2); From a2021e4b3e8a489a8604245c875ff1f0f14fc2ff Mon Sep 17 00:00:00 2001 From: Arseny Yusufov Date: Tue, 3 Sep 2024 02:38:37 +0200 Subject: [PATCH 14/14] add tests for gc --- src/plib/sys/Makefile | 3 +- src/plib/sys/src/ru.dz/ru.dz.demo.garbage.ph | 48 +++++++++++++++++++ .../sys/src/ru.dz/ru.dz.demo.garbage_unit.ph | 28 +++++++++++ src/plib/sys/src/ru.dz/ru.dz.demo.start.ph | 20 ++++---- .../src/ru.dz/ru.dz.phantom.system.shell.ph | 10 +--- 5 files changed, 90 insertions(+), 19 deletions(-) create mode 100755 src/plib/sys/src/ru.dz/ru.dz.demo.garbage.ph create mode 100755 src/plib/sys/src/ru.dz/ru.dz.demo.garbage_unit.ph diff --git a/src/plib/sys/Makefile b/src/plib/sys/Makefile index ff9a550bf..020ff9e93 100755 --- a/src/plib/sys/Makefile +++ b/src/plib/sys/Makefile @@ -74,8 +74,9 @@ $(BINDIR)/phantom.os.pc: phantom.os.time.pc phantom.osimpl.pc internal.world.pc $(BINDIR)/phantom.util.hashmap.pc: phantom.util.hashpair.pc $(BINDIR)/ru.dz.demo.chart.pc: phantom.os.pc internal.io.tty.pc internal.window.pc internal.connection.pc ru.dz.phantom.system.runnable.pc -$(BINDIR)/ru.dz.demo.start.pc: ru.dz.demo.weather.pc ru.dz.demo.chart.pc +$(BINDIR)/ru.dz.demo.start.pc: ru.dz.demo.weather.pc ru.dz.demo.chart.pc ru.dz.demo.wasm.pc ru.dz.phantom.persistence_test.pc ru.dz.phantom.performance_test.pc ru.dz.demo.garbage.pc $(BINDIR)/ru.dz.demo.weather.pc: ru.dz.demo.chart.pc internal.bitmap.pc +$(BINDIR)/ru.dz.demo.garbage.pc: ru.dz.demo.garbage_unit.pc $(BINDIR)/ru.dz.phantom.backgrounds.pc: ../resources/backgrounds/phantom_dz_new_1024_768.ppm diff --git a/src/plib/sys/src/ru.dz/ru.dz.demo.garbage.ph b/src/plib/sys/src/ru.dz/ru.dz.demo.garbage.ph new file mode 100755 index 000000000..8638e8509 --- /dev/null +++ b/src/plib/sys/src/ru.dz/ru.dz.demo.garbage.ph @@ -0,0 +1,48 @@ +/** + * + * Phantom OS - Phantom language library + * +**/ + +package .ru.dz.demo; + +import .phantom.os; +import .internal.io.tty; +import .internal.string; +import .internal.connection; +import .ru.dz.demo.garbage_unit; + +class garbage +{ + void run(var console : .internal.io.tty) + { + console.putws("Started garbage generation demo scenario\n"); + + var sleep : .internal.connection; + sleep = new .internal.connection(); + sleep.connect("tmr:"); + + var garbage_created : .internal.int; + garbage_created = 0; + while (1) { + var A : garbage_unit; + var B : garbage_unit; + var C : garbage_unit; + A = new garbage_unit(); + B = new garbage_unit(); + C = new garbage_unit(); + + A.load_payload(); + A.set_next(B); + B.set_next(C); + C.set_next(A); + + garbage_created = garbage_created + 3; + console.putws("Iteration complete, total garbage created: "); + console.putws(garbage_created.toString()); + console.putws("\n"); + sleep.block(null, 25); + } + } +}; + diff --git a/src/plib/sys/src/ru.dz/ru.dz.demo.garbage_unit.ph b/src/plib/sys/src/ru.dz/ru.dz.demo.garbage_unit.ph new file mode 100755 index 000000000..1823a17ed --- /dev/null +++ b/src/plib/sys/src/ru.dz/ru.dz.demo.garbage_unit.ph @@ -0,0 +1,28 @@ +/** + * + * Phantom OS - Phantom language library + * +**/ + +package .ru.dz.demo; + +import .internal.string; + +class garbage_unit +{ + var next : garbage_unit; + var payload : .internal.string; + + void load_payload() { + payload = load_existing_payload(); + } + + void set_next(var n : garbage_unit) { + next = n; + } + + .internal.string load_existing_payload() { + return import "../resources/test_images/cat.jpg" ; + } +}; + diff --git a/src/plib/sys/src/ru.dz/ru.dz.demo.start.ph b/src/plib/sys/src/ru.dz/ru.dz.demo.start.ph index c5216f4e3..f633d884d 100755 --- a/src/plib/sys/src/ru.dz/ru.dz.demo.start.ph +++ b/src/plib/sys/src/ru.dz/ru.dz.demo.start.ph @@ -14,26 +14,26 @@ package .ru.dz.demo; import .phantom.os; import .internal.io.tty; +import .ru.dz.phantom.performance_test; +import .ru.dz.phantom.persistence_test; import .ru.dz.demo.weather; import .ru.dz.demo.chart; +import .ru.dz.demo.wasm; +import .ru.dz.demo.garbage; attribute const * ->!; class start { - var wv : .ru.dz.demo.weather; - // var cv : .ru.dz.demo.chart; + var demo : .ru.dz.demo.garbage; + // var demo : .ru.dz.demo.weather; + // var demo : .ru.dz.demo.wasm; void run(var console : .internal.io.tty) { - //cv = new .ru.dz.demo.chart(); - //cv.start(console); - - wv = new .ru.dz.demo.weather(); - wv.run(console); - + // demo = new .ru.dz.demo.weather(); + demo = new .ru.dz.demo.garbage(); + demo.run(console); } - }; - diff --git a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph index f560bb9a9..920d30248 100755 --- a/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph +++ b/src/plib/sys/src/ru.dz/ru.dz.phantom.system.shell.ph @@ -21,10 +21,7 @@ import .ru.dz.phantom.system.runnable; import .ru.dz.phantom.system.shell_callback; //import .test.suite; -import .ru.dz.demo.wasm; import .ru.dz.demo.start; -import .ru.dz.phantom.persistence_test; -import .ru.dz.phantom.performance_test; attribute const * ->!; @@ -54,9 +51,7 @@ class shell extends runnable //var mtx : .internal.mutex; - var demo : .ru.dz.demo.wasm; - // var demo : .ru.dz.demo.start; - // var demo : .ru.dz.phantom.persistence_test; + var demo : .ru.dz.demo.start; /* void init() { @@ -114,8 +109,7 @@ class shell extends runnable stat_conn = new .internal.connection(); stat_conn.connect("stt:"); - //demo = new .ru.dz.demo.start(); - demo = new .ru.dz.demo.wasm(); + demo = new .ru.dz.demo.start(); demo.run(console); while(1)