mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42: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>
|
#include <iostream>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// using namespace photon;
|
|
||||||
// WorkPool* work_pool;
|
// WorkPool* work_pool;
|
||||||
// WorkPool* new_photon_work_pool();
|
|
||||||
photon::WorkPool* work_pool;
|
photon::WorkPool* work_pool;
|
||||||
|
|
||||||
|
// using namespace photon;
|
||||||
|
// typedef WorkPool PhotonWorkPool;
|
||||||
|
// typedef photon::WorkPool PhotonWorkPool1;
|
||||||
#else
|
#else
|
||||||
#endif
|
#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
|
// custom v functions
|
||||||
void init_photon_work_pool(size_t);
|
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* (* f)(void*), void* arg);
|
||||||
|
// void photon_thread_create_and_migrate_to_work_pool(void*, void* (* f)(void*), void* arg);
|
||||||
// direct wrappers to photon functions
|
// direct wrappers to photon functions
|
||||||
int photon_init_default();
|
int photon_init_default();
|
||||||
void photon_thread_create(void* (* f)(void*), void* arg);
|
void photon_thread_create(void* (* f)(void*), void* arg);
|
||||||
void photon_sleep_s(int n);
|
void photon_sleep_s(int n);
|
||||||
void photon_sleep_ms(int n);
|
void photon_sleep_ms(int n);
|
||||||
|
|
||||||
// void* default_photon_thread_stack_alloc(void*, 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 default_photon_thread_stack_dealloc(void*, void* ptr, size_t size);
|
||||||
void set_photon_thread_stack_allocator(
|
void set_photon_thread_stack_allocator(
|
||||||
void* (*alloc_func)(void*, size_t),
|
void* (*alloc_func)(void*, size_t),
|
||||||
void (*dealloc_func)(void*, 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_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
|
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_add_roots(voidptr, voidptr)
|
||||||
fn C.GC_remove_roots(voidptr, voidptr)
|
fn C.GC_remove_roots(voidptr, voidptr)
|
||||||
|
|
|
@ -11,45 +11,77 @@ import time
|
||||||
|
|
||||||
#include "photonwrapper.h"
|
#include "photonwrapper.h"
|
||||||
|
|
||||||
// struct C.WorkPool {}
|
fn C.set_photon_thread_stack_allocator(fn (voidptr, int) voidptr, fn (voidptr, voidptr, int))
|
||||||
// fn C.new_photon_work_pool) C.WorkPool
|
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.init_photon_work_pool(int)
|
||||||
|
fn C.init_photon_manual(int, fn ())
|
||||||
// fn C.photon_thread_create_and_migrate_to_work_pool(f voidptr, arg voidptr)
|
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_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_init_default() int
|
||||||
|
|
||||||
fn C.photon_sleep_s(n int)
|
fn C.photon_sleep_s(n int)
|
||||||
fn C.photon_sleep_ms(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()
|
// sleep is coroutine-safe version of time.sleep()
|
||||||
pub fn sleep(duration time.Duration) {
|
pub fn sleep(duration time.Duration) {
|
||||||
C.photon_sleep_ms(duration.milliseconds())
|
C.photon_sleep_ms(duration.milliseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init() {
|
fn alloc(_ voidptr, stack_size int) voidptr {
|
||||||
alloc := fn (_ voidptr, stack_size int) voidptr {
|
// println('## alloc called')
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_ptr := malloc(stack_size)
|
// 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 ? {
|
$if gcboehm ? {
|
||||||
C.GC_add_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
C.GC_add_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack_ptr
|
return stack_ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dealloc := fn (_ voidptr, stack_ptr voidptr, stack_size int) {
|
|
||||||
|
fn dealloc(_ voidptr, stack_ptr voidptr, stack_size int) {
|
||||||
|
// println('## dealloc called')
|
||||||
unsafe {
|
unsafe {
|
||||||
$if gcboehm ? {
|
$if gcboehm ? {
|
||||||
|
// C.GC_unregister_my_thread()
|
||||||
C.GC_remove_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
C.GC_remove_roots(stack_ptr, charptr(stack_ptr) + stack_size)
|
||||||
}
|
}
|
||||||
free(stack_ptr)
|
// free(stack_ptr)
|
||||||
|
C.default_photon_thread_stack_dealloc(nil, stack_ptr, stack_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init() {
|
||||||
C.set_photon_thread_stack_allocator(alloc, dealloc)
|
C.set_photon_thread_stack_allocator(alloc, dealloc)
|
||||||
ret := C.photon_init_default()
|
ret := C.photon_init_default()
|
||||||
if util.nr_jobs > 0 {
|
|
||||||
|
if util.nr_jobs >= 1 {
|
||||||
C.init_photon_work_pool(util.nr_jobs)
|
C.init_photon_work_pool(util.nr_jobs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
panic('failed to initialize coroutines via photon (ret=${ret})')
|
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() {
|
for x in cleaning_up_array.reverse() {
|
||||||
g.writeln(x)
|
g.writeln(x)
|
||||||
}
|
}
|
||||||
|
if g.pref.use_coroutines {
|
||||||
|
g.writeln('\tdelete_photon_work_pool();')
|
||||||
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
||||||
println(g.out.after(fn_vcleanup_start_pos))
|
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_find_leak(1);')
|
||||||
}
|
}
|
||||||
g.writeln('\tGC_set_pages_executable(0);')
|
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();')
|
g.writeln('\tGC_INIT();')
|
||||||
|
|
||||||
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
||||||
g.writeln('\tGC_enable_incremental();')
|
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_find_leak(1);')
|
||||||
}
|
}
|
||||||
g.writeln('\tGC_set_pages_executable(0);')
|
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();')
|
g.writeln('\tGC_INIT();')
|
||||||
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
if g.pref.gc_mode in [.boehm_incr, .boehm_incr_opt] {
|
||||||
g.writeln('\tGC_enable_incremental();')
|
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 {
|
} 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});')
|
g.writeln('photon_thread_create_and_migrate_to_work_pool((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('photon_thread_create((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
g.writeln('photon_thread_create((void*)${wrapper_fn_name}, &${arg_tmp_var});')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue