summaryrefslogtreecommitdiff
path: root/ext/ffi_c/Call.c
diff options
context:
space:
mode:
authorWayne Meissner <wmeissner@gmail.com>2009-08-05 13:12:11 +1000
committerWayne Meissner <wmeissner@gmail.com>2009-08-05 13:12:11 +1000
commit8c0a3d99e2a8c40f704bd220893a845e7e4904ca (patch)
tree4daa06a4a0c229adec68e699679e78fe5f33811c /ext/ffi_c/Call.c
parent4dc43f8979e25a40a83b304fbbf0103297388950 (diff)
downloadffi-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.c40
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();