diff --git a/base/threadcall.jl b/base/threadcall.jl index 2267e4ea2228c..f0e5f336ec0ca 100644 --- a/base/threadcall.jl +++ b/base/threadcall.jl @@ -30,7 +30,7 @@ macro threadcall(f, rettype, argtypes, argvals...) argvals = map(esc, argvals) # construct non-allocating wrapper to call C function - wrapper = :(function (args_ptr::Ptr{Cvoid}, retval_ptr::Ptr{Cvoid}) + wrapper = :(function (fptr::Ptr{Cvoid}, args_ptr::Ptr{Cvoid}, retval_ptr::Ptr{Cvoid}) p = args_ptr # the rest of the body is created below end) @@ -42,18 +42,19 @@ macro threadcall(f, rettype, argtypes, argvals...) push!(body, :(p += Core.sizeof($T))) push!(args, arg) end - push!(body, :(ret = ccall($f, $rettype, ($(argtypes...),), $(args...)))) + push!(body, :(ret = ccall(fptr, $rettype, ($(argtypes...),), $(args...)))) push!(body, :(unsafe_store!(convert(Ptr{$rettype}, retval_ptr), ret))) push!(body, :(return Int(Core.sizeof($rettype)))) # return code to generate wrapper function and send work request thread queue wrapper = Expr(Symbol("hygienic-scope"), wrapper, @__MODULE__) - return :(let fun_ptr = @cfunction($wrapper, Int, (Ptr{Cvoid}, Ptr{Cvoid})) - do_threadcall(fun_ptr, $rettype, Any[$(argtypes...)], Any[$(argvals...)]) + return :(let fun_ptr = @cfunction($wrapper, Int, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid})) + # use cglobal to look up the function on the calling thread + do_threadcall(fun_ptr, cglobal($f), $rettype, Any[$(argtypes...)], Any[$(argvals...)]) end) end -function do_threadcall(fun_ptr::Ptr{Cvoid}, rettype::Type, argtypes::Vector, argvals::Vector) +function do_threadcall(fun_ptr::Ptr{Cvoid}, cfptr::Ptr{Cvoid}, rettype::Type, argtypes::Vector, argvals::Vector) # generate function pointer c_notify_fun = @cfunction( function notify_fun(idx) @@ -86,8 +87,8 @@ function do_threadcall(fun_ptr::Ptr{Cvoid}, rettype::Type, argtypes::Vector, arg GC.@preserve args_arr ret_arr roots begin # queue up the work to be done ccall(:jl_queue_work, Cvoid, - (Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Cvoid}, Cint), - fun_ptr, args_arr, ret_arr, c_notify_fun, idx) + (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Cvoid}, Cint), + fun_ptr, cfptr, args_arr, ret_arr, c_notify_fun, idx) # wait for a result & return it wait(thread_notifiers[idx]) diff --git a/src/jl_uv.c b/src/jl_uv.c index a2dce926a924f..18733926e8c54 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -966,12 +966,13 @@ JL_DLLEXPORT int jl_tty_set_mode(uv_tty_t *handle, int mode) return uv_tty_set_mode(handle, mode_enum); } -typedef int (*work_cb_t)(void *, void *); +typedef int (*work_cb_t)(void *, void *, void *); typedef void (*notify_cb_t)(int); struct work_baton { uv_work_t req; work_cb_t work_func; + void *ccall_fptr; void *work_args; void *work_retval; notify_cb_t notify_func; @@ -985,7 +986,7 @@ struct work_baton { void jl_work_wrapper(uv_work_t *req) { struct work_baton *baton = (struct work_baton*) req->data; - baton->work_func(baton->work_args, baton->work_retval); + baton->work_func(baton->ccall_fptr, baton->work_args, baton->work_retval); } void jl_work_notifier(uv_work_t *req, int status) @@ -995,12 +996,13 @@ void jl_work_notifier(uv_work_t *req, int status) free(baton); } -JL_DLLEXPORT int jl_queue_work(work_cb_t work_func, void *work_args, void *work_retval, +JL_DLLEXPORT int jl_queue_work(work_cb_t work_func, void *ccall_fptr, void *work_args, void *work_retval, notify_cb_t notify_func, int notify_idx) { struct work_baton *baton = (struct work_baton*)malloc_s(sizeof(struct work_baton)); baton->req.data = (void*) baton; baton->work_func = work_func; + baton->ccall_fptr = ccall_fptr; baton->work_args = work_args; baton->work_retval = work_retval; baton->notify_func = notify_func;