diff options
author | Lars Kanis <lars@greiz-reinsdorf.de> | 2020-12-05 17:51:51 +0100 |
---|---|---|
committer | Lars Kanis <lars@greiz-reinsdorf.de> | 2020-12-05 17:51:51 +0100 |
commit | 9029cc0da03175c12b412e14f1fdf9814a2cf293 (patch) | |
tree | 02c17aa2402afcaa5034e02b18370a47d1fe534c | |
parent | d77419803ef92e9101b189743c9174df9079c60f (diff) | |
parent | a10ac1b8fadeed65064ed9a8e8d5956a9c2d6980 (diff) | |
download | ffi-9029cc0da03175c12b412e14f1fdf9814a2cf293.tar.gz |
Merge branch 'fix-crash-on-apple-silicon' of https://github.com/Watson1978/ffi into Watson1978-fix-crash-on-apple-silicon
-rw-r--r-- | ext/ffi_c/ClosurePool.c | 67 | ||||
-rw-r--r-- | ext/ffi_c/ClosurePool.h | 2 | ||||
-rw-r--r-- | ext/ffi_c/Function.c | 2 | ||||
-rw-r--r-- | ext/ffi_c/MethodHandle.c | 2 | ||||
-rw-r--r-- | ext/ffi_c/extconf.rb | 3 |
5 files changed, 74 insertions, 2 deletions
diff --git a/ext/ffi_c/ClosurePool.c b/ext/ffi_c/ClosurePool.c index 3934a3b..e15a4ee 100644 --- a/ext/ffi_c/ClosurePool.c +++ b/ext/ffi_c/ClosurePool.c @@ -58,6 +58,11 @@ #include "ClosurePool.h" +#if (defined(__arm64__) && defined(__APPLE__)) +#define USE_FFI_ALLOC 1 +#else +#define USE_FFI_ALLOC 0 +#endif #ifndef roundup # define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) @@ -107,7 +112,11 @@ cleanup_closure_pool(ClosurePool* pool) for (memory = pool->blocks; memory != NULL; ) { Memory* next = memory->next; +#if !USE_FFI_ALLOC freePage(memory->code); +#else + ffi_closure_free(memory->code); +#endif free(memory->data); free(memory); memory = next; @@ -126,6 +135,8 @@ rbffi_ClosurePool_Free(ClosurePool* pool) } } +#if !USE_FFI_ALLOC + Closure* rbffi_Closure_Alloc(ClosurePool* pool) { @@ -161,6 +172,7 @@ rbffi_Closure_Alloc(ClosurePool* pool) closure->next = &list[i + 1]; closure->pool = pool; closure->code = ((char *)code + (i * trampolineSize)); + closure->pcl = closure->code; if (!(*pool->prep)(pool->ctx, closure->code, closure, errmsg, sizeof(errmsg))) { goto error; @@ -197,6 +209,57 @@ error: return NULL; } +#else + +Closure* +rbffi_Closure_Alloc(ClosurePool* pool) +{ + Closure *closure = NULL; + Memory* block = NULL; + void *code = NULL; + void *pcl = NULL; + char errmsg[256]; + + block = calloc(1, sizeof(*block)); + closure = calloc(1, sizeof(*closure)); + pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + + if (block == NULL || closure == NULL || pcl == NULL) { + snprintf(errmsg, sizeof(errmsg), "failed to allocate a page. errno=%d (%s)", errno, strerror(errno)); + goto error; + } + + closure->pool = pool; + closure->code = code; + closure->pcl = pcl; + + if (!(*pool->prep)(pool->ctx, closure->code, closure, errmsg, sizeof(errmsg))) { + goto error; + } + + /* Track the allocated page + Closure memory area */ + block->data = closure; + block->code = pcl; + pool->blocks = block; + + /* Thread the new block onto the free list, apart from the first one. */ + pool->refcnt++; + + return closure; + +error: + free(block); + free(closure); + if (pcl != NULL) { + ffi_closure_free(pcl); + } + + rb_raise(rb_eRuntimeError, "%s", errmsg); + return NULL; +} + +#endif /* !USE_FFI_ALLOC */ + void rbffi_Closure_Free(Closure* closure) { @@ -232,6 +295,8 @@ getPageSize() #endif } +#if !USE_FFI_ALLOC + static void* allocatePage(void) { @@ -264,6 +329,8 @@ protectPage(void* page) #endif } +#endif /* !USE_FFI_ALLOC */ + void rbffi_ClosurePool_Init(VALUE module) { diff --git a/ext/ffi_c/ClosurePool.h b/ext/ffi_c/ClosurePool.h index b842375..36619f4 100644 --- a/ext/ffi_c/ClosurePool.h +++ b/ext/ffi_c/ClosurePool.h @@ -36,6 +36,8 @@ struct Closure_ { void* info; /* opaque handle for storing closure-instance specific data */ void* function; /* closure-instance specific function, called by custom trampoline */ void* code; /* The native trampoline code location */ + void* pcl; + struct ClosurePool_* pool; Closure* next; }; diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index 28aaaa1..305f8b1 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -844,7 +844,7 @@ callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errm FunctionType* fnInfo = (FunctionType *) ctx; ffi_status ffiStatus; - ffiStatus = ffi_prep_closure_loc(code, &fnInfo->ffi_cif, callback_invoke, closure, code); + ffiStatus = ffi_prep_closure_loc(closure->pcl, &fnInfo->ffi_cif, callback_invoke, closure, code); if (ffiStatus != FFI_OK) { snprintf(errmsg, errmsgsize, "ffi_prep_closure_loc failed. status=%#x", ffiStatus); return false; diff --git a/ext/ffi_c/MethodHandle.c b/ext/ffi_c/MethodHandle.c index c44167e..d047e10 100644 --- a/ext/ffi_c/MethodHandle.c +++ b/ext/ffi_c/MethodHandle.c @@ -136,7 +136,7 @@ prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t er #if defined(USE_RAW) ffiStatus = ffi_prep_raw_closure(code, &mh_cif, attached_method_invoke, closure); #else - ffiStatus = ffi_prep_closure_loc(code, &mh_cif, attached_method_invoke, closure, code); + ffiStatus = ffi_prep_closure_loc(closure->pcl, &mh_cif, attached_method_invoke, closure, code); #endif if (ffiStatus != FFI_OK) { snprintf(errmsg, errmsgsize, "ffi_prep_closure_loc failed. status=%#x", ffiStatus); diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb index 6dd28aa..a8bdc28 100644 --- a/ext/ffi_c/extconf.rb +++ b/ext/ffi_c/extconf.rb @@ -61,6 +61,9 @@ if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' File.open("Makefile", "a") do |mf| mf.puts "LIBFFI_HOST=--host=#{RbConfig::CONFIG['host_alias']}" if RbConfig::CONFIG.has_key?("host_alias") if RbConfig::CONFIG['host_os'].downcase =~ /darwin/ + if RbConfig::CONFIG['host'] =~ /arm/ + mf.puts "LIBFFI_HOST=--host=aarch64-apple-#{RbConfig::CONFIG['host_os']}" + end mf.puts "include ${srcdir}/libffi.darwin.mk" elsif RbConfig::CONFIG['host_os'].downcase =~ /bsd/ mf.puts '.include "${srcdir}/libffi.bsd.mk"' |