f939c86d9495e13d975553a57562ad145dc0be18
[m6w6/ext-psi] / src / libffi_compat.h
1 /*******************************************************************************
2 Copyright (c) 2018, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #ifndef PSI_LIBFFI_COMPAT_H
27 #define PSI_LIBFFI_COMPAT_H
28
29 #include "php_psi_stdinc.h"
30
31 #undef PACKAGE
32 #undef PACKAGE_BUGREPORT
33 #undef PACKAGE_NAME
34 #undef PACKAGE_STRING
35 #undef PACKAGE_TARNAME
36 #undef PACKAGE_VERSION
37
38 #include <ffi.h>
39
40 #ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
41 # if HAVE_UNISTD_H
42 # include <unistd.h>
43 # endif
44 # if HAVE_SYS_MMAN_H
45 # include <sys/mman.h>
46 # ifndef MAP_ANONYMOUS
47 # define MAP_ANONYMOUS MAP_ANON
48 # endif
49 # endif
50 #endif
51
52 static inline void *psi_ffi_closure_alloc(size_t s, void **code)
53 {
54 #ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
55 return ffi_closure_alloc(s, code);
56 #elif HAVE_MMAP
57 *code = mmap(NULL, s, PROT_EXEC|PROT_WRITE|PROT_READ,
58 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
59 if (MAP_FAILED == *code) {
60 return NULL;
61 }
62 return *code;
63 #else
64 # error "Neither ffi_closure_alloc() nor mmap() available"
65 #endif
66 }
67
68 static inline ffi_status psi_ffi_prep_closure(ffi_closure **closure, void **code, ffi_cif *sig, void (*handler)(ffi_cif*,void*,void**,void*), void *data) {
69 *closure = psi_ffi_closure_alloc(sizeof(ffi_closure), code);
70 assert(*closure != NULL);
71
72 #if PSI_HAVE_FFI_PREP_CLOSURE_LOC
73 return ffi_prep_closure_loc(*closure, sig, handler, data, *code);
74
75 #elif PSI_HAVE_FFI_PREP_CLOSURE
76 return ffi_prep_closure(*code, sig, handler, data);
77 #else
78 # error "Neither ffi_prep_closure() nor ffi_prep_closure_loc() is available"
79 abort(); /* fix IDE warning */
80 #endif
81 }
82
83 static inline void psi_ffi_closure_free(void *c)
84 {
85 #ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
86 ffi_closure_free(c);
87 #elif HAVE_MMAP
88 munmap(c, sizeof(ffi_closure));
89 #endif
90 }
91
92 static inline void psi_ffi_prep_va(ffi_cif *base, ffi_cif *signature, size_t argc, size_t va_count,
93 ffi_type **param_types) {
94 ffi_status rc;
95
96 #ifdef PSI_HAVE_FFI_PREP_CIF_VAR
97 rc = ffi_prep_cif_var(signature, base->abi, argc, argc + va_count,
98 base->rtype, param_types);
99 #else
100 /* FIXME: test in config.m4; assume we can just call anyway */
101 rc = ffi_prep_cif(signature, base->abi, argc + va_count, base->rtype, param_types);
102 #endif
103
104 assert(FFI_OK == rc);
105 }
106
107
108 #endif /* LIBFFI_COMPAT_H */