ffi 1.10.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +2 -1
  4. data/.travis.yml +17 -18
  5. data/CHANGELOG.md +33 -0
  6. data/Gemfile +1 -1
  7. data/README.md +20 -17
  8. data/Rakefile +10 -83
  9. data/appveyor.yml +6 -1
  10. data/ext/ffi_c/Call.c +16 -33
  11. data/ext/ffi_c/Call.h +2 -5
  12. data/ext/ffi_c/Function.c +24 -108
  13. data/ext/ffi_c/Platform.c +0 -47
  14. data/ext/ffi_c/Thread.c +6 -222
  15. data/ext/ffi_c/Thread.h +2 -13
  16. data/ext/ffi_c/Type.c +0 -18
  17. data/ext/ffi_c/Type.h +0 -1
  18. data/ext/ffi_c/Variadic.c +9 -15
  19. data/ext/ffi_c/extconf.rb +34 -20
  20. data/ext/ffi_c/ffi.c +3 -8
  21. data/ext/ffi_c/libffi/configure.ac +5 -1
  22. data/ext/ffi_c/libffi/include/ffi_common.h +1 -1
  23. data/ext/ffi_c/libffi/src/aarch64/ffi.c +2 -2
  24. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  25. data/ext/ffi_c/libffi/src/metag/ffi.c +1 -1
  26. data/ext/ffi_c/libffi/src/moxie/ffi.c +1 -1
  27. data/ext/ffi_c/libffi/src/riscv/ffi.c +42 -6
  28. data/ext/ffi_c/libffi/src/riscv/ffitarget.h +1 -0
  29. data/ext/ffi_c/libffi/src/riscv/sysv.S +86 -7
  30. data/ext/ffi_c/libffi/src/x86/ffi.c +2 -1
  31. data/ext/ffi_c/libffi/src/x86/ffiw64.c +1 -1
  32. data/ext/ffi_c/libffi/src/x86/sysv.S +88 -2
  33. data/ext/ffi_c/libffi/src/x86/unix64.S +41 -0
  34. data/ext/ffi_c/rbffi.h +0 -2
  35. data/ffi.gemspec +11 -4
  36. data/lib/ffi/data_converter.rb +67 -0
  37. data/lib/ffi/ffi.rb +1 -0
  38. data/lib/ffi/platform.rb +2 -0
  39. data/lib/ffi/pointer.rb +1 -1
  40. data/lib/ffi/struct.rb +3 -63
  41. data/lib/ffi/struct_by_reference.rb +72 -0
  42. data/lib/ffi/struct_layout.rb +96 -0
  43. data/lib/ffi/tools/const_generator.rb +5 -4
  44. data/lib/ffi/tools/generator.rb +47 -2
  45. data/lib/ffi/tools/generator_task.rb +13 -17
  46. data/lib/ffi/tools/struct_generator.rb +4 -4
  47. data/lib/ffi/types.rb +1 -1
  48. data/lib/ffi/version.rb +1 -1
  49. metadata +18 -13
  50. data/ext/ffi_c/DataConverter.c +0 -91
  51. data/ext/ffi_c/StructByReference.c +0 -190
  52. data/ext/ffi_c/StructByReference.h +0 -50
