From dcb9c3beb396b2a0b4183175978698736bd50d76 Mon Sep 17 00:00:00 2001 From: MatejMagat305 <61238240+MatejMagat305@users.noreply.github.com> Date: Thu, 9 Feb 2023 14:57:53 +0100 Subject: [PATCH] cgen: support `[spawn_stack: 131072]` fn attribute, for controlling the max size of the stack, of the spawned threads (#17222) --- examples/control_thread_stack_size.v | 19 +++++++++++++ vlib/v/gen/c/coutput_test.v | 23 ++++++++++++++++ vlib/v/gen/c/fn.v | 22 +++++++++++++-- .../c/testdata/spawn_stack_nix.c.must_have | 2 ++ vlib/v/gen/c/testdata/spawn_stack_nix.out | 3 +++ vlib/v/gen/c/testdata/spawn_stack_nix.vv | 27 +++++++++++++++++++ .../testdata/spawn_stack_windows.c.must_have | 2 ++ vlib/v/gen/c/testdata/spawn_stack_windows.out | 3 +++ vlib/v/gen/c/testdata/spawn_stack_windows.vv | 27 +++++++++++++++++++ 9 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 examples/control_thread_stack_size.v create mode 100644 vlib/v/gen/c/testdata/spawn_stack_nix.c.must_have create mode 100644 vlib/v/gen/c/testdata/spawn_stack_nix.out create mode 100644 vlib/v/gen/c/testdata/spawn_stack_nix.vv create mode 100644 vlib/v/gen/c/testdata/spawn_stack_windows.c.must_have create mode 100644 vlib/v/gen/c/testdata/spawn_stack_windows.out create mode 100644 vlib/v/gen/c/testdata/spawn_stack_windows.vv diff --git a/examples/control_thread_stack_size.v b/examples/control_thread_stack_size.v new file mode 100644 index 0000000000..4e76a6db1f --- /dev/null +++ b/examples/control_thread_stack_size.v @@ -0,0 +1,19 @@ +module main + +fn main() { + th := spawn my_print1() + th.wait() + th2 := spawn my_print2() + th2.wait() +} + +// default stack size +fn my_print1() { + println('hello word') +} + +// 2MB stack size +[spawn_stack: 2097152] +fn my_print2() { + println('ahoj svet') +} diff --git a/vlib/v/gen/c/coutput_test.v b/vlib/v/gen/c/coutput_test.v index cf24ef0995..c45ea31695 100644 --- a/vlib/v/gen/c/coutput_test.v +++ b/vlib/v/gen/c/coutput_test.v @@ -14,6 +14,8 @@ const diff_cmd = diff.find_working_diff_command() or { '' } const show_compilation_output = os.getenv('VTEST_SHOW_COMPILATION_OUTPUT').int() == 1 +const user_os = os.user_os() + fn mm(s string) string { return term.colorize(term.magenta, s) } @@ -36,6 +38,9 @@ fn test_out_files() { mut total_errors := 0 for out_path in paths { basename, path, relpath, out_relpath := target2paths(out_path, '.out') + if should_skip(relpath) { + continue + } pexe := os.join_path(output_path, '${basename}.exe') // file_options := get_file_options(path) @@ -108,6 +113,9 @@ fn test_c_must_have_files() { mut failed_descriptions := []string{cap: paths.len} for must_have_path in paths { basename, path, relpath, must_have_relpath := target2paths(must_have_path, '.c.must_have') + if should_skip(relpath) { + continue + } file_options := get_file_options(path) alloptions := '-o - ${file_options.vflags}' description := mm('v ${alloptions} ${relpath}') + @@ -221,3 +229,18 @@ pub fn get_file_options(file string) FileOptions { } return res } + +fn should_skip(relpath string) bool { + if user_os == 'windows' { + if relpath.contains('_nix.vv') { + eprintln('> skipping ${relpath} on windows') + return true + } + } else { + if relpath.contains('_windows.vv') { + eprintln('> skipping ${relpath} on !windows') + return true + } + } + return false +} diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 3ec4d96bfb..5464f3d68c 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1972,7 +1972,8 @@ fn (mut g Gen) go_expr(node ast.GoExpr) { } else { 'thread_${tmp}' } - g.writeln('HANDLE ${simple_handle} = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0);') + stack_size := g.get_cur_thread_stack_size(expr.name) + g.writeln('HANDLE ${simple_handle} = CreateThread(0, ${stack_size}, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0); // fn: ${expr.name}') g.writeln('if (!${simple_handle}) panic_lasterr(tos3("`go ${name}()`: "));') if node.is_expr && node.call_expr.return_type != ast.void_type { g.writeln('${gohandle_name} thread_${tmp} = {') @@ -1989,7 +1990,8 @@ fn (mut g Gen) go_expr(node ast.GoExpr) { if g.pref.os != .vinix { g.writeln('pthread_attr_t thread_${tmp}_attributes;') g.writeln('pthread_attr_init(&thread_${tmp}_attributes);') - g.writeln('pthread_attr_setstacksize(&thread_${tmp}_attributes, ${g.pref.thread_stack_size});') + size := g.get_cur_thread_stack_size(expr.name) + g.writeln('pthread_attr_setstacksize(&thread_${tmp}_attributes, ${size}); // fn: ${expr.name}') sthread_attributes = '&thread_${tmp}_attributes' } g.writeln('int ${tmp}_thr_res = pthread_create(&thread_${tmp}, ${sthread_attributes}, (void*)${wrapper_fn_name}, ${arg_tmp_var});') @@ -2210,6 +2212,22 @@ fn (mut g Gen) go_expr(node ast.GoExpr) { } } +// get current thread size, if fn hasn't defined return default +[inline] +fn (mut g Gen) get_cur_thread_stack_size(name string) string { + ast_fn := g.table.fns[name] or { return '${g.pref.thread_stack_size}' } + attrs := ast_fn.attrs + if isnil(attrs) { + return '${g.pref.thread_stack_size}' + } + for attr in attrs { + if attr.name == 'spawn_stack' { + return attr.arg + } + } + return '${g.pref.thread_stack_size}' +} + // similar to `autofree_call_pregen()` but only to to handle [keep_args_alive] for C functions fn (mut g Gen) keep_alive_call_pregen(node ast.CallExpr) int { g.empty_line = true diff --git a/vlib/v/gen/c/testdata/spawn_stack_nix.c.must_have b/vlib/v/gen/c/testdata/spawn_stack_nix.c.must_have new file mode 100644 index 0000000000..6ac06ec68c --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_nix.c.must_have @@ -0,0 +1,2 @@ +pthread_attr_setstacksize(&thread__t3_attributes, 65536); // fn: main.my_print2 +pthread_attr_setstacksize(&thread__t5_attributes, 131072); // fn: main.my_print3 diff --git a/vlib/v/gen/c/testdata/spawn_stack_nix.out b/vlib/v/gen/c/testdata/spawn_stack_nix.out new file mode 100644 index 0000000000..353cd9cf85 --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_nix.out @@ -0,0 +1,3 @@ +hello word +ahoj svet +здравей свят diff --git a/vlib/v/gen/c/testdata/spawn_stack_nix.vv b/vlib/v/gen/c/testdata/spawn_stack_nix.vv new file mode 100644 index 0000000000..0c3858ff28 --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_nix.vv @@ -0,0 +1,27 @@ +module main + +fn main() { + th := spawn my_print1() + th.wait() + th2 := spawn my_print2() + th2.wait() + th3 := spawn my_print3() + th3.wait() +} + +// default stack size +fn my_print1() { + println('hello word') +} + +// 64KB stack size +[spawn_stack: 65536] +fn my_print2() { + println('ahoj svet') +} + +// 64KB stack size +[spawn_stack: 131072] +fn my_print3() { + println('здравей свят') +} diff --git a/vlib/v/gen/c/testdata/spawn_stack_windows.c.must_have b/vlib/v/gen/c/testdata/spawn_stack_windows.c.must_have new file mode 100644 index 0000000000..67f51648e3 --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_windows.c.must_have @@ -0,0 +1,2 @@ +CreateThread(0, 65536, (LPTHREAD_START_ROUTINE)main__my_print2_thread_wrapper +CreateThread(0, 131072, (LPTHREAD_START_ROUTINE)main__my_print3_thread_wrapper diff --git a/vlib/v/gen/c/testdata/spawn_stack_windows.out b/vlib/v/gen/c/testdata/spawn_stack_windows.out new file mode 100644 index 0000000000..353cd9cf85 --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_windows.out @@ -0,0 +1,3 @@ +hello word +ahoj svet +здравей свят diff --git a/vlib/v/gen/c/testdata/spawn_stack_windows.vv b/vlib/v/gen/c/testdata/spawn_stack_windows.vv new file mode 100644 index 0000000000..0c3858ff28 --- /dev/null +++ b/vlib/v/gen/c/testdata/spawn_stack_windows.vv @@ -0,0 +1,27 @@ +module main + +fn main() { + th := spawn my_print1() + th.wait() + th2 := spawn my_print2() + th2.wait() + th3 := spawn my_print3() + th3.wait() +} + +// default stack size +fn my_print1() { + println('hello word') +} + +// 64KB stack size +[spawn_stack: 65536] +fn my_print2() { + println('ahoj svet') +} + +// 64KB stack size +[spawn_stack: 131072] +fn my_print3() { + println('здравей свят') +}