mirror of
https://github.com/ruby/ruby.git
synced 2025-09-17 01:23:57 +02:00

Remove "All Rights Reserved." from Copyright statement. Patch assembly so that it aligns properly Removed trailing spaces [ci skip] Fix build error on Apple silicon macOS This patch will fix following build error on macOS 11.0 + Xcode 12 beta. ``` $ ./configure $ make V=1 BASERUBY = /Users/watson/.rbenv/shims/ruby --disable=gems CC = clang -fdeclspec LD = ld LDSHARED = clang -fdeclspec -dynamiclib CFLAGS = -O3 -ggdb3 -Wall -Wextra -Werror=deprecated-declarations -Werror=division-by-zero -Werror=implicit-function-declaration -Werror=implicit-int -Werror=misleading-indentation -Werror=pointer-arith -Werror=shorten-64-to-32 -Werror=write-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Werror=extra-tokens -std=gnu99 -pipe XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fno-strict-overflow -DRUBY_DEVEL=1 -fvisibility=hidden -DRUBY_EXPORT -fPIE -DCANONICALIZATION_FOR_MATHN -I. -I.ext/include/arm64-darwin20 -I./include -I. -I./enc/unicode/12.1.0 CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT DLDFLAGS = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -fstack-protector-strong -Wl,-pie -framework Security -framework Foundation SOLIBS = -lpthread -ldl -lobjc LANG = ja_JP.UTF-8 LC_ALL = LC_CTYPE = MFLAGS = Apple clang version 12.0.0 (clang-1200.0.22.19) Target: arm64-apple-darwin20.0.0 Thread model: posix InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin clang -fdeclspec -O3 -ggdb3 -Wall -Wextra -Werror=deprecated-declarations -Werror=division-by-zero -Werror=implicit-function-declaration -Werror=implicit-int -Werror=misleading-indentation -Werror=pointer-arith -Werror=shorten-64-to-32 -Werror=write-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Werror=extra-tokens -std=gnu99 -pipe -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fno-strict-overflow -DRUBY_DEVEL=1 -fvisibility=hidden -DRUBY_EXPORT -fPIE -DCANONICALIZATION_FOR_MATHN -I. -I.ext/include/arm64-darwin20 -I./include -I. -I./enc/unicode/12.1.0 -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -o cont.o -c cont.c In file included from cont.c:19: ./coroutine/ucontext/Context.h:32:5: error: 'getcontext' is deprecated: first deprecated in macOS 10.6 [-Werror,-Wdeprecated-declarations] getcontext(&context->state); ^ /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ucontext.h:37:6: note: 'getcontext' has been explicitly marked deprecated here int getcontext(ucontext_t *) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0) __WATCHOS_PROHIBITED __TVOS_PROHIBITED; ^ In file included from cont.c:19: ./coroutine/ucontext/Context.h:51:5: error: 'makecontext' is deprecated: first deprecated in macOS 10.6 [-Werror,-Wdeprecated-declarations] makecontext(&context->state, (void(*)(void))coroutine_trampoline, 2, (void*)start, (void*)context); ^ /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ucontext.h:38:6: note: 'makecontext' has been explicitly marked deprecated here void makecontext(ucontext_t *, void (*)(), int, ...) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_2_0) __WATCHOS_PROHI... ^ In file included from cont.c:19: ./coroutine/ucontext/Context.h:59:5: error: 'swapcontext' is deprecated: first deprecated in macOS 10.6 [-Werror,-Wdeprecated-declarations] swapcontext(¤t->state, &target->state); ^ /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ucontext.h:40:6: note: 'swapcontext' has been explicitly marked deprecated here int swapcontext(ucontext_t * __restrict, const ucontext_t * __restrict) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_6, __IPHONE_2_0, __IPHONE_... ^ 3 errors generated. make: *** [cont.o] Error 1 ``` Extract correct processor name for ARM64 Macs Prefix export symbol prefix to coroutine_transfer Revert "Revert "[ruby/fiddle] Use ffi_closure_free by default. (#20)"" This reverts commitefd641ffab
. This changeset seems to be needed to suppress a warning on Ubuntu 20.0420200304
T033004Z.log.html.gz ``` closure.c:264:5: warning: 'ffi_prep_closure' is deprecated: use ffi_prep_closure_loc instead [-Wdeprecated-declarations] 264 | result = ffi_prep_closure(pcl, cif, callback, (void *)self); | ^~~~~~ ``` I guess there was a reason why the commit was reverted (maybe some CIs failed?), so try it again.
317 lines
7.2 KiB
C
317 lines
7.2 KiB
C
#include <fiddle.h>
|
|
#include <ruby/thread.h>
|
|
|
|
int ruby_thread_has_gvl_p(void); /* from internal.h */
|
|
|
|
VALUE cFiddleClosure;
|
|
|
|
typedef struct {
|
|
void * code;
|
|
ffi_closure *pcl;
|
|
ffi_cif cif;
|
|
int argc;
|
|
ffi_type **argv;
|
|
} fiddle_closure;
|
|
|
|
static void
|
|
dealloc(void * ptr)
|
|
{
|
|
fiddle_closure * cls = (fiddle_closure *)ptr;
|
|
ffi_closure_free(cls->pcl);
|
|
if (cls->argv) xfree(cls->argv);
|
|
xfree(cls);
|
|
}
|
|
|
|
static size_t
|
|
closure_memsize(const void * ptr)
|
|
{
|
|
fiddle_closure * cls = (fiddle_closure *)ptr;
|
|
size_t size = 0;
|
|
|
|
size += sizeof(*cls);
|
|
#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
|
|
size += ffi_raw_size(&cls->cif);
|
|
#endif
|
|
size += sizeof(*cls->argv);
|
|
size += sizeof(ffi_closure);
|
|
|
|
return size;
|
|
}
|
|
|
|
const rb_data_type_t closure_data_type = {
|
|
"fiddle/closure",
|
|
{0, dealloc, closure_memsize,},
|
|
};
|
|
|
|
struct callback_args {
|
|
ffi_cif *cif;
|
|
void *resp;
|
|
void **args;
|
|
void *ctx;
|
|
};
|
|
|
|
static void *
|
|
with_gvl_callback(void *ptr)
|
|
{
|
|
struct callback_args *x = ptr;
|
|
|
|
VALUE self = (VALUE)x->ctx;
|
|
VALUE rbargs = rb_iv_get(self, "@args");
|
|
VALUE ctype = rb_iv_get(self, "@ctype");
|
|
int argc = RARRAY_LENINT(rbargs);
|
|
VALUE params = rb_ary_tmp_new(argc);
|
|
VALUE ret;
|
|
VALUE cPointer;
|
|
int i, type;
|
|
|
|
cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
type = NUM2INT(RARRAY_AREF(rbargs, i));
|
|
switch (type) {
|
|
case TYPE_VOID:
|
|
argc = 0;
|
|
break;
|
|
case TYPE_INT:
|
|
rb_ary_push(params, INT2NUM(*(int *)x->args[i]));
|
|
break;
|
|
case -TYPE_INT:
|
|
rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i]));
|
|
break;
|
|
case TYPE_VOIDP:
|
|
rb_ary_push(params,
|
|
rb_funcall(cPointer, rb_intern("[]"), 1,
|
|
PTR2NUM(*(void **)x->args[i])));
|
|
break;
|
|
case TYPE_LONG:
|
|
rb_ary_push(params, LONG2NUM(*(long *)x->args[i]));
|
|
break;
|
|
case -TYPE_LONG:
|
|
rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i]));
|
|
break;
|
|
case TYPE_CHAR:
|
|
rb_ary_push(params, INT2NUM(*(signed char *)x->args[i]));
|
|
break;
|
|
case -TYPE_CHAR:
|
|
rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i]));
|
|
break;
|
|
case TYPE_SHORT:
|
|
rb_ary_push(params, INT2NUM(*(signed short *)x->args[i]));
|
|
break;
|
|
case -TYPE_SHORT:
|
|
rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i]));
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
rb_ary_push(params, rb_float_new(*(double *)x->args[i]));
|
|
break;
|
|
case TYPE_FLOAT:
|
|
rb_ary_push(params, rb_float_new(*(float *)x->args[i]));
|
|
break;
|
|
#if HAVE_LONG_LONG
|
|
case TYPE_LONG_LONG:
|
|
rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i]));
|
|
break;
|
|
case -TYPE_LONG_LONG:
|
|
rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
|
|
break;
|
|
#endif
|
|
default:
|
|
rb_raise(rb_eRuntimeError, "closure args: %d", type);
|
|
}
|
|
}
|
|
|
|
ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_CONST_PTR(params));
|
|
RB_GC_GUARD(params);
|
|
|
|
type = NUM2INT(ctype);
|
|
switch (type) {
|
|
case TYPE_VOID:
|
|
break;
|
|
case TYPE_LONG:
|
|
*(long *)x->resp = NUM2LONG(ret);
|
|
break;
|
|
case -TYPE_LONG:
|
|
*(unsigned long *)x->resp = NUM2ULONG(ret);
|
|
break;
|
|
case TYPE_CHAR:
|
|
case TYPE_SHORT:
|
|
case TYPE_INT:
|
|
*(ffi_sarg *)x->resp = NUM2INT(ret);
|
|
break;
|
|
case -TYPE_CHAR:
|
|
case -TYPE_SHORT:
|
|
case -TYPE_INT:
|
|
*(ffi_arg *)x->resp = NUM2UINT(ret);
|
|
break;
|
|
case TYPE_VOIDP:
|
|
*(void **)x->resp = NUM2PTR(ret);
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
*(double *)x->resp = NUM2DBL(ret);
|
|
break;
|
|
case TYPE_FLOAT:
|
|
*(float *)x->resp = (float)NUM2DBL(ret);
|
|
break;
|
|
#if HAVE_LONG_LONG
|
|
case TYPE_LONG_LONG:
|
|
*(LONG_LONG *)x->resp = NUM2LL(ret);
|
|
break;
|
|
case -TYPE_LONG_LONG:
|
|
*(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
|
|
break;
|
|
#endif
|
|
default:
|
|
rb_raise(rb_eRuntimeError, "closure retval: %d", type);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
callback(ffi_cif *cif, void *resp, void **args, void *ctx)
|
|
{
|
|
struct callback_args x;
|
|
|
|
x.cif = cif;
|
|
x.resp = resp;
|
|
x.args = args;
|
|
x.ctx = ctx;
|
|
|
|
if (ruby_thread_has_gvl_p()) {
|
|
(void)with_gvl_callback(&x);
|
|
} else {
|
|
(void)rb_thread_call_with_gvl(with_gvl_callback, &x);
|
|
}
|
|
}
|
|
|
|
static VALUE
|
|
allocate(VALUE klass)
|
|
{
|
|
fiddle_closure * closure;
|
|
|
|
VALUE i = TypedData_Make_Struct(klass, fiddle_closure,
|
|
&closure_data_type, closure);
|
|
|
|
closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code);
|
|
|
|
return i;
|
|
}
|
|
|
|
static VALUE
|
|
initialize(int rbargc, VALUE argv[], VALUE self)
|
|
{
|
|
VALUE ret;
|
|
VALUE args;
|
|
VALUE abi;
|
|
fiddle_closure * cl;
|
|
ffi_cif * cif;
|
|
ffi_closure *pcl;
|
|
ffi_status result;
|
|
int i, argc;
|
|
|
|
if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
|
|
abi = INT2NUM(FFI_DEFAULT_ABI);
|
|
|
|
Check_Type(args, T_ARRAY);
|
|
|
|
argc = RARRAY_LENINT(args);
|
|
|
|
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
|
|
|
|
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
int type = NUM2INT(RARRAY_AREF(args, i));
|
|
cl->argv[i] = INT2FFI_TYPE(type);
|
|
}
|
|
cl->argv[argc] = NULL;
|
|
|
|
rb_iv_set(self, "@ctype", ret);
|
|
rb_iv_set(self, "@args", args);
|
|
|
|
cif = &cl->cif;
|
|
pcl = cl->pcl;
|
|
|
|
result = ffi_prep_cif(cif, NUM2INT(abi), argc,
|
|
INT2FFI_TYPE(NUM2INT(ret)),
|
|
cl->argv);
|
|
|
|
if (FFI_OK != result)
|
|
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
|
|
|
|
result = ffi_prep_closure_loc(pcl, cif, callback,
|
|
(void *)self, cl->code);
|
|
|
|
if (FFI_OK != result)
|
|
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
|
|
|
|
return self;
|
|
}
|
|
|
|
static VALUE
|
|
to_i(VALUE self)
|
|
{
|
|
fiddle_closure * cl;
|
|
void *code;
|
|
|
|
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
|
|
|
|
code = cl->code;
|
|
|
|
return PTR2NUM(code);
|
|
}
|
|
|
|
void
|
|
Init_fiddle_closure(void)
|
|
{
|
|
#if 0
|
|
mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */
|
|
#endif
|
|
|
|
/*
|
|
* Document-class: Fiddle::Closure
|
|
*
|
|
* == Description
|
|
*
|
|
* An FFI closure wrapper, for handling callbacks.
|
|
*
|
|
* == Example
|
|
*
|
|
* closure = Class.new(Fiddle::Closure) {
|
|
* def call
|
|
* 10
|
|
* end
|
|
* }.new(Fiddle::TYPE_INT, [])
|
|
* #=> #<#<Class:0x0000000150d308>:0x0000000150d240>
|
|
* func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
|
|
* #=> #<Fiddle::Function:0x00000001516e58>
|
|
* func.call
|
|
* #=> 10
|
|
*/
|
|
cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject);
|
|
|
|
rb_define_alloc_func(cFiddleClosure, allocate);
|
|
|
|
/*
|
|
* Document-method: new
|
|
*
|
|
* call-seq: new(ret, args, abi = Fiddle::DEFAULT)
|
|
*
|
|
* Construct a new Closure object.
|
|
*
|
|
* * +ret+ is the C type to be returned
|
|
* * +args+ is an Array of arguments, passed to the callback function
|
|
* * +abi+ is the abi of the closure
|
|
*
|
|
* If there is an error in preparing the ffi_cif or ffi_prep_closure,
|
|
* then a RuntimeError will be raised.
|
|
*/
|
|
rb_define_method(cFiddleClosure, "initialize", initialize, -1);
|
|
|
|
/*
|
|
* Document-method: to_i
|
|
*
|
|
* Returns the memory address for this closure
|
|
*/
|
|
rb_define_method(cFiddleClosure, "to_i", to_i, 0);
|
|
}
|
|
/* vim: set noet sw=4 sts=4 */
|