@@ -48,7 +48,7 @@ extern "C" {
48
48
  #if (defined(__i386__) || defined(__x86_64__)) && !(defined(_WIN32) || defined(__WIN32__))
49
49
  # define BYPASS_FFI 1
50
50
  #endif
51
-
51
+
52
52
  typedef union {
53
53
  #ifdef USE_RAW
54
54
  signed int s8, s16, s32;
@@ -70,7 +70,7 @@ typedef union {
70
70
  double f64;
71
71
  long double ld;
72
72
  } FFIStorage;
73
-
73
+
74
74
  extern void rbffi_Call_Init(VALUE moduleFFI);
75
75
 
76
76
  extern void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
@@ -94,9 +94,6 @@ typedef struct rbffi_blocking_call {
94
94
  void **ffiValues;
95
95
  void* retval;
96
96
  void* params;
97
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
98
- void* stkretval;
99
- #endif
100
97
  } rbffi_blocking_call_t;
101
98
 
102
99
  VALUE rbffi_do_blocking_call(void* data);
@@ -47,9 +47,7 @@
47
47
  # endif
48
48
  #endif
49
49
  #include <ruby.h>
50
- #if defined(HAVE_RUBY_THREAD_H)
51
50
  #include <ruby/thread.h>
52
- #endif
53
51
 
54
52
  #include <ffi.h>
55
53
  #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
@@ -101,10 +99,27 @@ static VALUE async_cb_event(void *);
101
99
  static VALUE async_cb_call(void *);
102
100
  #endif
103
101
 
104
- #ifdef HAVE_RB_THREAD_CALL_WITH_GVL
105
- extern void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
102
+ #ifdef HAVE_RUBY_THREAD_HAS_GVL_P
103
+ extern int ruby_thread_has_gvl_p(void);
104
+ #define rbffi_thread_has_gvl_p(frame) ruby_thread_has_gvl_p()
105
+ #else
106
+ static int rbffi_thread_has_gvl_p(rbffi_frame_t *frame)
107
+ {
108
+ return frame != NULL && frame->has_gvl;
109
+ }
106
110
  #endif
107
111
 
112
+ #ifdef HAVE_RUBY_NATIVE_THREAD_P
113
+ extern int ruby_native_thread_p(void);
114
+ #define rbffi_native_thread_p(frame) ruby_native_thread_p()
115
+ #else
116
+ static int rbffi_native_thread_p(rbffi_frame_t *frame)
117
+ {
118
+ return frame != NULL;
119
+ }
120
+ #endif
121
+
122
+
108
123
  VALUE rbffi_FunctionClass = Qnil;
109
124
 
110
125
  #if defined(DEFER_ASYNC_CALLBACK)
@@ -136,15 +151,9 @@ static struct gvl_callback* async_cb_list = NULL;
136
151
  # ifndef _WIN32
137
152
  static pthread_mutex_t async_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
138
153
  static pthread_cond_t async_cb_cond = PTHREAD_COND_INITIALIZER;
139
- # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
140
- static int async_cb_pipe[2];
141
- # endif
142
154
  # else
143
155
  static HANDLE async_cb_cond;
144
156
  static CRITICAL_SECTION async_cb_lock;
145
- # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
146
- static int async_cb_pipe[2];
147
- # endif
148
157
  # endif
149
158
  #endif
150
159
 
@@ -323,16 +332,8 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
323
332
 
324
333
  #if defined(DEFER_ASYNC_CALLBACK)
325
334
  if (async_cb_thread == Qnil) {
326
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)) && defined(_WIN32)
327
- _pipe(async_cb_pipe, 1024, O_BINARY);
328
- #elif !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
329
- pipe(async_cb_pipe);
330
- fcntl(async_cb_pipe[0], F_SETFL, fcntl(async_cb_pipe[0], F_GETFL) | O_NONBLOCK);
331
- fcntl(async_cb_pipe[1], F_SETFL, fcntl(async_cb_pipe[1], F_GETFL) | O_NONBLOCK);
332
- #endif
333
335
  async_cb_thread = rb_thread_create(async_cb_event, NULL);
334
336
  }
335
-
336
337
  #endif
337
338
 
338
339
  fn->closure = rbffi_Closure_Alloc(fn->info->closurePool);
@@ -474,13 +475,13 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
474
475
  cb.frame = rbffi_frame_current();
475
476
 
476
477
  if (cb.frame != NULL) cb.frame->exc = Qnil;
