/* foreign4.c * Copyright 1984-2017 Cisco Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #if defined(_REENTRANT) || defined(_WIN32) # ifdef _WIN32 # include # define SCHEME_IMPORT # include "scheme.h" # else # include # include "scheme.h" # endif # undef EXPORT #endif typedef signed char i8; typedef unsigned char u8; typedef unsigned short u16; #ifdef _WIN32 typedef __int64 i64; # define EXPORT extern __declspec (dllexport) #else typedef long long i64; # define EXPORT #endif /* To help make sure that argument and result handling doesn't read or write too far, try to provide functions that allocate a structure at the end of a memory page (where the next page is likely to be unmapped) */ #if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) # include # include # include # include EXPORT void *malloc_at_boundary(int sz) { intptr_t alloc_size = getpagesize(); char *p; p = mmap(NULL, 2 * alloc_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); mprotect(p + alloc_size, alloc_size, PROT_NONE); return p + alloc_size - sz; } EXPORT void free_at_boundary(void *p) { intptr_t alloc_size = getpagesize(); munmap((void *)(((intptr_t)p) & ~(alloc_size-1)), 2 * alloc_size); } #elif defined(_WIN32) EXPORT void *malloc_at_boundary(int sz) { SYSTEM_INFO si; char *p; DWORD dummy; GetSystemInfo(&si); p = VirtualAlloc(NULL, 2 * si.dwPageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); VirtualProtect(p + si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &dummy); return p + si.dwPageSize - sz; } EXPORT void free_at_boundary(void *p) { SYSTEM_INFO si; GetSystemInfo(&si); VirtualFree((void *)(((intptr_t)p) & ~(si.dwPageSize-1)), 0, MEM_RELEASE); } #else EXPORT void *malloc_at_boundary(int sz) { return malloc(sz); } EXPORT void free_at_boundary(void *p) { free(p); } #endif #if defined(_REENTRANT) || defined(_WIN32) typedef struct in_thread_args_t { double (*proc)(double arg); double arg; int n_times; } in_thread_args_t; void *in_thread(void *_proc_and_arg) { in_thread_args_t *proc_and_arg = _proc_and_arg; int i; for (i = 0; i < proc_and_arg->n_times; i++) { proc_and_arg->arg = proc_and_arg->proc(proc_and_arg->arg); } return NULL; } #if defined(_WIN32) # define os_thread_t unsigned # define os_thread_create(addr, proc, arg) (((*(addr)) = _beginthread(proc, 0, arg)) == -1) # define os_thread_join(t) WaitForSingleObject((HANDLE)(intptr_t)(t), INFINITE) #else # define os_thread_t pthread_t # define os_thread_create(addr, proc, arg) pthread_create(addr, NULL, in_thread, proc_and_arg) # define os_thread_join(t) pthread_join(t, NULL) #endif #ifdef FEATURE_PTHREADS EXPORT double call_in_unknown_thread(double (*proc)(double arg), double arg, int n_times, int do_fork, int do_deactivate) { os_thread_t t; in_thread_args_t *proc_and_arg = malloc(sizeof(in_thread_args_t)); proc_and_arg->proc = proc; proc_and_arg->arg = arg; proc_and_arg->n_times = n_times; if (do_fork) { if (do_deactivate) Sdeactivate_thread(); if (!os_thread_create(&t, in_thread, proc_and_arg)) { os_thread_join(t); } if (do_deactivate) Sactivate_thread(); } else { in_thread(proc_and_arg); } arg = proc_and_arg->arg; free(proc_and_arg); return arg; } #endif /* FEATURE_PTHREADS */ #endif EXPORT unsigned spin_a_while(int amt, unsigned a, unsigned b) { int i; /* A loop that the compiler is unlikely to optimize away */ for (i = 0; i < amt; i++) { a = a + b; b = b + a; } return a; } #define GEN(ts, init, sum) \ EXPORT ts f4_get_ ## ts () { \ ts r = init; \ return r; \ } \ EXPORT double f4_sum_ ## ts (ts v) { \ return sum(v); \ } \ EXPORT double f4_sum_two_ ## ts (ts v1, ts v2) { \ return sum(v1) + sum(v2); \ } \ EXPORT double f4_sum_pre_double_ ## ts (double v0, ts v) { \ return v0 + sum(v); \ } \ EXPORT double f4_sum_pre_double_double_ ## ts (double v0, double v1, ts v) { \ return v0 + v1 + sum(v); \ } \ EXPORT double f4_sum_pre_double_double_double_double_ ## ts (double v0, double v1, double v2, double v3, ts v) { \ return v0 + v1 + v2 + v3 + sum(v); \ } \ EXPORT double f4_sum_pre_double_double_double_double_double_double_double_double_ ## ts \ (double v0, double v1, double v2, double v3, double v4, double v5, double v6, double v7, ts v) { \ return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + sum(v); \ } \ EXPORT double f4_sum_ ## ts ## _post_double (ts v, double v0) { \ return v0 + sum(v); \ } \ EXPORT double f4_sum_pre_int_ ## ts (int v0, ts v) { \ return (double)v0 + sum(v); \ } \ EXPORT double f4_sum_pre_int_int_ ## ts (int v0, int v1, ts v) { \ return (double)v0 + (double)v1 + sum(v); \ } \ EXPORT double f4_sum_pre_int_int_int_int_ ## ts (int v0, int v1, int v2, int v3, ts v) { \ return (double)v0 + (double)v1 + (double)v2 + (double)v3 + sum(v); \ } \ EXPORT double f4_sum_pre_int_int_int_int_int_int_ ## ts (int v0, int v1, int v2, int v3, int v4, int v5, ts v) { \ return (double)v0 + (double)v1 + (double)v2 + (double)v3 + (double)v4 + (double)v5 + sum(v); \ } \ EXPORT double f4_sum_ ## ts ## _post_int (ts v, int v0) { \ return (double)v0 + sum(v); \ } \ EXPORT double f4_cb_send_ ## ts (double (*cb)(ts)) { \ ts r = init; \ return cb(r) + 1.0; \ } \ EXPORT double f4_cb_send_two_ ## ts (double (*cb)(ts, ts)) { \ ts r1 = init; \ ts r2 = init; \ return cb(r1, r2) + 1.0; \ } \ EXPORT double f4_cb_send_pre_int_ ## ts (double (*cb)(int, ts)) { \ ts r = init; \ return cb(8, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_int_int_ ## ts (double (*cb)(int, int, ts)) { \ ts r = init; \ return cb(8, 9, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_int_int_int_int_ ## ts (double (*cb)(int, int, int, int, ts)) { \ ts r = init; \ return cb(8, 9, 10, 11, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_int_int_int_int_int_int_ ## ts (double (*cb)(int, int, int, int, int, int, ts)) { \ ts r = init; \ return cb(8, 9, 10, 11, 12, 13, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_double_ ## ts (double (*cb)(double, ts)) { \ ts r = init; \ return cb(8.25, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_double_double_ ## ts (double (*cb)(double, double, ts)) { \ ts r = init; \ return cb(8.25, 9.25, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_double_double_double_double_ ## ts (double (*cb)(double, double, double, double, ts)) { \ ts r = init; \ return cb(8.25, 9.25, 10.25, 11.25, r) + 1.0; \ } \ EXPORT double f4_cb_send_pre_double_double_double_double_double_double_double_double_ ## ts \ (double (*cb)(double, double, double, double, double, double, double, double, ts)) { \ ts r = init; \ return cb(8.25, 9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, r) + 1.0; \ } \ EXPORT double f4_sum_cb_ ## ts (ts (*cb)()) { \ ts v = cb(); \ return sum(v); \ } #define TO_DOUBLE(x) ((double)(x)) GEN(i8, -11, TO_DOUBLE) GEN(u8, 129, TO_DOUBLE) GEN(short, -22, TO_DOUBLE) GEN(u16, 33022, TO_DOUBLE) GEN(long, 33, TO_DOUBLE) GEN(int, 44, TO_DOUBLE) GEN(i64, 49, TO_DOUBLE) GEN(float, 55.0, TO_DOUBLE) GEN(double, 66.0, TO_DOUBLE) /* Some ABIs treat a struct containing a single field different that just the field */ #define GEN_1(t1, v1) \ typedef struct struct_ ## t1 { t1 x; } struct_ ## t1; \ static double _f4_sum_struct_ ## t1 (struct_ ## t1 v) { \ return (double)v.x; \ } \ static struct_ ## t1 init_struct_ ## t1 = { v1 }; \ GEN(struct_ ## t1, init_struct_ ## t1, _f4_sum_struct_ ## t1) GEN_1(i8, -12) GEN_1(u8, 212) GEN_1(short, -23) GEN_1(u16, 33023) GEN_1(long, 34) GEN_1(int, 45) GEN_1(i64, 48) GEN_1(float, 56.0) GEN_1(double, 67.0) #define GEN_2(t1, t2, v1, v2) \ typedef struct struct_ ## t1 ## _ ## t2 { t1 x; t2 y; } struct_ ## t1 ## _ ## t2; \ static double _f4_sum_struct_ ## t1 ## _ ## t2 (struct_ ## t1 ## _ ## t2 v) { \ return (double)v.x + (double)v.y; \ } \ static struct_ ## t1 ## _ ## t2 init_struct_ ## t1 ## _ ## t2 = { v1, v2 }; \ GEN(struct_ ## t1 ## _ ## t2, init_struct_ ## t1 ## _ ## t2, _f4_sum_struct_ ## t1 ## _ ## t2) #define GEN_2_SET(t, x) \ GEN_2(t, i8, 1+x, 10) \ GEN_2(t, short, 2+x, 20) \ GEN_2(t, long, 3+x, 30) \ GEN_2(t, i64, 5+x, 50) \ GEN_2(short, t, 6, 60+x) \ GEN_2(long, t, 7, 70+x) \ GEN_2(i64, t, 9, 90+x) \ GEN_2(i8, t, 10, 100+x) GEN_2_SET(int, 0) GEN_2_SET(float, 0.5) GEN_2_SET(double, 0.25) GEN_2(int, int, 4, 40) GEN_2(float, float, 4.5, 40.5) GEN_2(double, double, 4.25, 40.25) #define GEN_3(t1, t2, t3, v1, v2, v3) \ typedef struct struct_ ## t1 ## _ ## t2 ## _ ## t3 { t1 x; t2 y; t3 z; } struct_ ## t1 ## _ ## t2 ## _ ## t3; \ static double _f4_sum_struct_ ## t1 ## _ ## t2 ## _ ## t3 (struct_ ## t1 ## _ ## t2 ## _ ## t3 v) { \ return (double)v.x + (double)v.y + (double)v.z; \ } \ static struct_ ## t1 ## _ ## t2 ## _ ## t3 init_struct_ ## t1 ## _ ## t2 ## _ ## t3 = { v1, v2, v3 }; \ GEN(struct_ ## t1 ## _ ## t2 ## _ ## t3, init_struct_ ## t1 ## _ ## t2 ## _ ## t3, _f4_sum_struct_ ## t1 ## _ ## t2 ## _ ## t3) #define GEN_3_SET(t, x) \ GEN_3(t, i8, int, 1+x, 10, 100) \ GEN_3(t, short, int, 2+x, 20, 200) \ GEN_3(t, long, int, 3+x, 30, 300) \ GEN_3(t, i64, int, 5+x, 50, 500) \ GEN_3(short, t, int, 6, 60+x, 600) \ GEN_3(long, t, int, 7, 70+x, 700) \ GEN_3(i64, t, int, 9, 90+x, 900) \ GEN_3(i8, t, int, 10, 100+x, 1000) GEN_3_SET(int, 0) GEN_3_SET(float, 0.5) GEN_3_SET(double, 0.25) GEN_3(i8, i8, i8, 4, 38, 127) GEN_3(short, short, short, 4, 39, 399) GEN_3(int, int, int, 4, 40, 400) GEN_3(float, float, float, 4.5, 40.5, 400.5) GEN_3(double, double, double, 4.25, 40.25, 400.25) typedef struct struct_i8_i8_i8_i8_i8 { i8 x, y, z, w, q; } struct_i8_i8_i8_i8_i8; static double _f4_sum_struct_i8_i8_i8_i8_i8 (struct_i8_i8_i8_i8_i8 v) { return (double)v.x + (double)v.y + (double)v.z + (double)v.w + (double)v.q; } static struct struct_i8_i8_i8_i8_i8 init_struct_i8_i8_i8_i8_i8 = { 1, 2, 3, 4, 5 }; GEN(struct_i8_i8_i8_i8_i8, init_struct_i8_i8_i8_i8_i8, _f4_sum_struct_i8_i8_i8_i8_i8) typedef struct struct_i8_i8_i8_i8_i8_i8_i8 { i8 x, y, z, w, q, r, s; } struct_i8_i8_i8_i8_i8_i8_i8; static double _f4_sum_struct_i8_i8_i8_i8_i8_i8_i8 (struct struct_i8_i8_i8_i8_i8_i8_i8 v) { return (double)v.x + (double)v.y + (double)v.z + (double)v.w + (double)v.q + (double)v.r + (double)v.s; } static struct struct_i8_i8_i8_i8_i8_i8_i8 init_struct_i8_i8_i8_i8_i8_i8_i8 = { 1, 2, 3, 4, 5, 6, 7 }; GEN(struct_i8_i8_i8_i8_i8_i8_i8, init_struct_i8_i8_i8_i8_i8_i8_i8, _f4_sum_struct_i8_i8_i8_i8_i8_i8_i8) /* Some ABIs treat a union containing a single field different that just the field */ #define GEN_U1(t1, v1) \ typedef union union_ ## t1 { t1 x; } union_ ## t1; \ static double _f4_sum_union_ ## t1 (union_ ## t1 v) { \ return (double)v.x; \ } \ static union_ ## t1 init_union_ ## t1 = { v1 }; \ GEN(union_ ## t1, init_union_ ## t1, _f4_sum_union_ ## t1) GEN_U1(i8, -17) GEN_U1(u8, 217) GEN_U1(short, -27) GEN_U1(u16, 33027) GEN_U1(long, 37) GEN_U1(int, 47) GEN_U1(i64, 49) GEN_U1(float, 57.0) GEN_U1(double, 77.0) #define GEN_U2(t1, t2, v1) \ typedef union union_ ## t1 ## _ ## t2 { t1 x; t2 y; } union_ ## t1 ## _ ## t2; \ static double _f4_sum_union_ ## t1 ## _ ## t2 (union_ ## t1 ## _ ## t2 v) { \ return (double)v.x; \ } \ static union_ ## t1 ## _ ## t2 init_union_ ## t1 ## _ ## t2 = { v1 }; \ GEN(union_ ## t1 ## _ ## t2, init_union_ ## t1 ## _ ## t2, _f4_sum_union_ ## t1 ## _ ## t2) GEN_U2(i8, int, 18) GEN_U2(short, int, 28) GEN_U2(long, int, 38) GEN_U2(int, int, 48) GEN_U2(i64, int, 43) GEN_U2(float, int, 58.0) GEN_U2(double, int, 68.0)