diff options
author | Wayne Meissner <wmeissner@gmail.com> | 2009-08-05 13:12:11 +1000 |
---|---|---|
committer | Wayne Meissner <wmeissner@gmail.com> | 2009-08-05 13:12:11 +1000 |
commit | 8c0a3d99e2a8c40f704bd220893a845e7e4904ca (patch) | |
tree | 4daa06a4a0c229adec68e699679e78fe5f33811c /ext/ffi_c/Call.c | |
parent | 4dc43f8979e25a40a83b304fbbf0103297388950 (diff) | |
download | ffi-8c0a3d99e2a8c40f704bd220893a845e7e4904ca.tar.gz |
Move the default execution path into Call.c, and fixup blocking calls
Diffstat (limited to 'ext/ffi_c/Call.c')
-rw-r--r-- | ext/ffi_c/Call.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c index f1b5275..ee7b057 100644 --- a/ext/ffi_c/Call.c +++ b/ext/ffi_c/Call.c @@ -35,7 +35,10 @@ #include <stdbool.h> #include <errno.h> #include <ruby.h> - +#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) +# include <signal.h> +# include <pthread.h> +#endif #include <ffi.h> #include "rbffi.h" #include "compat.h" @@ -226,6 +229,26 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy } +#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) + +typedef struct BlockingCall_ { + void* function; + FunctionInfo* info; + void **ffiValues; + FFIStorage* retval; +} BlockingCall; + +static VALUE +call_blocking_function(void* data) +{ + BlockingCall* b = (BlockingCall *) data; + + ffi_call(&b->info->ffi_cif, FFI_FN(b->function), b->retval, b->ffiValues); + + return Qnil; +} +#endif + VALUE rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionInfo* fnInfo) { @@ -241,7 +264,22 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionInfo* fnInfo) fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues, fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums); +#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) + if (unlikely(fnInfo->blocking)) { + BlockingCall bc; + + bc.info = fnInfo; + bc.function = function; + bc.ffiValues = ffiValues; + bc.retval = retval; + + rb_thread_blocking_region(call_blocking_function, &bc, (void *) -1, NULL); + } else { + ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues); + } +#else ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues); +#endif if (!fnInfo->ignoreErrno) { rbffi_save_errno(); |