ffi 1.7.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 08d9e4bd775b810d8ca6541f51491d4cf12301b8
4
- data.tar.gz: c641ccba1fcb08a552d8b9d27faeef47e254c287
3
+ metadata.gz: b18df2604943c2ffa28b49b8154664b58572779f
4
+ data.tar.gz: 383c237370cf383b21f64af209e2798307845758
5
5
  SHA512:
6
- metadata.gz: 58cbea900c076f8091b8b5146610a7e313faa73b131c2822d3fb78dab6c6f3aed0d68227921f36570c91875229eaa92eda067eac1d1fa9dd8a927277fb5b86d7
7
- data.tar.gz: 12f5440b92613fbdd0a74f0865750f6edad8e1f95470dae0f1c506e9b696028faad1c7d420ffcefc3b8e8667877c5b852ada95534e125486513d1f9fb87ea33d
6
+ metadata.gz: ee8047e83a5454166bfbda7041e096ec045c4ca8dc9315ce6e0a3aae70ce5b0f417a98f351d105e1bbf0460a803b527d71ad0f8f4040003ce614ad981aca52d9
7
+ data.tar.gz: a5bd97cc92544ff52295318226cda8956bb3214fab36f0f40d31efe1cd457259f2e24f74ade72f3ccb8508ee67eee0d2d73cc58a70978e89ad0196f4e62c6d75
@@ -20,19 +20,17 @@
20
20
 
21
21
  #include <sys/types.h>
22
22
  #ifndef _MSC_VER
23
- #include <sys/param.h>
24
- #include <stdint.h>
25
- #include <stdbool.h>
23
+ # include <sys/param.h>
24
+ # include <stdint.h>
25
+ # include <stdbool.h>
26
26
  #else
27
- typedef int bool;
28
- #define true 1
29
- #define false 0
27
+ # include "win32/stdbool.h"
28
+ # include "win32/stdint.h"
30
29
  #endif
30
+
31
31
  #include <limits.h>
32
32
  #include <ruby.h>
33
- #if defined(_MSC_VER) && !defined(INT8_MIN)
34
- # include "win32/stdint.h"
35
- #endif
33
+
36
34
  #include "rbffi.h"
37
35
  #include "compat.h"
38
36
  #include "AbstractMemory.h"
@@ -19,14 +19,11 @@
19
19
  */
20
20
 
21
21
  #ifndef _MSC_VER
22
- #include <stdbool.h>
22
+ # include <stdint.h>
23
+ # include <stdbool.h>
23
24
  #else
24
- typedef int bool;
25
- #define true 1
26
- #define false 0
27
- #endif
28
- #ifndef _MSC_VER
29
- #include <stdint.h>
25
+ # include "win32/stdbool.h"
26
+ # include "win32/stdint.h"
30
27
  #endif
31
28
  #include <limits.h>
32
29
  #include <ruby.h>
@@ -26,16 +26,15 @@
26
26
  #include <sys/types.h>
27
27
  #include <stdio.h>
28
28
  #ifndef _MSC_VER
29
- #include <stdint.h>
30
- #include <stdbool.h>
29
+ # include <stdint.h>
30
+ # include <stdbool.h>
31
31
  #else
32
- typedef int bool;
33
- #define true 1
34
- #define false 0
32
+ # include "win32/stdbool.h"
33
+ # include "win32/stdint.h"
35
34
  #endif
36
35
  #include <errno.h>
37
36
  #include <ruby.h>
38
- #if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION) && !defined(_WIN32)
37
+ #if defined(HAVE_NATIVETHREAD) && (defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)) && !defined(_WIN32)
39
38
  # include <signal.h>
40
39
  # include <pthread.h>
41
40
  #endif
@@ -267,6 +266,7 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
267
266
 
268
267
 
