mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
coroutines: fix segfaults with GC (part 1) (#20549)
This commit is contained in:
parent
5f7e6ff13a
commit
f79dd79242
6 changed files with 94 additions and 28 deletions
23
thirdparty/photon/photonwrapper.h
vendored
23
thirdparty/photon/photonwrapper.h
vendored
|
@ -19,24 +19,39 @@
|
|||
#include <iostream>
|
||||
|
||||
extern "C" {
|
||||
// using namespace photon;
|
||||
|
||||
// WorkPool* work_pool;
|
||||
// WorkPool* new_photon_work_pool();
|
||||
photon::WorkPool* work_pool;
|
||||
|
||||
// using namespace photon;
|
||||
// typedef WorkPool PhotonWorkPool;
|
||||
// typedef photon::WorkPool PhotonWorkPool1;
|
||||
#else
|
||||
#endif
|
||||
|
||||
// using namespace photon;
|
||||
// typedef WorkPool PhotonWorkPool;
|
||||
// typedef photon::WorkPool PhotonWorkPool;
|
||||
// typedef WorkPool PhotonWorkPool;
|
||||
// typedef PhotonWorkPool1 PhotonWorkPool;
|
||||
// PhotonWorkPool* new_photon_work_pool();
|
||||
void* new_photon_work_pool(size_t);
|
||||
// void delete_photon_work_pool(void*);
|
||||
void delete_photon_work_pool();
|
||||
// custom v functions
|
||||
void init_photon_work_pool(size_t);
|
||||
// void photon_thread_migrate();
|
||||
// void photon_thread_migrate(void*);
|
||||
void photon_thread_create_and_migrate_to_work_pool(void* (* f)(void*), void* arg);
|
||||
// void photon_thread_create_and_migrate_to_work_pool(void*, void* (* f)(void*), void* arg);
|
||||
// direct wrappers to photon functions
|
||||
int photon_init_default();
|
||||
void photon_thread_create(void* (* f)(void*), void* arg);
|
||||
void photon_sleep_s(int n);
|
||||
void photon_sleep_ms(int n);
|
||||
|
||||
// void* default_photon_thread_stack_alloc(void*, size_t size);
|
||||
// void default_photon_thread_stack_dealloc(void*, void* ptr, size_t size);
|
||||
void* default_photon_thread_stack_alloc(void*, size_t size);
|
||||
void default_photon_thread_stack_dealloc(void*, void* ptr, size_t size);
|
||||
void set_photon_thread_stack_allocator(
|
||||
void* (*alloc_func)(void*, size_t),
|
||||
void (*dealloc_func)(void*, void*, size_t)
|
||||
|
|
|
@ -143,5 +143,16 @@ pub fn gc_check_leaks() {
|
|||
fn C.GC_get_heap_usage_safe(pheap_size &usize, pfree_bytes &usize, punmapped_bytes &usize, pbytes_since_gc &usize, ptotal_bytes &usize)
|
||||
fn C.GC_get_memory_use() usize
|
||||
|
||||
pub struct C.GC_stack_base {
|
||||
mem_base voidptr
|
||||
// reg_base voidptr
|
||||
}
|
||||
|
||||
// pub struct C.GC_stack_base{}
|
||||
|
||||
fn C.GC_get_stack_base(voidptr)
|
||||
fn C.GC_register_my_thread(voidptr) int
|
||||
fn C.GC_unregister_my_thread() int
|
||||
|
||||
fn C.GC_add_roots(voidptr, voidptr)
|
||||
fn C.GC_remove_roots(voidptr, voidptr)
|
||||
|
|
|
@ -11,45 +11,77 @@ import time
|
|||
|
||||
#include "photonwrapper.h"
|
||||
|
||||
// struct C.WorkPool {}
|
||||
// fn C.new_photon_work_pool) C.WorkPool
|
||||
fn C.set_photon_thread_stack_allocator(fn (voidptr, int) voidptr, fn (voidptr, voidptr, int))
|
||||
fn C.default_photon_thread_stack_alloc(voidptr, int) voidptr
|
||||
fn C.default_photon_thread_stack_dealloc(voidptr, voidptr, int)
|
||||
fn C.new_photon_work_pool(int) voidptr
|
||||
fn C.delete_photon_work_pool()
|
||||
fn C.init_photon_work_pool(int)
|
||||
|
||||
// fn C.photon_thread_create_and_migrate_to_work_pool(f voidptr, arg voidptr)
|
||||
fn C.init_photon_manual(int, fn ())
|
||||
fn C.init_photon_manual2(fn (), fn ())
|
||||
fn C.photon_thread_create_and_migrate_to_work_pool(f voidptr, arg voidptr)
|
||||
fn C.photon_thread_create(f voidptr, arg voidptr)
|
||||
fn C.photon_thread_migrate()
|
||||
|
||||
// fn C.photon_thread_migrate(work_pool voidptr)
|
||||
fn C.photon_init_default() int
|
||||
|
||||
fn C.photon_sleep_s(n int)
|
||||
fn C.photon_sleep_ms(n int)
|
||||
fn C.set_photon_thread_stack_allocator(fn (voidptr, int) voidptr, fn (voidptr, voidptr, int))
|
||||
|
||||
// sleep is coroutine-safe version of time.sleep()
|
||||
pub fn sleep(duration time.Duration) {
|
||||
C.photon_sleep_ms(duration.milliseconds())
|
||||
}
|
||||
|
||||
fn alloc(_ voidptr, stack_size int) voidptr {
|
||||
// println('## alloc called')
|
||||
unsafe {
|
||||
// thread_id := C.pthread_self()
|
||||
// println('## Thread ID: $thread_id')
|
||||
|
||||
// $if gcboehm ? {
|
||||
// mut sb := C.GC_stack_base{}
|
||||
// C.GC_get_stack_base(&sb)
|
||||
// C.GC_register_my_thread(&sb)
|
||||
// // res = C.GC_register_my_thread(&sb)
|
||||
// // println('## RES: $res')
|
||||
// }
|
||||
|
||||
// NOTE: when using malloc (GC_MALLOC) we get a segfault
|
||||
// when migrating from a new thread to a work pool thread
|
||||
// stack_ptr := malloc(stack_size)
|
||||
// stack_ptr := C.malloc(stack_size)
|
||||
stack_ptr := C.default_photon_thread_stack_alloc(nil, stack_size)
|
||||
|
||||
$if gcboehm ? {
|
||||
C.GC_add_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||
}
|
||||
|
||||
return stack_ptr
|
||||
}
|
||||
}
|
||||
|
||||
fn dealloc(_ voidptr, stack_ptr voidptr, stack_size int) {
|
||||
// println('## dealloc called')
|
||||
unsafe {
|
||||
$if gcboehm ? {
|
||||
// C.GC_unregister_my_thread()
|
||||
C.GC_remove_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||
}
|
||||
// free(stack_ptr)
|
||||
C.default_photon_thread_stack_dealloc(nil, stack_ptr, stack_size)
|
||||
}
|
||||
}
|
||||
|
||||
fn init() {
|
||||
alloc := fn (_ voidptr, stack_size int) voidptr {
|
||||
unsafe {
|
||||
stack_ptr := malloc(stack_size)
|
||||
$if gcboehm ? {
|
||||
C.GC_add_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||
}
|
||||
return stack_ptr
|
||||
}
|
||||
}
|
||||
dealloc := fn (_ voidptr, stack_ptr voidptr, stack_size int) {
|
||||
unsafe {
|
||||
$if gcboehm ? {
|
||||
C.GC_remove_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||
}
|
||||
free(stack_ptr)
|
||||
}
|
||||
}
|
||||
C.set_photon_thread_stack_allocator(alloc, dealloc)
|
||||
ret := C.photon_init_default()
|
||||
if util.nr_jobs > 0 {
|
||||
|
||||
if util.nr_jobs >= 1 {
|
||||
C.init_photon_work_pool(util.nr_jobs)
|
||||
}
|
||||
|
||||
if ret < 0 {
|
||||
panic('failed to initialize coroutines via photon (ret=${ret})')
|
||||
}
|
||||
|
|
|
@ -6173,6 +6173,9 @@ fn (mut g Gen) write_init_function() {
|
|||
for x in cleaning_up_array.reverse() {
|
||||
g.writeln(x)
|
||||
}
|
||||
if g.pref.use_coroutines {
|
||||
g.writeln('\tdelete_photon_work_pool();')
|
||||
}
|
||||
g.writeln('}')
|
||||
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
||||
println(g.out.after(fn_vcleanup_start_pos))
|
||||
|
|
|
@ -110,7 +110,10 @@ fn (mut g Gen) gen_c_main_header() {
|
|||
g.writeln('\tGC_set_find_leak(1);')
|
||||
}
|
||||
g.writeln('\tGC_set_pages_executable(0);')
|
||||
// NOTE: required when using GC_MALLOC & GC_register_my_thread
|
||||
// g.writeln('\tGC_allow_register_threads();')
|
||||
g.writeln('\tGC_INIT();')
|
||||
|
||||
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
||||
g.writeln('\tGC_enable_incremental();')
|
||||
}
|
||||
|
@ -242,6 +245,8 @@ pub fn (mut g Gen) gen_c_main_for_tests() {
|
|||
g.writeln('\tGC_set_find_leak(1);')
|
||||
}
|
||||
g.writeln('\tGC_set_pages_executable(0);')
|
||||
// NOTE: required when using GC_MALLOC & GC_register_my_thread
|
||||
// g.writeln('\tGC_allow_register_threads();')
|
||||
g.writeln('\tGC_INIT();')
|
||||
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
||||
g.writeln('\tGC_enable_incremental();')
|
||||
|
|
|
@ -162,7 +162,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
|
|||
}
|
||||
}
|
||||
} else if is_go {
|
||||
if util.nr_jobs > 0 {
|
||||
if util.nr_jobs > 1 {
|
||||
g.writeln('photon_thread_create_and_migrate_to_work_pool((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
||||
} else {
|
||||
g.writeln('photon_thread_create((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue