#include <ffi.h>
+#ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
+# if HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+# if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+# endif
+#endif
+
+static void *psi_ffi_closure_alloc(size_t s, void **code)
+{
+#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
+ return ffi_closure_alloc(s, code);
+#elif HAVE_MMAP
+ *code = mmap(NULL, s, PROT_EXEC|PROT_WRITE|PROT_READ,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (MAP_FAILED == *code) {
+ return NULL;
+ }
+ return *code;
+#else
+ return NULL;
+#endif
+}
+
+static void psi_ffi_closure_free(void *c)
+{
+#ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
+ ffi_closure_free(c);
+#elif HAVE_MMAP
+ munmap(c, sizeof(ffi_closure));
+#endif
+}
+
static void handler(ffi_cif *signature, void *_result, void **_args, void *_data);
static inline ffi_abi psi_ffi_abi(const char *convention) {
psi_ffi_decl_arg_type(data->impl->decl->func),
data->params);
ZEND_ASSERT(FFI_OK == rc);
- data->closure = ffi_closure_alloc(sizeof(ffi_closure), &data->code);
+
+ data->closure = psi_ffi_closure_alloc(sizeof(ffi_closure), &data->code);
+ ZEND_ASSERT(data->closure != NULL);
+#if PSI_HAVE_FFI_PREP_CLOSURE_LOC
rc = ffi_prep_closure_loc(
data->closure,
&context->signature,
data,
data->code);
ZEND_ASSERT(FFI_OK == rc);
+#elif PSI_HAVE_FFI_PREP_CLOSURE
+ rc = ffi_prep_closure(data->code, &context->signature, handler, data);
+ ZEND_ASSERT(FFI_OK == rc);
+#else
+# error "Neither ffi_prep_closure() nor ffi_prep_closure_loc() available"
+#endif
context->data.list = realloc(context->data.list, ++context->data.count * sizeof(*context->data.list));
context->data.list[context->data.count-1] = data;
}
static inline void PSI_LibffiDataFree(PSI_LibffiData *data) {
+ psi_ffi_closure_free(data->closure);
free(data->arginfo);
- ffi_closure_free(data->closure);
free(data);
}