summaryrefslogtreecommitdiff
path: root/spec/ruby/optional/capi/ext/thread_spec.c
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/optional/capi/ext/thread_spec.c')
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c113
1 files changed, 60 insertions, 53 deletions
diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c
index 3bfe76b925..ac77e4e813 100644
--- a/spec/ruby/optional/capi/ext/thread_spec.c
+++ b/spec/ruby/optional/capi/ext/thread_spec.c
@@ -4,30 +4,32 @@
#include <math.h>
#include <errno.h>
-#if HAVE_UNISTD_H
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(_WIN32)
-#define pipe(p) rb_w32_pipe(p)
+#include "ruby/win32.h"
+#define read rb_w32_read
+#define write rb_w32_write
+#define pipe rb_w32_pipe
+#endif
+
+#ifndef _WIN32
+#include <pthread.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef HAVE_RB_THREAD_ALONE
-static VALUE thread_spec_rb_thread_alone() {
+static VALUE thread_spec_rb_thread_alone(VALUE self) {
return rb_thread_alone() ? Qtrue : Qfalse;
}
-#endif
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
/* This is unblocked by unblock_func(). */
static void* blocking_gvl_func(void* data) {
int rfd = *(int *)data;
- char dummy;
+ char dummy = ' ';
ssize_t r;
do {
@@ -36,7 +38,7 @@ static void* blocking_gvl_func(void* data) {
close(rfd);
- return (void*)((r == 1) ? Qtrue : Qfalse);
+ return (void*)((r == 1 && dummy == 'A') ? Qtrue : Qfalse);
}
static void unblock_gvl_func(void *data) {
@@ -57,7 +59,7 @@ static VALUE thread_spec_rb_thread_call_without_gvl(VALUE self) {
void* ret;
if (pipe(fds) == -1) {
- return Qfalse;
+ rb_raise(rb_eRuntimeError, "could not create pipe");
}
ret = rb_thread_call_without_gvl(blocking_gvl_func, &fds[0],
unblock_gvl_func, &fds[1]);
@@ -65,7 +67,7 @@ static VALUE thread_spec_rb_thread_call_without_gvl(VALUE self) {
}
/* This is unblocked by a signal. */
-static void* blocking_gvl_func_for_udf_io(void *data) {
+static void* blocking_gvl_func_for_ubf_io(void *data) {
int rfd = (int)(size_t)data;
char dummy;
@@ -82,42 +84,32 @@ static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) {
void* ret;
if (pipe(fds) == -1) {
- return Qfalse;
+ rb_raise(rb_eRuntimeError, "could not create pipe");
}
- ret = rb_thread_call_without_gvl(blocking_gvl_func_for_udf_io,
+ ret = rb_thread_call_without_gvl(blocking_gvl_func_for_ubf_io,
(void*)(size_t)fds[0], RUBY_UBF_IO, 0);
close(fds[0]);
close(fds[1]);
return (VALUE)ret;
}
-#endif
-#ifdef HAVE_RB_THREAD_CURRENT
-static VALUE thread_spec_rb_thread_current() {
+static VALUE thread_spec_rb_thread_current(VALUE self) {
return rb_thread_current();
}
-#endif
-#ifdef HAVE_RB_THREAD_LOCAL_AREF
static VALUE thread_spec_rb_thread_local_aref(VALUE self, VALUE thr, VALUE sym) {
return rb_thread_local_aref(thr, SYM2ID(sym));
}
-#endif
-#ifdef HAVE_RB_THREAD_LOCAL_ASET
static VALUE thread_spec_rb_thread_local_aset(VALUE self, VALUE thr, VALUE sym, VALUE value) {
return rb_thread_local_aset(thr, SYM2ID(sym), value);
}
-#endif
-#ifdef HAVE_RB_THREAD_WAKEUP
static VALUE thread_spec_rb_thread_wakeup(VALUE self, VALUE thr) {
return rb_thread_wakeup(thr);
}
-#endif
-#ifdef HAVE_RB_THREAD_WAIT_FOR
static VALUE thread_spec_rb_thread_wait_for(VALUE self, VALUE s, VALUE ms) {
struct timeval tv;
tv.tv_sec = NUM2INT(s);
@@ -125,11 +117,9 @@ static VALUE thread_spec_rb_thread_wait_for(VALUE self, VALUE s, VALUE ms) {
rb_thread_wait_for(tv);
return Qnil;
}
-#endif
-
-#ifdef HAVE_RB_THREAD_CREATE
-VALUE thread_spec_call_proc(VALUE arg_array) {
+VALUE thread_spec_call_proc(void *arg_ptr) {
+ VALUE arg_array = (VALUE)arg_ptr;
VALUE arg = rb_ary_pop(arg_array);
VALUE proc = rb_ary_pop(arg_array);
return rb_funcall(proc, rb_intern("call"), 1, arg);
@@ -142,44 +132,61 @@ static VALUE thread_spec_rb_thread_create(VALUE self, VALUE proc, VALUE arg) {
return rb_thread_create(thread_spec_call_proc, (void*)args);
}
-#endif
+static VALUE thread_spec_ruby_native_thread_p(VALUE self) {
+ if (ruby_native_thread_p()) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
-void Init_thread_spec(void) {
- VALUE cls;
- cls = rb_define_class("CApiThreadSpecs", rb_cObject);
+#ifndef _WIN32
+static VALUE false_result = Qfalse;
+static VALUE true_result = Qtrue;
-#ifdef HAVE_RB_THREAD_ALONE
- rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0);
+static void *new_thread_check(void *args) {
+ if (ruby_native_thread_p()) {
+ return &true_result;
+ } else {
+ return &false_result;
+ }
+}
#endif
-#ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
- rb_define_method(cls, "rb_thread_call_without_gvl", thread_spec_rb_thread_call_without_gvl, 0);
- rb_define_method(cls, "rb_thread_call_without_gvl_with_ubf_io", thread_spec_rb_thread_call_without_gvl_with_ubf_io, 0);
+static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) {
+#ifndef _WIN32
+ pthread_t t;
+ void *result = &true_result;
+ pthread_create(&t, NULL, new_thread_check, NULL);
+ pthread_join(t, &result);
+ return *(VALUE *)result;
+#else
+ return Qfalse;
#endif
+}
-#ifdef HAVE_RB_THREAD_CURRENT
- rb_define_method(cls, "rb_thread_current", thread_spec_rb_thread_current, 0);
+#ifdef RUBY_VERSION_IS_4_0
+static VALUE thread_spec_ruby_thread_has_gvl_p(VALUE self) {
+ return ruby_thread_has_gvl_p() ? Qtrue : Qfalse;
+}
#endif
-#ifdef HAVE_RB_THREAD_LOCAL_AREF
+void Init_thread_spec(void) {
+ VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject);
+ rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0);
+ rb_define_method(cls, "rb_thread_call_without_gvl", thread_spec_rb_thread_call_without_gvl, 0);
+ rb_define_method(cls, "rb_thread_call_without_gvl_with_ubf_io", thread_spec_rb_thread_call_without_gvl_with_ubf_io, 0);
+ rb_define_method(cls, "rb_thread_current", thread_spec_rb_thread_current, 0);
rb_define_method(cls, "rb_thread_local_aref", thread_spec_rb_thread_local_aref, 2);
-#endif
-
-#ifdef HAVE_RB_THREAD_LOCAL_ASET
rb_define_method(cls, "rb_thread_local_aset", thread_spec_rb_thread_local_aset, 3);
-#endif
-
-#ifdef HAVE_RB_THREAD_WAKEUP
rb_define_method(cls, "rb_thread_wakeup", thread_spec_rb_thread_wakeup, 1);
-#endif
-
-#ifdef HAVE_RB_THREAD_WAIT_FOR
rb_define_method(cls, "rb_thread_wait_for", thread_spec_rb_thread_wait_for, 2);
-#endif
-
-#ifdef HAVE_RB_THREAD_CREATE
rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2);
+ rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0);
+ rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0);
+#ifdef RUBY_VERSION_IS_4_0
+ rb_define_method(cls, "ruby_thread_has_gvl_p", thread_spec_ruby_thread_has_gvl_p, 0);
#endif
}