Skip to content

Commit

Permalink
Merge pull request #22987 from JuliaLang/jn/init-threads-world
Browse files Browse the repository at this point in the history
mark julia threads as initialized for cfunction
  • Loading branch information
vtjnash authored Aug 3, 2017
2 parents 8d85aa4 + 98a2d1d commit a342e0f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 21 deletions.
16 changes: 9 additions & 7 deletions examples/embedding/embedding-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
using Base.Test

@test length(ARGS) == 1
let
@testset "embedding example" begin
stdout = Pipe()
stderr = Pipe()
p = spawn(pipeline(Cmd(ARGS), stdin=DevNull, stdout=stdout, stderr=stderr))
close(stdout.in)
close(stderr.in)
stderr_task = @async readlines(stderr)
lines = readlines(stdout)
@test length(lines) == 6
@test parse(Float64, lines[1]) sqrt(2)
lines = wait(stderr_task)
@test lines == ["UndefVarError(:this_function_does_not_exist)"]
stdout_task = @async readlines(stdout)
stderr = read(stderr, String)
@test stderr == "MethodError: no method matching this_function_has_no_methods()\n"
@test success(p)
lines = wait(stdout_task)
@test length(lines) == 9
@test parse(Float64, lines[1]) sqrt(2)
@test lines[8] == "called bar"
@test lines[9] == "calling new bar"
end
81 changes: 67 additions & 14 deletions examples/embedding/embedding.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,39 @@ double my_c_sqrt(double x)
return sqrt(x);
}

jl_value_t *checked_eval_string(const char* code)
{
jl_value_t *result = jl_eval_string(code);
if (jl_exception_occurred()) {
// none of these allocate, so a gc-root (JL_GC_PUSH) is not necessary
jl_call2(jl_get_function(jl_base_module, "showerror"),
jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
jl_atexit_hook(1);
exit(1);
}
assert(result && "Missing return value but no exception occurred!");
return result;
}

int main()
{
jl_init();

{
// Simple running Julia code
// Simple running of Julia code

jl_eval_string("println(sqrt(2.0))");
checked_eval_string("println(sqrt(2.0))");
}

{
// Accessing the return value

jl_value_t *ret = jl_eval_string("sqrt(2.0)");
jl_value_t *ret = checked_eval_string("sqrt(2.0)");
double retDouble = jl_unbox_float64(ret);
printf("sqrt(2.0) in C: %e\n", retDouble);
fflush(stdout);
}

{
Expand All @@ -40,62 +57,98 @@ int main()
jl_value_t* ret = jl_call1(func, argument);
double retDouble = jl_unbox_float64(ret);
printf("sqrt(2.0) in C: %e\n", retDouble);
fflush(stdout);
}

{
// 1D arrays

jl_value_t* array_type = jl_apply_array_type( (jl_value_t*)jl_float64_type, 1 );
jl_array_t* x = jl_alloc_array_1d(array_type , 10);
jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
jl_array_t* x = jl_alloc_array_1d(array_type, 10);
// JL_GC_PUSH* is required here to ensure that `x` is not deleted before
// (aka, is gc-rooted until) the program reaches the corresponding JL_GC_POP()
JL_GC_PUSH1(&x);

double* xData = jl_array_data(x);

size_t i;
for(i=0; i<jl_array_len(x); i++)
for (i = 0; i < jl_array_len(x); i++)
xData[i] = i;

jl_function_t *func = jl_get_function(jl_base_module, "reverse!");
jl_call1(func, (jl_value_t*) x);

printf("x = [");
for(i=0; i<jl_array_len(x); i++)
for (i = 0; i < jl_array_len(x); i++)
printf("%e ", xData[i]);
printf("]\n");
fflush(stdout);

JL_GC_POP();
}

{
// define julia function and call it
// Defining a Julia function and calling it

jl_eval_string("my_func(x) = 2*x");
checked_eval_string("my_func(x) = 2 * x");

jl_function_t *func = jl_get_function(jl_current_module, "my_func");
jl_value_t* arg = jl_box_float64(5.0);
double ret = jl_unbox_float64(jl_call1(func, arg));

printf("my_func(5.0) = %f\n", ret);
fflush(stdout);
}

{
// call c function
// Calling a C function from Julia (from C)

jl_eval_string("println( ccall( :my_c_sqrt, Float64, (Float64,), 2.0 ) )");
// in a shared library (exported, by name)
checked_eval_string("println( ccall(:my_c_sqrt, Float64, (Float64,), 2.0) )");

// or via a pointer
jl_value_t *call_by_ptr = checked_eval_string(
"my_c_sqrt -> println( ccall(my_c_sqrt, Float64, (Float64,), 2.0) )");
jl_call1(call_by_ptr, jl_box_voidpointer(my_c_sqrt));
}

{
// check for exceptions
// Handling exceptions gracefully

jl_eval_string("this_function_does_not_exist()");
jl_value_t *f = checked_eval_string("function this_function_has_no_methods end");
jl_call0(f);

if (jl_exception_occurred()) {
jl_call2(jl_get_function(jl_base_module, "show"), jl_stderr_obj(), jl_exception_occurred());
jl_call2(jl_get_function(jl_base_module, "showerror"),
jl_stderr_obj(),
jl_exception_occurred());
jl_printf(jl_stderr_stream(), "\n");
}

}

{
// Creating and using a native C function handle
// to a Julia function signature

checked_eval_string(
"function bar()\n"
" println(\"called bar\")\n"
" random_return_value = 42\n"
"end");
checked_eval_string(
"function bar_from_c()\n"
" bar()\n"
" nothing\n"
"end");
typedef void (*Func_VOID__VOID)(void);
jl_value_t *pbar = jl_eval_string("cfunction(bar_from_c, Void, ())");
Func_VOID__VOID bar = (Func_VOID__VOID)jl_unbox_voidpointer(pbar);
bar();
checked_eval_string("bar() = println(\"calling new bar\")");
bar();
}

int ret = 0;
jl_atexit_hook(ret);
return ret;
Expand Down
2 changes: 2 additions & 0 deletions src/threading.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ static void ti_initthread(int16_t tid)
#ifndef _OS_WINDOWS_
ptls->system_id = pthread_self();
#endif
assert(ptls->world_age == 0);
ptls->world_age = 1; // OK to run Julia code on this thread
ptls->tid = tid;
ptls->pgcstack = NULL;
ptls->gc_state = 0; // GC unsafe
Expand Down

2 comments on commit a342e0f

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

Please sign in to comment.