477
- if (cb.frame != NULL && cb.frame->has_gvl) {
478
- callback_with_gvl(&cb);
479
478
 
480
- #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
481
- } else if (cb.frame != NULL) {
479
+ if (rbffi_native_thread_p(cb.frame)) {
480
+ if(rbffi_thread_has_gvl_p(cb.frame)) {
481
+ callback_with_gvl(&cb);
482
+ } else {
482
483
  rb_thread_call_with_gvl(callback_with_gvl, &cb);
483
- #endif
484
+ }
484
485
  #if defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
485
486
  } else {
486
487
  bool empty = false;
@@ -494,17 +495,8 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
494
495
  cb.next = async_cb_list;
495
496
  async_cb_list = &cb;
496
497
 
497
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
498
- pthread_mutex_unlock(&async_cb_mutex);
499
- /* Only signal if the list was empty */
500
- if (empty) {
501
- char c;
502
- write(async_cb_pipe[1], &c, 1);
503
- }
504
- #else
505
498
  pthread_cond_signal(&async_cb_cond);
506
499
  pthread_mutex_unlock(&async_cb_mutex);
507
- #endif
508
500
 
509
501
  /* Wait for the thread executing the ruby callback to signal it is done */
510
502
  pthread_mutex_lock(&cb.async_mutex);
@@ -528,15 +520,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
528
520
  async_cb_list = &cb;
529
521
  LeaveCriticalSection(&async_cb_lock);
530
522
 
531
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
532
- /* Only signal if the list was empty */
533
- if (empty) {
534
- char c;
535
- write(async_cb_pipe[1], &c, 1);
536
- }
537
- #else
538
523
  SetEvent(async_cb_cond);
539
- #endif
540
524
 
541
525
  /* Wait for the thread executing the ruby callback to signal it is done */
542
526
  WaitForSingleObject(cb.async_event, INFINITE);
@@ -554,7 +538,6 @@ struct async_wait {
554
538
  static void * async_cb_wait(void *);
555
539
  static void async_cb_stop(void *);
556
540
 
557
- #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
558
541
  static VALUE
559
542
  async_cb_event(void* unused)
560
543
  {
@@ -562,11 +545,7 @@ async_cb_event(void* unused)
562
545
 
563
546
  w.stop = false;
564
547
  while (!w.stop) {
565
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
566
548
  rb_thread_call_without_gvl(async_cb_wait, &w, async_cb_stop, &w);
567
- #else
568
- rb_thread_blocking_region(async_cb_wait, &w, async_cb_stop, &w);
569
- #endif
570
549
  if (w.cb != NULL) {
571
550
  /* Start up a new ruby thread to run the ruby callback */
572
551
  rb_thread_create(async_cb_call, w.cb);
@@ -576,69 +555,6 @@ async_cb_event(void* unused)
576
555
  return Qnil;
577
556
  }
578
557
 
579
- #elif defined(_WIN32)
580
- static VALUE
581
- async_cb_event(void* unused)
582
- {
583
- while (true) {
584
- struct gvl_callback* cb;
585
- char buf[64];
586
- fd_set rfds;
587
-
588
- FD_ZERO(&rfds);
589
- FD_SET(async_cb_pipe[0], &rfds);
590
- rb_thread_select(async_cb_pipe[0] + 1, &rfds, NULL, NULL, NULL);
591
- read(async_cb_pipe[0], buf, sizeof(buf));
592
-
593
- EnterCriticalSection(&async_cb_lock);
594
- cb = async_cb_list;
595
- async_cb_list = NULL;
596
- LeaveCriticalSection(&async_cb_lock);
597
-
598
- while (cb != NULL) {
599
- struct gvl_callback* next = cb->next;
600
- /* Start up a new ruby thread to run the ruby callback */
601
- rb_thread_create(async_cb_call, cb);
602
- cb = next;
603
- }
604
- }
605
-
606
- return Qnil;
607
- }
608
- #else
609
- static VALUE
610
- async_cb_event(void* unused)
611
- {
612
- while (true) {
613
- struct gvl_callback* cb;
614
- char buf[64];
615
-
616
- if (read(async_cb_pipe[0], buf, sizeof(buf)) < 0) {
617
- rb_thread_wait_fd(async_cb_pipe[0]);
618
- while (read(async_cb_pipe[0], buf, sizeof (buf)) < 0) {
619
- if (rb_io_wait_readable(async_cb_pipe[0]) != Qtrue) {
620
- return Qfalse;
621
- }
622
- }
623
- }
624
-
625
- pthread_mutex_lock(&async_cb_mutex);
626
- cb = async_cb_list;
627
- async_cb_list = NULL;
628
- pthread_mutex_unlock(&async_cb_mutex);
629
-
630
- while (cb != NULL) {
631
- struct gvl_callback* next = cb->next;
632
- /* Start up a new ruby thread to run the ruby callback */
633
- rb_thread_create(async_cb_call, cb);
634
- cb = next;
635
- }
636
- }
637
-
638
- return Qnil;
639
- }
640
- #endif
641
-
642
558
  #ifdef _WIN32
643
559
  static void *
644
560
  async_cb_wait(void *data)
@@ -49,51 +49,6 @@
49
49
 
50
50
  static VALUE PlatformModule = Qnil;
51
51
 
52
- /*
53
- * Determine the cpu type at compile time - useful for MacOSX where the the
54
- * system installed ruby incorrectly reports 'host_cpu' as 'powerpc' when running
55
- * on intel.
56
- */
57
- #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64) || defined(_M_X64) || defined(_M_AMD64)
58
- # define CPU "x86_64"
59
-
60
- #elif defined(__i386__) || defined(__i386) || defined(_M_IX86)
61
- # define CPU "i386"
62
-
63
- #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_M_PPC)
64
- # define CPU "ppc64"
65
-
66
- #elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc)
67
- # define CPU "ppc"
68
-
69
- /*
70
- * Need to check for __sparcv9 first, because __sparc will be defined either way.
71
- * Note that __sparcv9 seems to only be set for Solaris. On Linux, __sparc will
72
- * be set, along with __arch64__ if a 64-bit platform.
73
- */
74
- #elif defined(__sparcv9__) || defined(__sparcv9)
75
- # define CPU "sparcv9"
76
-
77
- #elif defined(__sparc__) || defined(__sparc)
78
- # if defined(__arch64__)
79
- # define CPU "sparcv9"
80
- # else
81
- # define CPU "sparc"
82
- # endif
83
-
84
- #elif defined(__arm__) || defined(__arm)
85
- # define CPU "arm"
86
-
87
- #elif defined(__mips__) || defined(__mips)
88
- # define CPU "mips"
89
-
90
- #elif defined(__s390__)
91
- # define CPU "s390"
92
-
93
- #else
94
- # define CPU "unknown"
95
- #endif
96
-
97
52
  static void
98
53
  export_primitive_types(VALUE module)
99
54
  {
@@ -120,10 +75,8 @@ rbffi_Platform_Init(VALUE moduleFFI)
120
75
  rb_define_const(PlatformModule, "BYTE_ORDER", INT2FIX(BYTE_ORDER));
121
76
  rb_define_const(PlatformModule, "LITTLE_ENDIAN", INT2FIX(LITTLE_ENDIAN));
122
77
  rb_define_const(PlatformModule, "BIG_ENDIAN", INT2FIX(BIG_ENDIAN));
123
- rb_define_const(PlatformModule, "CPU", rb_str_new2(CPU));
124
78
  #if defined(__GNU__) || defined(__GLIBC__)
125
79
  rb_define_const(PlatformModule, "GNU_LIBC", rb_str_new2(LIBC_SO));
126
80
  #endif
127
81
  export_primitive_types(PlatformModule);
128
82
  }
129
-
@@ -70,13 +70,15 @@ rbffi_frame_current(void)
70
70
  #endif
71
71
  }
72
72
 
73
- void
73
+ void
74
74
  rbffi_frame_push(rbffi_frame_t* frame)
75
75
  {
76
76
  memset(frame, 0, sizeof(*frame));
77
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
77
78
  frame->has_gvl = true;
79
+ #endif
78
80
  frame->exc = Qnil;
79
-
81
+
80
82
  #ifdef _WIN32
81
83
  frame->prev = TlsGetValue(frame_thread_key);
82
84
  TlsSetValue(frame_thread_key, frame);
@@ -87,7 +89,7 @@ rbffi_frame_push(rbffi_frame_t* frame)
87
89
  #endif
88
90
  }
89
91
 
90
- void
92
+ void
91
93
  rbffi_frame_pop(rbffi_frame_t* frame)
92
94
  {
93
95
  #ifdef _WIN32
@@ -97,224 +99,6 @@ rbffi_frame_pop(rbffi_frame_t* frame)
97
99
  #endif
98
100
  }
99
101
 
100
- #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
101
-
102
- #if !defined(_WIN32)
103
-
104
- struct BlockingThread {
105
- pthread_t tid;
106
- VALUE (*fn)(void *);
107
- void *data;
108
- void (*ubf)(void *);
109
- void *data2;
110
- VALUE retval;
111
- int wrfd;
112
- int rdfd;
113
- };
114
-
115
- static void*
116
- rbffi_blocking_thread(void* args)
117
- {
118
- struct BlockingThread* thr = (struct BlockingThread *) args;
119
- char c = 1;
120
- VALUE retval;
121
-
122
- retval = (*thr->fn)(thr->data);
123
-
124
- pthread_testcancel();
125
-
126
- thr->retval = retval;
127
-
128
- write(thr->wrfd, &c, sizeof(c));
129
-
130
- return NULL;
131
- }
132
-
133
- static VALUE
134
- wait_for_thread(void *data)
135
- {
136
- struct BlockingThread* thr = (struct BlockingThread *) data;
137
- char c;
138
-
139
- if (read(thr->rdfd, &c, 1) < 1) {
140
- rb_thread_wait_fd(thr->rdfd);
141
- while (read(thr->rdfd, &c, 1) < 1 && rb_io_wait_readable(thr->rdfd) == Qtrue) {
142
- ;
143
- }
144
- }
145
-
146
- return Qnil;
147
- }
148
-
149
- static VALUE
150
- cleanup_blocking_thread(void *data, VALUE exc)
151
- {
152
- struct BlockingThread* thr = (struct BlockingThread *) data;
153
-
154
- if (thr->ubf != (void (*)(void *)) -1) {
155
- (*thr->ubf)(thr->data2);
156
- } else {
157
- pthread_kill(thr->tid, SIGVTALRM);
158
- }
159
-
160
- return exc;
161
- }
162
-
163
- VALUE
164
- rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
165
- {
166
- struct BlockingThread* thr;
167
- int fd[2];
168
- VALUE exc;
169
-
170
- if (pipe(fd) < 0) {
171
- rb_raise(rb_eSystemCallError, "pipe(2) failed");
172
- return Qnil;
173
- }
174
- fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_NONBLOCK);
175
-
176
- thr = ALLOC_N(struct BlockingThread, 1);
177
- thr->rdfd = fd[0];
178
- thr->wrfd = fd[1];
179
- thr->fn = func;
180
- thr->data = data1;
181
- thr->ubf = ubf;
182
- thr->data2 = data2;
183
- thr->retval = Qnil;
184
-
185
- if (pthread_create(&thr->tid, NULL, rbffi_blocking_thread, thr) != 0) {
186
- close(fd[0]);
187
- close(fd[1]);
188
- xfree(thr);
189
- rb_raise(rb_eSystemCallError, "pipe(2) failed");
190
- return Qnil;
191
- }
192
-
193
- exc = rb_rescue2(wait_for_thread, (VALUE) thr, cleanup_blocking_thread, (VALUE) thr,
194
- rb_eException);
195
-
196
- pthread_join(thr->tid, NULL);
197
- close(fd[1]);
198
- close(fd[0]);
199
- xfree(thr);
200
-
201
- if (exc != Qnil) {
202
- rb_exc_raise(exc);
203
- }
204
-
205
- return thr->retval;
206
- }
207
-
208
- #else
209
- /* win32 implementation */
210
-
211
- struct BlockingThread {
212
- HANDLE tid;
213
- VALUE (*fn)(void *);
214
- void *data;
215
- void (*ubf)(void *);
216
- void *data2;
217
- VALUE retval;
218
- int wrfd;
219
- int rdfd;
220
- };
221
-
222
- static DWORD __stdcall
223
- rbffi_blocking_thread(LPVOID args)
224
- {
225
- struct BlockingThread* thr = (struct BlockingThread *) args;
226
- char c = 1;
227
- VALUE retval;
228
-
229
- retval = (*thr->fn)(thr->data);
230
- thr->retval = retval;
231
-
232
- write(thr->wrfd, &c, sizeof(c));
233
-
234
- return 0;
235
- }
236
-
237
- static VALUE
238
- wait_for_thread(void *data)
239
- {
240
- struct BlockingThread* thr = (struct BlockingThread *) data;
241
- char c, res;
242
- fd_set rfds;
243
-
244
- FD_ZERO(&rfds);
245
- FD_SET(thr->rdfd, &rfds);
246
- rb_thread_select(thr->rdfd + 1, &rfds, NULL, NULL, NULL);
247
- read(thr->rdfd, &c, 1);
248
- return Qnil;
249
- }
250
-
251
- static VALUE
252
- cleanup_blocking_thread(void *data, VALUE exc)
253
- {
254
- struct BlockingThread* thr = (struct BlockingThread *) data;
255
-
256
- if (thr->ubf != (void (*)(void *)) -1) {
257
- (*thr->ubf)(thr->data2);
258
- } else {
259
- TerminateThread(thr->tid, 0);
260
- }
261
-
262
- return exc;
263
- }
264
-
265
- VALUE
266
- rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
267
- {
268
- struct BlockingThread* thr;
269
- int fd[2];
270
- VALUE exc;
271
- DWORD state;
272
- DWORD res;
273
-
274
- if (_pipe(fd, 1024, O_BINARY) == -1) {
275
- rb_raise(rb_eSystemCallError, "_pipe() failed");
276
- return Qnil;
277
- }
278
-
279
- thr = ALLOC_N(struct BlockingThread, 1);
280
- thr->rdfd = fd[0];
281
- thr->wrfd = fd[1];
282
- thr->fn = func;
283
- thr->data = data1;
284
- thr->ubf = ubf;
285
- thr->data2 = data2;
286
- thr->retval = Qnil;
287
-
288
- thr->tid = CreateThread(NULL, 0, rbffi_blocking_thread, thr, 0, NULL);
289
- if (!thr->tid) {
290
- close(fd[0]);
291
- close(fd[1]);
292
- xfree(thr);
293
- rb_raise(rb_eSystemCallError, "CreateThread() failed");
294
- return Qnil;
295
- }
296
-
297
- exc = rb_rescue2(wait_for_thread, (VALUE) thr, cleanup_blocking_thread, (VALUE) thr,
298
- rb_eException);
299
-
300
- /* The thread should be finished, already. */
301
- WaitForSingleObject(thr->tid, INFINITE);
302
- CloseHandle(thr->tid);
303
- close(fd[1]);
304
- close(fd[0]);
305
- xfree(thr);
306
-
307
- if (exc != Qnil) {
308
- rb_exc_raise(exc);
309
- }
310
-
311
- return thr->retval;
312
- }
313
-
314
- #endif /* !_WIN32 */
315
-
316
- #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
317
-
318
102
  #ifndef _WIN32
319
103
  static struct thread_data* thread_data_init(void);
320
104
 
@@ -348,6 +132,6 @@ rbffi_Thread_Init(VALUE moduleFFI)
348
132
  #ifdef _WIN32
349
133
  frame_thread_key = TlsAlloc();
350
134
  #else
351
- pthread_key_create(&thread_data_key, thread_data_free);
135
+ pthread_key_create(&thread_data_key, thread_data_free);
352
136
  #endif
353
137
  }