269
268
  typedef struct BlockingCall_ {
269
+ rbffi_frame_t* frame;
270
270
  void* function;
271
271
  FunctionType* info;
272
272
  void **ffiValues;
@@ -281,14 +281,13 @@ static VALUE
281
281
  call_blocking_function(void* data)
282
282
  {
283
283
  BlockingCall* b = (BlockingCall *) data;
284
-
284
+ b->frame->has_gvl = false;
285
285
  ffi_call(&b->info->ffi_cif, FFI_FN(b->function), b->retval, b->ffiValues);
286
+ b->frame->has_gvl = true;
286
287
 
287
288
  return Qnil;
288
289
  }
289
290
 
290
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
291
-
292
291
  static VALUE
293
292
  do_blocking_call(void *data)
294
293
  {
@@ -298,30 +297,22 @@ do_blocking_call(void *data)
298
297
  }
299
298
 
300
299
  static VALUE
301
- cleanup_blocking_call(void *data)
300
+ save_frame_exception(void *data, VALUE exc)
302
301
  {
303
- BlockingCall* bc = (BlockingCall *) data;
304
-
305
- memcpy(bc->stkretval, bc->retval, MAX(bc->info->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
306
- xfree(bc->params);
307
- xfree(bc->ffiValues);
308
- xfree(bc->retval);
309
- xfree(bc);
310
-
302
+ rbffi_frame_t* frame = (rbffi_frame_t *) data;
303
+ frame->exc = exc;
311
304
  return Qnil;
312
305
  }
313
306
 
314
- #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
315
-
316
307
  VALUE
317
308
  rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
318
309
  {
319
310
  void* retval;
320
311
  void** ffiValues;
321
312
  FFIStorage* params;
322
- VALUE rbReturnValue, exc;
323
- rbffi_thread_t oldThread;
324
-
313
+ VALUE rbReturnValue;
314
+ rbffi_frame_t frame = { 0 };
315
+
325
316
  retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
326
317
 
327
318
  if (unlikely(fnInfo->blocking)) {
@@ -347,21 +338,24 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
347
338
  bc->function = function;
348
339
  bc->ffiValues = ffiValues;
349
340
  bc->params = params;
341
+ bc->frame = &frame;
350
342
 
351
343
  rbffi_SetupCallParams(argc, argv,
352
344
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
353
345
  fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
354
346
 
355
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
356
- rb_thread_call_without_gvl(call_blocking_function, bc, (void *) -1, NULL);
347
+ rbffi_frame_push(&frame);
348
+ rb_rescue2(do_blocking_call, (VALUE) bc, save_frame_exception, (VALUE) &frame, rb_eException, (VALUE) 0);
349
+ rbffi_frame_pop(&frame);
357
350
 
358
- #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
359
- rb_thread_blocking_region(call_blocking_function, bc, (void *) -1, NULL);
360
-
361
- #else
362
- rb_ensure(do_blocking_call, (VALUE) bc, cleanup_blocking_call, (VALUE) bc);
351
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
352
+ memcpy(bc->stkretval, bc->retval, MAX(bc->info->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
353
+ xfree(bc->params);
354
+ xfree(bc->ffiValues);
355
+ xfree(bc->retval);
356
+ xfree(bc);
363
357
  #endif
364
-
358
+
365
359
  } else {
366
360
 
367
361
  ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
@@ -371,22 +365,19 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
371
365
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
372
366
  fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
373
367
 
374
- oldThread = rbffi_active_thread;
375
- rbffi_active_thread = rbffi_thread_self();
376
-
368
+ rbffi_frame_push(&frame);
377
369
  ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
378
-
379
- exc = rbffi_active_thread.exc;
380
- rbffi_active_thread = oldThread;
381
- if (exc != Qnil) {
382
- rb_exc_raise(exc);
383
- }
370
+ rbffi_frame_pop(&frame);
384
371
  }
385
372
 
386
373
  if (unlikely(!fnInfo->ignoreErrno)) {
387
374
  rbffi_save_errno();
388
375
  }
389
-
376
+
377
+ if (RTEST(frame.exc) && frame.exc != Qnil) {
378
+ rb_exc_raise(frame.exc);
379
+ }
380
+
390
381
  RB_GC_GUARD(rbReturnValue) = rbffi_NativeValue_ToRuby(fnInfo->returnType, fnInfo->rbReturnType, retval);
391
382
  RB_GC_GUARD(fnInfo->rbReturnType);
392
383
 
@@ -21,8 +21,8 @@
21
21
  * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
22
22
  */
23
23
 
24
- #ifndef RBFFI_INVOKE_H
25
- #define RBFFI_INVOKE_H
24
+ #ifndef RBFFI_CALL_H
25
+ #define RBFFI_CALL_H
26
26
 
27
27
  #ifdef __cplusplus
28
28
  extern "C" {
@@ -59,19 +59,19 @@ typedef union {
59
59
  double f64;
60
60
  long double ld;
61
61
  } FFIStorage;
62
-
63
-
62
+
64
63
  extern void rbffi_Call_Init(VALUE moduleFFI);
65
64
 
66
65
  extern void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
67
66
  FFIStorage* paramStorage, void** ffiValues,
68
67
  VALUE* callbackParameters, int callbackCount, VALUE enums);
69
68
 
70
- extern VALUE rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
69
+ struct FunctionType_;
70
+ extern VALUE rbffi_CallFunction(int argc, VALUE* argv, void* function, struct FunctionType_* fnInfo);
71
71
 
72
- typedef VALUE (*Invoker)(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
72
+ typedef VALUE (*Invoker)(int argc, VALUE* argv, void* function, struct FunctionType_* fnInfo);
73
73
 
74
- Invoker rbffi_GetInvoker(FunctionType* fnInfo);
74
+ Invoker rbffi_GetInvoker(struct FunctionType_* fnInfo);
75
75
 
76
76
  extern VALUE rbffi_GetEnumValue(VALUE enums, VALUE value);
77
77
  extern int rbffi_GetSignedIntValue(VALUE value, int type, int minValue, int maxValue, const char* typeName, VALUE enums);
@@ -80,5 +80,5 @@ extern int rbffi_GetSignedIntValue(VALUE value, int type, int minValue, int maxV
80
80
  }
81
81
  #endif
82
82
 
83
- #endif /* RBFFI_INVOKE_H */
83
+ #endif /* RBFFI_CALL_H */
84
84
 
@@ -26,12 +26,11 @@
26
26
  #endif
27
27
  #include <stdio.h>
28
28
  #ifndef _MSC_VER
29
- #include <stdint.h>
30
- #include <stdbool.h>
29
+ # include <stdint.h>
30
+ # include <stdbool.h>
31
31
  #else
32
- typedef int bool;
33
- #define true 1
34
- #define false 0
32
+ # include "win32/stdbool.h"
33
+ # include "win32/stdint.h"
35
34
  #endif
36
35
  #ifndef _WIN32
37
36
  # include <unistd.h>
@@ -18,8 +18,6 @@
18
18
  * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
19
19
  */
20
20
 
21
- #include "MethodHandle.h"
22
-
23
21
  #ifndef _MSC_VER
24
22
  #include <sys/param.h>
25
23
  #endif
@@ -28,19 +26,18 @@
28
26
  # include <sys/mman.h>
29
27
  # include <unistd.h>
30
28
  #endif
29
+
31
30
  #include <stdio.h>
32
31
  #ifndef _MSC_VER
33
- #include <stdint.h>
34
- #include <stdbool.h>
32
+ # include <stdint.h>
33
+ # include <stdbool.h>
35
34
  #else
36
- typedef int bool;
37
- #define true 1
38
- #define false 0
39
- #endif
40
- #include <ruby.h>
41
- #if defined(_MSC_VER) && !defined(INT8_MIN)
35
+ # include "win32/stdbool.h"
36
+ # if !defined(INT8_MIN)
42
37
  # include "win32/stdint.h"
38
+ # endif
43
39
  #endif
40
+ #include <ruby.h>
44
41
 
45
42
  #include <ffi.h>
46
43
  #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
@@ -59,10 +56,11 @@ typedef int bool;
59
56
  #include "LastError.h"
60
57
  #include "Call.h"
61
58
  #include "ClosurePool.h"
62
- #include "Function.h"
63
59
  #include "MappedType.h"
64
60
  #include "Thread.h"
65
61
  #include "LongDouble.h"
62
+ #include "MethodHandle.h"
63
+ #include "Function.h"
66
64
 
67
65
  typedef struct Function_ {
68
66
  Pointer base;
@@ -80,6 +78,7 @@ static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
80
78
  static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
81
79
  static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
82
80
  static VALUE callback_with_gvl(void* data);
81
+ static VALUE invoke_callback(void* data);
83
82
  static VALUE save_callback_exception(void* data, VALUE exc);
84
83
 
85
84
  #define DEFER_ASYNC_CALLBACK 1
@@ -107,6 +106,7 @@ struct gvl_callback {
107
106
  void* retval;
108
107
  void** parameters;
109
108
  bool done;
109
+ rbffi_frame_t *frame;
110
110
  #if defined(DEFER_ASYNC_CALLBACK)
111
111
  struct gvl_callback* next;
112
112
  # ifndef _WIN32
@@ -124,13 +124,13 @@ static struct gvl_callback* async_cb_list = NULL;
124
124
  # ifndef _WIN32
125
125
  static pthread_mutex_t async_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
126
126
  static pthread_cond_t async_cb_cond = PTHREAD_COND_INITIALIZER;
127
- # if !defined(HAVE_RB_THREAD_BLOCKING_REGION)
127
+ # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
128
128
  static int async_cb_pipe[2];
129
129
  # endif
130
130
  # else
131
131
  static HANDLE async_cb_cond;
132
132
  static CRITICAL_SECTION async_cb_lock;
133
- # if !defined(HAVE_RB_THREAD_BLOCKING_REGION)
133
+ # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
134
134
  static int async_cb_pipe[2];
135
135
  # endif
136
136
  # endif
@@ -311,9 +311,9 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
311
311
 
312
312
  #if defined(DEFER_ASYNC_CALLBACK)
313
313
  if (async_cb_thread == Qnil) {
314
- #if !defined(HAVE_RB_THREAD_BLOCKING_REGION) && defined(_WIN32)
314
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)) && defined(_WIN32)
315
315
  _pipe(async_cb_pipe, 1024, O_BINARY);
316
- #elif !defined(HAVE_RB_THREAD_BLOCKING_REGION)
316
+ #elif !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
317
317
  pipe(async_cb_pipe);
318
318
  fcntl(async_cb_pipe[0], F_SETFL, fcntl(async_cb_pipe[0], F_GETFL) | O_NONBLOCK);
319
319
  fcntl(async_cb_pipe[1], F_SETFL, fcntl(async_cb_pipe[1], F_GETFL) | O_NONBLOCK);
@@ -453,16 +453,22 @@ function_release(VALUE self)
453
453
  static void
454
454
  callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
455
455
  {
456
- struct gvl_callback cb;
456
+ struct gvl_callback cb = { 0 };
457
+
457
458
  cb.closure = (Closure *) user_data;
458
459
  cb.retval = retval;
459
460
  cb.parameters = parameters;
460
461
  cb.done = false;
461
-
462
- if (rbffi_thread_has_gvl_p()) {
463
- rbffi_active_thread.exc = Qnil;
464
- rb_rescue2(callback_with_gvl, (VALUE) &cb, save_callback_exception, (VALUE) &cb, rb_eException, (VALUE) 0);
462
+ cb.frame = rbffi_frame_current();
465
463
 
464
+ if (cb.frame != NULL) cb.frame->exc = Qnil;
465
+ if (cb.frame != NULL && cb.frame->has_gvl) {
466
+ callback_with_gvl(&cb);
467
+
468
+ #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
469
+ } else if (cb.frame != NULL) {
470
+ rb_thread_call_with_gvl(callback_with_gvl, &cb);
471
+ #endif
466
472
  #if defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
467
473
  } else {
468
474
  bool empty = false;
@@ -475,9 +481,9 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
475
481
  empty = async_cb_list == NULL;
476
482
  cb.next = async_cb_list;
477
483
  async_cb_list = &cb;
478
- pthread_mutex_unlock(&async_cb_mutex);
479
484
 
480
- #if !defined(HAVE_RB_THREAD_BLOCKING_REGION)
485
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
486
+ pthread_mutex_unlock(&async_cb_mutex);
481
487
  /* Only signal if the list was empty */
482
488
  if (empty) {
483
489
  char c;
@@ -485,6 +491,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
485
491
  }
486
492
  #else
487
493
  pthread_cond_signal(&async_cb_cond);
494
+ pthread_mutex_unlock(&async_cb_mutex);
488
495
  #endif
489
496
 
490
497
  /* Wait for the thread executing the ruby callback to signal it is done */
@@ -509,7 +516,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
509
516
  async_cb_list = &cb;
510
517
  LeaveCriticalSection(&async_cb_lock);
511
518
 
512
- #if !defined(HAVE_RB_THREAD_BLOCKING_REGION)
519
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
513
520
  /* Only signal if the list was empty */
514
521
  if (empty) {
515
522
  char c;
@@ -697,9 +704,9 @@ static VALUE
697
704
  async_cb_call(void *data)
698
705
  {
699
706
  struct gvl_callback* cb = (struct gvl_callback *) data;
700
-
701
- callback_with_gvl(cb);
702
-
707
+
708
+ callback_with_gvl(data);
709
+
703
710
  /* Signal the original native thread that the ruby code has completed */
704
711
  #ifdef _WIN32
705
712
  SetEvent(cb->async_event);
@@ -715,9 +722,14 @@ async_cb_call(void *data)
715
722
 
716
723
  #endif
717
724
 
718
-
719
725
  static VALUE
720
726
  callback_with_gvl(void* data)
727
+ {
728
+ rb_rescue2(invoke_callback, (VALUE) data, save_callback_exception, (VALUE) data, rb_eException, (VALUE) 0);
729
+ }
730
+
731
+ static VALUE
732
+ invoke_callback(void* data)
721
733
  {
722
734
  struct gvl_callback* cb = (struct gvl_callback *) data;
723
735
 
@@ -913,7 +925,7 @@ save_callback_exception(void* data, VALUE exc)
913
925
  struct gvl_callback* cb = (struct gvl_callback *) data;
914
926
 
915
927
  memset(cb->retval, 0, ((Function *) cb->closure->info)->info->returnType->ffiType->size);
916
- rbffi_active_thread.exc = exc;
928
+ if (cb->frame != NULL) cb->frame->exc = exc;
917
929
 
918
930
  return Qnil;
919
931
  }
@@ -26,12 +26,11 @@ extern "C" {
26
26
  #endif
27
27
 
28
28
  #ifndef _MSC_VER
29
- #include <stdbool.h>
29
+ # include <stdbool.h>
30
30
  #else
31
- typedef int bool;
32
- #define true 1
33
- #define false 0
31
+ # include "win32/stdbool.h"
34
32
  #endif
33
+
35
34
  #include <ffi.h>
36
35
 
37
36
  typedef struct FunctionType_ FunctionType;
@@ -18,18 +18,18 @@
18
18
  */
19
19
 
20
20
  #ifndef _MSC_VER
21
- #include <sys/param.h>
21
+ # include <sys/param.h>
22
22
  #endif
23
23
  #include <sys/types.h>
24
24
  #include <stdio.h>
25
+
25
26
  #ifndef _MSC_VER
26
- #include <stdint.h>
27
- #include <stdbool.h>
27
+ # include <stdint.h>
28
+ # include <stdbool.h>
28
29
  #else
29
- typedef int bool;
30
- #define true 1
31
- #define false 0
30
+ # include "win32/stdbool.h"
32
31
  #endif
32
+
33
33
  #include <errno.h>
34
34
  #include <ruby.h>
35
35
 
@@ -19,17 +19,15 @@
19
19
  */
20
20
 
21
21
  #ifndef _MSC_VER
22
- #include <sys/param.h>
22
+ # include <sys/param.h>
23
23
  #endif
24
24
  #include <sys/types.h>
25
25
  #include <stdio.h>
26
26
  #ifndef _MSC_VER
27
- #include <stdint.h>
28
- #include <stdbool.h>
27
+ # include <stdint.h>
28
+ # include <stdbool.h>
29
29
  #else
30
- typedef int bool;
31
- #define true 1
32
- #define false 0
30
+ # include "win32/stdbool.h"
33
31
  #endif
34
32
  #include <errno.h>
35
33
  #include <ruby.h>
@@ -20,14 +20,11 @@
20
20
  */
21
21
 
22
22
  #ifndef _MSC_VER
23
- #include <stdbool.h>
23
+ # include <stdbool.h>
24
+ # include <stdint.h>
24
25
  #else
25
- typedef int bool;
26
- #define true 1
27
- #define false 0
28
- #endif
29
- #ifndef _MSC_VER
30
- #include <stdint.h>
26
+ # include "win32/stdbool.h"
27
+ # include "win32/stdint.h"
31
28
  #endif
32
29
  #include <limits.h>
33
30
  #include <ruby.h>
@@ -23,11 +23,9 @@
23
23
  #define RBFFI_MEMORYPOINTER_H
24
24
 
25
25
  #ifndef _MSC_VER
26
- #include <stdbool.h>
26
+ # include <stdbool.h>
27
27
  #else
28
- typedef int bool;
29
- #define true 1
30
- #define false 0
28
+ # include "win32/stdbool.h"
31
29
  #endif
32
30
  #include <ruby.h>
33
31
 
@@ -22,19 +22,18 @@
22
22
  #endif
23
23
  #include <sys/types.h>
24
24
  #ifndef _WIN32
25
- # include <sys/mman.h>
25
+ # include <sys/mman.h>
26
26
  #endif
27
27
  #include <stdio.h>
28
28
  #ifndef _MSC_VER
29
- #include <stdint.h>
30
- #include <stdbool.h>
29
+ # include <stdint.h>
30
+ # include <stdbool.h>
31
31
  #else
32
- typedef int bool;
33
- #define true 1
34
- #define false 0
32
+ # include "win32/stdint.h"
33
+ # include "win32/stdbool.h"
35
34
  #endif
36
35
  #ifndef _WIN32
37
- # include <unistd.h>
36
+ # include <unistd.h>
38
37
  #endif
39
38
  #include <errno.h>
40
39
  #include <ruby.h>
@@ -19,23 +19,23 @@
19
19
  */
20
20
 
21
21
  #ifndef _MSC_VER
22
- #include <sys/param.h>
22
+ # include <sys/param.h>
23
23
  #endif
24
- #include <sys/types.h>
24
+ # include <sys/types.h>
25
25
  #ifndef _MSC_VER
26
- #include <stdint.h>
27
- #include <stdbool.h>
26
+ # include <stdint.h>
27
+ # include <stdbool.h>
28
28
  #else
29
- typedef int bool;
30
- #define true 1
31
- #define false 0
29
+ # include "win32/stdint.h"
30
+ # include "win32/stdbool.h"
32
31
  #endif
33
32
  #include <ruby.h>
34
33
  #include <ctype.h>
35
34
  #include "rbffi_endian.h"
36
35
  #include "Platform.h"
36
+
37
37
  #if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
38
- #include <gnu/lib-names.h>
38
+ # include <gnu/lib-names.h>
39
39
  #endif
40
40
 
41
41
  static VALUE PlatformModule = Qnil;
@@ -19,14 +19,11 @@
19
19
  */
20
20
 
21
21
  #ifndef _MSC_VER
22
- #include <stdbool.h>
22
+ # include <stdint.h>
23
+ # include <stdbool.h>
23
24
  #else
24
- typedef int bool;
25
- #define true 1
26
- #define false 0
27
- #endif
28
- #ifndef _MSC_VER
29
- #include <stdint.h>
25
+ # include "win32/stdint.h"
26
+ # include "win32/stdbool.h"
30
27
  #endif
31
28
  #include <limits.h>
32
29
  #include <ruby.h>
@@ -22,11 +22,9 @@
22
22
  #define RBFFI_POINTER_H
23
23
 
24
24
  #ifndef _MSC_VER
25
- #include <stdbool.h>
25
+ # include <stdbool.h>
26
26
  #else
27
- typedef int bool;
28
- #define true 1
29
- #define false 0
27
+ # include "win32/stdbool.h"
30
28
  #endif
31
29
 
32
30
  #ifdef __cplusplus
@@ -20,16 +20,13 @@
20
20
  */
21
21
 
22
22
  #include <sys/types.h>
23
-
24
- #include "Function.h"
25
23
  #ifndef _MSC_VER
26
- #include <sys/param.h>
27
- #include <stdint.h>
28
- #include <stdbool.h>
24
+ # include <sys/param.h>
25
+ # include <stdint.h>
26
+ # include <stdbool.h>
29
27
  #else
30
- typedef int bool;
31
- #define true 1
32
- #define false 0
28
+ # include "win32/stdbool.h"
29
+ # include "win32/stdint.h"
33
30
  #endif
34
31
  #include <ruby.h>
35
32
  #include "rbffi.h"
@@ -39,10 +36,11 @@ typedef int bool;
39
36
  #include "MemoryPointer.h"
40
37
  #include "Function.h"
41
38
  #include "Types.h"
42
- #include "Struct.h"
39
+ #include "Function.h"
43
40
  #include "StructByValue.h"
44
41
  #include "ArrayType.h"
45
42
  #include "MappedType.h"
43
+ #include "Struct.h"
46
44
 
47
45
  typedef struct InlineArray_ {
48
46
  VALUE rbMemory;
@@ -26,17 +26,16 @@
26
26
  */
27
27
 
28
28
  #ifndef _MSC_VER
29
- #include <sys/param.h>
29
+ # include <sys/param.h>
30
30
  #endif
31
31
  #include <sys/types.h>
32
32
  #include <stdio.h>
33
33
  #ifndef _MSC_VER
34
- #include <stdint.h>
35
- #include <stdbool.h>
34
+ # include <stdint.h>
35
+ # include <stdbool.h>
36
36
  #else
37
- typedef int bool;
38
- #define true 1
39
- #define false 0
37
+ # include "win32/stdbool.h"
38
+ # include "win32/stdint.h"
40
39
  #endif
41
40
  #include <errno.h>
42
41
  #include <ruby.h>
@@ -24,12 +24,11 @@
24
24
  #include <sys/types.h>
25
25
  #include <stdio.h>
26
26
  #ifndef _MSC_VER
27
- #include <stdint.h>
28
- #include <stdbool.h>
27
+ # include <stdint.h>
28
+ # include <stdbool.h>
29
29
  #else
30
- typedef int bool;
31
- #define true 1
32
- #define false 0
30
+ # include "win32/stdbool.h"
31
+ # include "win32/stdint.h"
33
32
  #endif
34
33
  #include <errno.h>
35
34
  #include <ruby.h>
@@ -21,15 +21,13 @@
21
21
 
22
22
  #include <sys/types.h>
23
23
 
24
- #include "Function.h"
25
24
  #ifndef _MSC_VER
26
- #include <sys/param.h>
27
- #include <stdint.h>
28
- #include <stdbool.h>
25
+ # include <sys/param.h>
26
+ # include <stdint.h>
27
+ # include <stdbool.h>
29
28
  #else
30
- typedef int bool;
31
- #define true 1
32
- #define false 0
29
+ # include "win32/stdbool.h"
30
+ # include "win32/stdint.h"
33
31
  #endif
34
32
  #include <ruby.h>
35
33
  #include "rbffi.h"
@@ -39,10 +37,11 @@ typedef int bool;
39
37
  #include "MemoryPointer.h"
40
38
  #include "Function.h"
41
39
  #include "Types.h"
42
- #include "Struct.h"
43
40
  #include "StructByValue.h"
44
41
  #include "ArrayType.h"
42
+ #include "Function.h"
45
43
  #include "MappedType.h"
44
+ #include "Struct.h"
46
45
 
47
46
  #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
48
47
 
@@ -21,9 +21,8 @@
21
21
  #ifndef _MSC_VER
22
22
  #include <stdbool.h>
23
23
  #else
24
- typedef int bool;
25
- #define true 1
26
- #define false 0
24
+ # include "win32/stdbool.h"
25
+ # include "win32/stdint.h"
27
26
  #endif
28
27
 
29
28
  #ifndef _WIN32
@@ -39,46 +38,56 @@ typedef int bool;
39
38
  #include <fcntl.h>
40
39
  #include "Thread.h"
41
40
 
41
+ #ifdef _WIN32
42
+ static volatile DWORD frame_thread_key = TLS_OUT_OF_INDEXES;
43
+ #else
44
+ static pthread_key_t thread_data_key;
45
+ struct thread_data {
46
+ rbffi_frame_t* frame;
47
+ };
48
+ static inline struct thread_data* thread_data_get(void);
42
49
 
43
- rbffi_thread_t rbffi_active_thread;
50
+ #endif
44
51
 
45
- rbffi_thread_t
46
- rbffi_thread_self()
52
+ rbffi_frame_t*
53
+ rbffi_frame_current(void)
47
54
  {
48
- rbffi_thread_t self;
49
55
  #ifdef _WIN32
50
- self.id = GetCurrentThreadId();
56
+ return (rbffi_frame_t *) TlsGetValue(frame_thread_key);
51
57
  #else
52
- self.id = pthread_self();
58
+ struct thread_data* td = (struct thread_data *) pthread_getspecific(thread_data_key);
59
+ return td != NULL ? td->frame : NULL;
53
60
  #endif
54
- self.valid = true;
55
- self.exc = Qnil;
56
-
57
- return self;
58
61
  }
59
62
 
60
- bool
61
- rbffi_thread_equal(const rbffi_thread_t* lhs, const rbffi_thread_t* rhs)
63
+ void
64
+ rbffi_frame_push(rbffi_frame_t* frame)
62
65
  {
63
- return lhs->valid && rhs->valid &&
66
+ memset(frame, 0, sizeof(*frame));
67
+ frame->has_gvl = true;
68
+ frame->exc = Qnil;
69
+
64
70
  #ifdef _WIN32
65
- lhs->id == rhs->id;
71
+ frame->prev = TlsGetValue(frame_thread_key);
72
+ TlsSetValue(frame_thread_key, frame);
66
73
  #else
67
- pthread_equal(lhs->id, rhs->id);
74
+ frame->td = thread_data_get();
75
+ frame->prev = frame->td->frame;
76
+ frame->td->frame = frame;
68
77
  #endif
69
78
  }
70
79
 
71
- bool
72
- rbffi_thread_has_gvl_p(void)
80
+ void
81
+ rbffi_frame_pop(rbffi_frame_t* frame)
73
82
  {
74
83
  #ifdef _WIN32
75
- return rbffi_active_thread.valid && rbffi_active_thread.id == GetCurrentThreadId();
84
+ TlsSetValue(frame_thread_key, frame->prev);
76
85
  #else
77
- return rbffi_active_thread.valid && pthread_equal(rbffi_active_thread.id, pthread_self());
86
+ frame->td->frame = frame->prev;
78
87
  #endif
79
88
  }
80
89
 
81
- #ifndef HAVE_RB_THREAD_BLOCKING_REGION
90
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
82
91
 
83
92
  #if !defined(_WIN32)
84
93
 
@@ -296,3 +305,39 @@ rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(voi
296
305
 
297
306
  #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
298
307
 
308
+ #ifndef _WIN32
309
+ static struct thread_data* thread_data_init(void);
310
+
311
+ static inline struct thread_data*
312
+ thread_data_get(void)
313
+ {
314
+ struct thread_data* td = (struct thread_data *) pthread_getspecific(thread_data_key);
315
+ return td != NULL ? td : thread_data_init();
316
+ }
317
+
318
+ static struct thread_data*
319
+ thread_data_init(void)
320
+ {
321
+ struct thread_data* td = calloc(1, sizeof(struct thread_data));
322
+
323
+ pthread_setspecific(thread_data_key, td);
324
+
325
+ return td;
326
+ }
327
+
328
+ static void
329
+ thread_data_free(void *ptr)
330
+ {
331
+ free(ptr);
332
+ }
333
+ #endif
334
+
335
+ void
336
+ rbffi_Thread_Init(VALUE moduleFFI)
337
+ {
338
+ #ifdef _WIN32
339
+ frame_thread_key = TlsAlloc();
340
+ #else
341
+ pthread_key_create(&thread_data_key, thread_data_free);
342
+ #endif
343
+ }
@@ -22,11 +22,10 @@
22
22
  #define RBFFI_THREAD_H
23
23
 
24
24
  #ifndef _MSC_VER
25
- #include <stdbool.h>
25
+ # include <stdbool.h>
26
26
  #else
27
- typedef int bool;
28
- #define true 1
29
- #define false 0
27
+ # include "win32/stdbool.h"
28
+ # include "win32/stdint.h"
30
29
  #endif
31
30
  #include <ruby.h>
32
31
  #include "extconf.h"
@@ -36,11 +35,6 @@ extern "C" {
36
35
  #endif
37
36
 
38
37
 
39
- #ifdef HAVE_RUBY_THREAD_HAS_GVL_P
40
- extern int ruby_thread_has_gvl_p(void);
41
- # define rbffi_thread_has_gvl_p ruby_thread_has_gvl_p
42
- #else
43
-
44
38
  #ifdef _WIN32
45
39
  # include <windows.h>
46
40
  #else
@@ -54,17 +48,29 @@ typedef struct {
54
48
  pthread_t id;
55
49
  #endif
56
50
  bool valid;
51
+ bool has_gvl;
57
52
  VALUE exc;
58
53
  } rbffi_thread_t;
59
54
 
60
- extern rbffi_thread_t rbffi_active_thread;
61
- rbffi_thread_t rbffi_thread_self();
62
- bool rbffi_thread_equal(const rbffi_thread_t* lhs, const rbffi_thread_t* rhs);
63
- bool rbffi_thread_has_gvl_p(void);
64
-
55
+ typedef struct rbffi_frame {
56
+ #ifndef _WIN32
57
+ struct thread_data* td;
65
58
  #endif
66
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
59
+ struct rbffi_frame* prev;
60
+ bool has_gvl;
61
+ VALUE exc;
62
+ } rbffi_frame_t;
63
+
64
+ rbffi_frame_t* rbffi_frame_current(void);
65
+ void rbffi_frame_push(rbffi_frame_t* frame);
66
+ void rbffi_frame_pop(rbffi_frame_t* frame);
67
+
68
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
69
+ # define rbffi_thread_blocking_region rb_thread_call_without_gvl
70
+
71
+ #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
67
72
  # define rbffi_thread_blocking_region rb_thread_blocking_region
73
+
68
74
  #else
69
75
 
70
76
  VALUE rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2);
@@ -24,12 +24,11 @@
24
24
 
25
25
  #include <stdio.h>
26
26
  #ifndef _MSC_VER
27
- #include <stdint.h>
28
- #include <stdbool.h>
27
+ # include <stdint.h>
28
+ # include <stdbool.h>
29
29
  #else
30
- typedef int bool;
31
- #define true 1
32
- #define false 0
30
+ # include "win32/stdbool.h"
31
+ # include "win32/stdint.h"
33
32
  #endif
34
33
  #include <ruby.h>
35
34
 
@@ -163,8 +162,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
163
162
  VALUE* argv;
164
163
  int paramCount = 0, i;
165
164
  ffi_status ffiStatus;
166
- VALUE exc;
167
- rbffi_thread_t oldThread;
165
+ rbffi_frame_t frame = { 0 };
168
166
 
169
167
  Check_Type(parameterTypes, T_ARRAY);
170
168
  Check_Type(parameterValues, T_ARRAY);
@@ -239,18 +237,16 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
239
237
 
240
238
  rbffi_SetupCallParams(paramCount, argv, -1, paramTypes, params,
241
239
  ffiValues, NULL, 0, invoker->rbEnums);
242
- oldThread = rbffi_active_thread;
243
- rbffi_active_thread = rbffi_thread_self();
244
-
240
+
241
+ rbffi_frame_push(&frame);
245
242
  ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
246
-
247
- exc = rbffi_active_thread.exc;
248
- rbffi_active_thread = oldThread;
249
- if (exc != Qnil) {
250
- rb_exc_raise(exc);
251
- }
243
+ rbffi_frame_pop(&frame);
252
244
 
253
245
  rbffi_save_errno();
246
+
247
+ if (RTEST(frame.exc) && frame.exc != Qnil) {
248
+ rb_exc_raise(frame.exc);
249
+ }
254
250
 
255
251
  return rbffi_NativeValue_ToRuby(invoker->returnType, invoker->rbReturnType, retval);
256
252
  }
@@ -49,7 +49,8 @@ VALUE rbffi_FFIModule = Qnil;
49
49
  static VALUE moduleFFI = Qnil;
50
50
 
51
51
  void
52
- Init_ffi_c(void) {
52
+ Init_ffi_c(void)
53
+ {
53
54
  /*
54
55
  * Document-module: FFI
55
56
  *
@@ -58,7 +59,8 @@ Init_ffi_c(void) {
58
59
  rbffi_FFIModule = moduleFFI = rb_define_module("FFI");
59
60
  rb_global_variable(&rbffi_FFIModule);
60
61
 
61
-
62
+ rbffi_Thread_Init(rbffi_FFIModule);
63
+
62
64
  /* FFI::Type needs to be initialized before most other classes */
63
65
  rbffi_Type_Init(moduleFFI);
64
66
 
@@ -38,6 +38,7 @@ extern void rbffi_Variadic_Init(VALUE ffiModule);
38
38
  extern void rbffi_DataConverter_Init(VALUE ffiModule);
39
39
  extern VALUE rbffi_AbstractMemoryClass, rbffi_InvokerClass;
40
40
  extern int rbffi_type_size(VALUE type);
41
+ extern void rbffi_Thread_Init(VALUE moduleFFI);
41
42
 
42
43
  #ifdef __cplusplus
43
44
  }
@@ -0,0 +1,8 @@
1
+ #ifndef FFI_STDBOOL_H
2
+ #define FFI_STDBOOL_H
3
+
4
+ typedef int bool;
5
+ #define true 1
6
+ #define false 0
7
+
8
+ #endif /* FFI_STDBOOL_H */
@@ -1,4 +1,5 @@
1
1
  /* stdint.h standard header */
2
+ #if !defined(_MSC_VER) && !defined(INT8_MIN)
2
3
  #pragma once
3
4
  #ifndef _STDINT
4
5
  #define _STDINT
@@ -197,3 +198,4 @@ using _CSTD uint_fast32_t; using _CSTD uint_fast64_t;
197
198
  * Copyright (c) 1992-2009 by P.J. Plauger. ALL RIGHTS RESERVED.
198
199
  * Consult your license regarding permissions and restrictions.
199
200
  V5.20:0009 */
201
+ #endif /* !defined(_MSC_VER) && !defined(INT8_MIN) */
@@ -1,6 +1,8 @@
1
+ require File.expand_path("../lib/#{File.basename(__FILE__, '.gemspec')}/version", __FILE__)
2
+
1
3
  Gem::Specification.new do |s|
2
4
  s.name = 'ffi'
3
- s.version = '1.7.0'
5
+ s.version = FFI::VERSION
4
6
  s.author = 'Wayne Meissner'
5
7
  s.email = 'wmeissner@gmail.com'
6
8
  s.homepage = 'http://wiki.github.com/ffi/ffi'
@@ -0,0 +1,4 @@
1
+ module FFI
2
+ VERSION = '1.8.1'
3
+ end
4
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wayne Meissner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-12 00:00:00.000000000 Z
11
+ date: 2013-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -406,6 +406,7 @@ files:
406
406
  - ext/ffi_c/Types.c
407
407
  - ext/ffi_c/Types.h
408
408
  - ext/ffi_c/Variadic.c
409
+ - ext/ffi_c/win32/stdbool.h
409
410
  - ext/ffi_c/win32/stdint.h
410
411
  - gen/log
411
412
  - gen/Rakefile
@@ -460,6 +461,7 @@ files:
460
461
  - lib/ffi/types.rb
461
462
  - lib/ffi/union.rb
462
463
  - lib/ffi/variadic.rb
464
+ - lib/ffi/version.rb
463
465
  - lib/ffi.rb
464
466
  - spec/ffi/async_callback_spec.rb
465
467
  - spec/ffi/bool_spec.rb