ffi 1.10.0 → 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
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
  }