koffi 2.2.3-beta.3 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +23 -3
- package/doc/calls.md +277 -0
- package/doc/functions.md +17 -275
- package/doc/index.rst +3 -1
- package/doc/misc.md +97 -0
- package/doc/pointers.md +135 -0
- package/doc/types.md +3 -193
- package/package.json +2 -2
- package/src/koffi/build/2.2.4/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.4/koffi_win32_x64.tar.gz +0 -0
- package/src/koffi/src/abi_arm64.cc +39 -0
- package/src/koffi/src/abi_x64_sysv_fwd.S +9 -9
- package/src/koffi/src/abi_x64_win_fwd.asm +12 -12
- package/src/koffi/src/abi_x86_fwd.S +13 -13
- package/src/koffi/src/abi_x86_fwd.asm +11 -11
- package/src/koffi/src/ffi.cc +29 -52
- package/src/koffi/src/ffi.hh +0 -4
- package/src/koffi/test/CMakeLists.txt +7 -0
- package/src/koffi/test/win32.c +39 -0
- package/src/koffi/test/win32.js +70 -0
- package/src/koffi/tools/qemu.js +20 -9
- package/src/koffi/tools/registry/machines.json +10 -2
- package/doc/memory.md +0 -33
- package/src/koffi/build/2.2.3-beta.3/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.3-beta.3/koffi_win32_x64.tar.gz +0 -0
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
.cfi_startproc
|
|
28
28
|
.cfi_def_cfa esp, 4
|
|
29
29
|
ENDBR32
|
|
30
|
-
push %
|
|
30
|
+
push %ebp
|
|
31
31
|
.cfi_def_cfa esp, 8
|
|
32
|
-
movl %esp, %
|
|
33
|
-
.cfi_def_cfa
|
|
32
|
+
movl %esp, %ebp
|
|
33
|
+
.cfi_def_cfa ebp, 8
|
|
34
34
|
movl 16(%esp), %eax
|
|
35
35
|
movl %esp, 0(%eax)
|
|
36
36
|
movl 8(%esp), %eax
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
# The return value is passed back untouched.
|
|
49
49
|
.macro epilogue
|
|
50
50
|
call *%eax
|
|
51
|
-
movl %
|
|
52
|
-
pop %
|
|
51
|
+
movl %ebp, %esp
|
|
52
|
+
pop %ebp
|
|
53
53
|
.cfi_def_cfa esp, 4
|
|
54
54
|
ret
|
|
55
55
|
.cfi_endproc
|
|
@@ -168,10 +168,10 @@ CallSwitchStack:
|
|
|
168
168
|
.cfi_startproc
|
|
169
169
|
.cfi_def_cfa esp, 4
|
|
170
170
|
ENDBR32
|
|
171
|
-
push %
|
|
171
|
+
push %ebp
|
|
172
172
|
.cfi_def_cfa esp, 8
|
|
173
|
-
movl %esp, %
|
|
174
|
-
.cfi_def_cfa
|
|
173
|
+
movl %esp, %ebp
|
|
174
|
+
.cfi_def_cfa ebp, 8
|
|
175
175
|
movl 28(%esp), %edx
|
|
176
176
|
movl 24(%esp), %ecx
|
|
177
177
|
movl %esp, %eax
|
|
@@ -180,16 +180,16 @@ CallSwitchStack:
|
|
|
180
180
|
movl %eax, 4(%ecx)
|
|
181
181
|
movl 20(%esp), %esp
|
|
182
182
|
subl $28, %esp
|
|
183
|
-
movl 8(%
|
|
183
|
+
movl 8(%ebp), %eax
|
|
184
184
|
movl %eax, 0(%esp)
|
|
185
|
-
movl 12(%
|
|
185
|
+
movl 12(%ebp), %eax
|
|
186
186
|
movl %eax, 4(%esp)
|
|
187
|
-
movl 16(%
|
|
187
|
+
movl 16(%ebp), %eax
|
|
188
188
|
movl %eax, 8(%esp)
|
|
189
189
|
call *%edx
|
|
190
|
-
mov %
|
|
190
|
+
mov %ebp, %esp
|
|
191
191
|
.cfi_def_cfa esp, 8
|
|
192
|
-
pop %
|
|
192
|
+
pop %ebp
|
|
193
193
|
.cfi_def_cfa esp, 4
|
|
194
194
|
ret
|
|
195
195
|
.cfi_endproc
|
|
@@ -29,8 +29,8 @@ public ForwardCallRD
|
|
|
29
29
|
; Save ESP in EBX (non-volatile), and use carefully assembled stack provided by caller.
|
|
30
30
|
prologue macro
|
|
31
31
|
endbr32
|
|
32
|
-
push
|
|
33
|
-
mov
|
|
32
|
+
push ebp
|
|
33
|
+
mov ebp, esp
|
|
34
34
|
mov eax, dword ptr [esp+16]
|
|
35
35
|
mov dword ptr [eax+0], esp
|
|
36
36
|
mov eax, dword ptr [esp+8]
|
|
@@ -48,8 +48,8 @@ endm
|
|
|
48
48
|
; The return value is passed back untouched.
|
|
49
49
|
epilogue macro
|
|
50
50
|
call eax
|
|
51
|
-
mov esp,
|
|
52
|
-
pop
|
|
51
|
+
mov esp, ebp
|
|
52
|
+
pop ebp
|
|
53
53
|
ret
|
|
54
54
|
endm
|
|
55
55
|
|
|
@@ -153,8 +153,8 @@ endm
|
|
|
153
153
|
; stack pointer, call Node.js/V8 and go back to ours.
|
|
154
154
|
CallSwitchStack proc
|
|
155
155
|
endbr32
|
|
156
|
-
push
|
|
157
|
-
mov
|
|
156
|
+
push ebp
|
|
157
|
+
mov ebp, esp
|
|
158
158
|
mov edx, dword ptr [esp+28]
|
|
159
159
|
mov ecx, dword ptr [esp+24]
|
|
160
160
|
mov eax, esp
|
|
@@ -163,15 +163,15 @@ CallSwitchStack proc
|
|
|
163
163
|
mov dword ptr [ecx+4], eax
|
|
164
164
|
mov esp, dword ptr [esp+20]
|
|
165
165
|
sub esp, 28
|
|
166
|
-
mov eax, dword ptr [
|
|
166
|
+
mov eax, dword ptr [ebp+8]
|
|
167
167
|
mov dword ptr [esp+0], eax
|
|
168
|
-
mov eax, dword ptr [
|
|
168
|
+
mov eax, dword ptr [ebp+12]
|
|
169
169
|
mov dword ptr [esp+4], eax
|
|
170
|
-
mov eax, dword ptr [
|
|
170
|
+
mov eax, dword ptr [ebp+16]
|
|
171
171
|
mov dword ptr [esp+8], eax
|
|
172
172
|
call edx
|
|
173
|
-
mov esp,
|
|
174
|
-
pop
|
|
173
|
+
mov esp, ebp
|
|
174
|
+
pop ebp
|
|
175
175
|
ret
|
|
176
176
|
CallSwitchStack endp
|
|
177
177
|
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -33,6 +33,9 @@
|
|
|
33
33
|
#include <dlfcn.h>
|
|
34
34
|
#include <unistd.h>
|
|
35
35
|
#include <sys/mman.h>
|
|
36
|
+
#ifndef MAP_STACK
|
|
37
|
+
#define MAP_STACK 0
|
|
38
|
+
#endif
|
|
36
39
|
#endif
|
|
37
40
|
|
|
38
41
|
#include <napi.h>
|
|
@@ -1019,60 +1022,39 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
|
|
|
1019
1022
|
InstanceMemory *mem = new InstanceMemory();
|
|
1020
1023
|
RG_DEFER_N(mem_guard) { delete mem; };
|
|
1021
1024
|
|
|
1022
|
-
|
|
1023
|
-
{
|
|
1024
|
-
struct FiberContext {
|
|
1025
|
-
InstanceMemory *mem;
|
|
1026
|
-
void *self;
|
|
1027
|
-
bool was_fiber;
|
|
1028
|
-
};
|
|
1025
|
+
stack_size = AlignLen(stack_size, Kibibytes(64));
|
|
1029
1026
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1027
|
+
#if defined(_WIN32)
|
|
1028
|
+
static const int PageSize = ([]() {
|
|
1029
|
+
SYSTEM_INFO info = {};
|
|
1032
1030
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (!ctx.self) {
|
|
1036
|
-
LogError("Failed to make initial fiber: %1", GetWin32ErrorString());
|
|
1037
|
-
return nullptr;
|
|
1038
|
-
}
|
|
1039
|
-
RG_DEFER {
|
|
1040
|
-
if (!is_fiber) {
|
|
1041
|
-
ConvertFiberToThread();
|
|
1042
|
-
}
|
|
1043
|
-
};
|
|
1031
|
+
GetNativeSystemInfo(&info);
|
|
1032
|
+
RG_ASSERT(info.dwPageSize);
|
|
1044
1033
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
mem->fiber = CreateFiberEx(stack_size - 1, stack_size,
|
|
1048
|
-
FIBER_FLAG_FLOAT_SWITCH, [](void *udata) {
|
|
1049
|
-
FiberContext *ctx = (FiberContext *)udata;
|
|
1034
|
+
return (int)info.dwPageSize;
|
|
1035
|
+
})();
|
|
1050
1036
|
|
|
1051
|
-
|
|
1037
|
+
// Allocate stack memory
|
|
1038
|
+
{
|
|
1039
|
+
mem->stack.len = stack_size;
|
|
1040
|
+
mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len + 2 * PageSize, MEM_RESERVE, PAGE_NOACCESS);
|
|
1052
1041
|
|
|
1053
|
-
|
|
1054
|
-
ctx->mem->stack.len = (uint8_t *)teb->StackBase - ctx->mem->stack.ptr;
|
|
1042
|
+
RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
|
|
1055
1043
|
|
|
1056
|
-
|
|
1057
|
-
}, &ctx);
|
|
1044
|
+
bool success = true;
|
|
1058
1045
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
}
|
|
1046
|
+
success &= !!VirtualAlloc(mem->stack.ptr + 0 * PageSize, PageSize, MEM_COMMIT, PAGE_NOACCESS);
|
|
1047
|
+
success &= !!VirtualAlloc(mem->stack.ptr + 1 * PageSize, PageSize, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD);
|
|
1048
|
+
success &= !!VirtualAlloc(mem->stack.ptr + 2 * PageSize, mem->stack.len, MEM_COMMIT, PAGE_READWRITE);
|
|
1063
1049
|
|
|
1064
|
-
|
|
1050
|
+
RG_CRITICAL(success, "Cannot commit stack memory: %1", GetWin32ErrorString());
|
|
1065
1051
|
}
|
|
1066
|
-
|
|
1067
|
-
RG_ASSERT(mem->stack.ptr);
|
|
1068
|
-
#elif defined(__APPLE__)
|
|
1069
|
-
mem->stack.len = stack_size;
|
|
1070
|
-
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
1071
1052
|
#else
|
|
1072
1053
|
mem->stack.len = stack_size;
|
|
1073
1054
|
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
|
|
1074
|
-
|
|
1055
|
+
|
|
1075
1056
|
RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
|
|
1057
|
+
#endif
|
|
1076
1058
|
|
|
1077
1059
|
#ifdef __OpenBSD__
|
|
1078
1060
|
// Make sure the SP points inside the MAP_STACK area, or (void) functions may crash on OpenBSD i386
|
|
@@ -1741,8 +1723,8 @@ void FunctionInfo::Unref() const
|
|
|
1741
1723
|
InstanceMemory::~InstanceMemory()
|
|
1742
1724
|
{
|
|
1743
1725
|
#ifdef _WIN32
|
|
1744
|
-
if (
|
|
1745
|
-
|
|
1726
|
+
if (stack.ptr) {
|
|
1727
|
+
VirtualFree(stack.ptr, 0, MEM_RELEASE);
|
|
1746
1728
|
}
|
|
1747
1729
|
if (heap.ptr) {
|
|
1748
1730
|
VirtualFree(heap.ptr, 0, MEM_RELEASE);
|
|
@@ -1773,16 +1755,11 @@ static InstanceData *CreateInstance(Napi::Env env)
|
|
|
1773
1755
|
}
|
|
1774
1756
|
napi_unref_threadsafe_function(env, instance->broker);
|
|
1775
1757
|
|
|
1776
|
-
#
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
instance->main_stack_max = *(void **)((uint8_t *)teb + 0x08); // StackBase
|
|
1780
|
-
instance->main_stack_min = *(void **)((uint8_t *)teb + 0x1478); // DeallocationStack
|
|
1781
|
-
#elif defined(_WIN32) && (defined(__i386__) || defined(_M_IX86))
|
|
1782
|
-
void *teb = (void *)__readfsdword(0x18);
|
|
1758
|
+
#ifdef _WIN32
|
|
1759
|
+
TEB *teb = GetTEB();
|
|
1783
1760
|
|
|
1784
|
-
instance->main_stack_max =
|
|
1785
|
-
instance->main_stack_min =
|
|
1761
|
+
instance->main_stack_max = teb->StackBase;
|
|
1762
|
+
instance->main_stack_min = teb->DeallocationStack;
|
|
1786
1763
|
#endif
|
|
1787
1764
|
|
|
1788
1765
|
err_guard.Disable();
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -116,3 +116,10 @@ if(MSVC)
|
|
|
116
116
|
target_compile_options(misc PRIVATE /wd4116)
|
|
117
117
|
target_link_options(misc PRIVATE "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/misc.def")
|
|
118
118
|
endif()
|
|
119
|
+
|
|
120
|
+
# ---- Win32 ----
|
|
121
|
+
|
|
122
|
+
if(WIN32)
|
|
123
|
+
add_library(win32 SHARED win32.c)
|
|
124
|
+
set_target_properties(win32 PROPERTIES PREFIX "")
|
|
125
|
+
endif()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// This program is free software: you can redistribute it and/or modify
|
|
2
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
3
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
4
|
+
// (at your option) any later version.
|
|
5
|
+
//
|
|
6
|
+
// This program is distributed in the hope that it will be useful,
|
|
7
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
8
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
9
|
+
// GNU Affero General Public License for more details.
|
|
10
|
+
//
|
|
11
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
12
|
+
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
|
+
|
|
14
|
+
#include <stdlib.h>
|
|
15
|
+
#include <stdio.h>
|
|
16
|
+
#include <inttypes.h>
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include <stdarg.h>
|
|
19
|
+
|
|
20
|
+
#define NOMINMAX
|
|
21
|
+
#define WIN32_LEAN_AND_MEAN
|
|
22
|
+
#include <windows.h>
|
|
23
|
+
|
|
24
|
+
#define EXPORT __declspec(dllexport)
|
|
25
|
+
|
|
26
|
+
EXPORT int DivideBySafe(int a, int b)
|
|
27
|
+
{
|
|
28
|
+
__try {
|
|
29
|
+
return a / b;
|
|
30
|
+
} __except (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) {
|
|
31
|
+
return -42;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
EXPORT int CallThrough(int (*func)(void))
|
|
36
|
+
{
|
|
37
|
+
int ret = func();
|
|
38
|
+
return ret;
|
|
39
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// This program is free software: you can redistribute it and/or modify
|
|
4
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
5
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
// (at your option) any later version.
|
|
7
|
+
//
|
|
8
|
+
// This program is distributed in the hope that it will be useful,
|
|
9
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
// GNU Affero General Public License for more details.
|
|
12
|
+
//
|
|
13
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
14
|
+
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
15
|
+
|
|
16
|
+
const koffi = require('./build/koffi.node');
|
|
17
|
+
const assert = require('assert');
|
|
18
|
+
const util = require('util');
|
|
19
|
+
|
|
20
|
+
const CallThroughFunc = koffi.callback('int CallThroughFunc()');
|
|
21
|
+
|
|
22
|
+
main();
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
try {
|
|
26
|
+
await test();
|
|
27
|
+
console.log('Success!');
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error(err);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function test() {
|
|
35
|
+
let lib_filename = __dirname + '/build/win32.dll';
|
|
36
|
+
let lib = koffi.load(lib_filename);
|
|
37
|
+
|
|
38
|
+
const DivideBySafe = lib.func('int DivideBySafe(int a, int b)');
|
|
39
|
+
const CallThrough = lib.func('int CallThrough(CallThroughFunc *func)');
|
|
40
|
+
|
|
41
|
+
// Sync SEH support
|
|
42
|
+
assert.equal(DivideBySafe(12, 3), 4);
|
|
43
|
+
assert.equal(DivideBySafe(84, 0), -42);
|
|
44
|
+
|
|
45
|
+
// Async SEH support
|
|
46
|
+
{
|
|
47
|
+
let results = await Promise.all([
|
|
48
|
+
util.promisify(DivideBySafe.async)(90, -9),
|
|
49
|
+
util.promisify(DivideBySafe.async)(227, 0)
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
assert.equal(results[0], -10);
|
|
53
|
+
assert.equal(results[1], -42);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Test SEH inside callback
|
|
57
|
+
assert.equal(CallThrough(() => DivideBySafe(16, 2)), 8);
|
|
58
|
+
assert.equal(CallThrough(() => DivideBySafe(16 * 2, 0)), -42);
|
|
59
|
+
|
|
60
|
+
// Test SEH inside callback running async
|
|
61
|
+
{
|
|
62
|
+
let results = await Promise.all([
|
|
63
|
+
util.promisify(CallThrough.async)(() => DivideBySafe(75, -5)),
|
|
64
|
+
util.promisify(CallThrough.async)(() => DivideBySafe(7, 5 - 5))
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
assert.equal(results[0], -15);
|
|
68
|
+
assert.equal(results[1], -42);
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/koffi/tools/qemu.js
CHANGED
|
@@ -571,7 +571,7 @@ async function upload(snapshot_dir, func) {
|
|
|
571
571
|
}
|
|
572
572
|
|
|
573
573
|
let status = copied ? chalk.bold.green('[ok]') : chalk.bold.red('[error]');
|
|
574
|
-
log(machine, '
|
|
574
|
+
log(machine, 'Upload', status);
|
|
575
575
|
}));
|
|
576
576
|
|
|
577
577
|
return success;
|
|
@@ -605,7 +605,7 @@ async function test() {
|
|
|
605
605
|
let ret = await exec_remote(machine, cmd, cwd);
|
|
606
606
|
let time = Number((process.hrtime.bigint() - start) / 1000000n);
|
|
607
607
|
|
|
608
|
-
if (ret.code
|
|
608
|
+
if (ret.code === 0) {
|
|
609
609
|
log(machine, `${suite} > ${name}`, chalk.bold.green(`[${(time / 1000).toFixed(2)}s]`));
|
|
610
610
|
} else {
|
|
611
611
|
log(machine, `${suite} > ${name}`, chalk.bold.red('[error]'));
|
|
@@ -654,8 +654,6 @@ async function stop(all = true) {
|
|
|
654
654
|
|
|
655
655
|
console.log('>> Sending shutdown commands...');
|
|
656
656
|
await Promise.all(machines.map(async machine => {
|
|
657
|
-
if (ignore.has(machine))
|
|
658
|
-
return;
|
|
659
657
|
if (machine.qemu == null)
|
|
660
658
|
return;
|
|
661
659
|
if (!machine.started && !all)
|
|
@@ -916,19 +914,32 @@ function log(machine, action, status) {
|
|
|
916
914
|
}
|
|
917
915
|
|
|
918
916
|
async function exec_remote(machine, cmd, cwd = null) {
|
|
917
|
+
if (typeof cmd == 'string') {
|
|
918
|
+
cmd = {
|
|
919
|
+
command: cmd,
|
|
920
|
+
repeat: 1
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
919
924
|
try {
|
|
925
|
+
let ret = { code: 0 };
|
|
926
|
+
|
|
920
927
|
if (machine.platform == 'win32') {
|
|
928
|
+
let cmd_line = cmd.command;
|
|
929
|
+
|
|
921
930
|
if (cwd != null) {
|
|
922
931
|
cwd = cwd.replaceAll('/', '\\');
|
|
923
|
-
|
|
932
|
+
cmd_line = `cd "${cwd}" && ${cmd_line}`;
|
|
924
933
|
}
|
|
925
934
|
|
|
926
|
-
let
|
|
927
|
-
|
|
935
|
+
for (let i = 0; ret.code === 0 && i < cmd.repeat; i++)
|
|
936
|
+
ret = await machine.ssh.execCommand(cmd_line);
|
|
928
937
|
} else {
|
|
929
|
-
let
|
|
930
|
-
|
|
938
|
+
for (let i = 0; ret.code === 0 && i < cmd.repeat; i++)
|
|
939
|
+
ret = await machine.ssh.execCommand(cmd.command, { cwd: cwd });
|
|
931
940
|
}
|
|
941
|
+
|
|
942
|
+
return ret;
|
|
932
943
|
} catch (err) {
|
|
933
944
|
console.log(err);
|
|
934
945
|
return err;
|
|
@@ -230,7 +230,11 @@
|
|
|
230
230
|
"Test Async": "C:\\Node32\\node32.cmd node test/async.js",
|
|
231
231
|
"Test Callbacks": "C:\\Node32\\node32.cmd node test/callbacks.js",
|
|
232
232
|
"Test Raylib": "seatsh C:\\Node32\\node32.cmd node test/raylib.js",
|
|
233
|
-
"Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js"
|
|
233
|
+
"Test SQLite": "C:\\Node32\\node32.cmd node test/sqlite.js",
|
|
234
|
+
"Test Win32": {
|
|
235
|
+
"command": "C:\\Node32\\node32.cmd node test/win32.js",
|
|
236
|
+
"repeat": 8
|
|
237
|
+
}
|
|
234
238
|
}
|
|
235
239
|
},
|
|
236
240
|
|
|
@@ -244,7 +248,11 @@
|
|
|
244
248
|
"Test Async": "C:\\Node64\\node64.cmd node test/async.js",
|
|
245
249
|
"Test Callbacks": "C:\\Node64\\node64.cmd node test/callbacks.js",
|
|
246
250
|
"Test Raylib": "seatsh C:\\Node64\\node64.cmd node test/raylib.js",
|
|
247
|
-
"Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js"
|
|
251
|
+
"Test SQLite": "C:\\Node64\\node64.cmd node test/sqlite.js",
|
|
252
|
+
"Test Win32": {
|
|
253
|
+
"command": "C:\\Node64\\node64.cmd node test/win32.js",
|
|
254
|
+
"repeat": 8
|
|
255
|
+
}
|
|
248
256
|
}
|
|
249
257
|
}
|
|
250
258
|
}
|
package/doc/memory.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Memory usage
|
|
2
|
-
|
|
3
|
-
## How it works
|
|
4
|
-
|
|
5
|
-
For synchronous/normal calls, Koffi uses two preallocated memory blocks:
|
|
6
|
-
|
|
7
|
-
- One to construct the C stack and assign registers, subsequently used by the platform-specific assembly code (1 MiB by default)
|
|
8
|
-
- One to allocate strings and big objects/structs (2 MiB by default)
|
|
9
|
-
|
|
10
|
-
Unless very big strings or objects (at least more than one page of memory) are used, Koffi does not directly allocate any extra memory during calls or callbacks. However, please note that the JS engine (V8) might.
|
|
11
|
-
|
|
12
|
-
The size (in bytes) of these preallocated blocks can be changed. Use `koffi.config()` to get an object with the settings, and `koffi.config(obj)` to apply new settings.
|
|
13
|
-
|
|
14
|
-
```js
|
|
15
|
-
let config = koffi.config();
|
|
16
|
-
console.log(config);
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
The same is true for asynchronous calls. When an asynchronous call is made, Koffi will allocate new blocks unless there is an unused (resident) set of blocks still available. Once the asynchronous call is finished, these blocks are freed if there are more than `resident_async_pools` sets of blocks left around.
|
|
20
|
-
|
|
21
|
-
There cannot be more than `max_async_calls` running at the same time.
|
|
22
|
-
|
|
23
|
-
## Default settings
|
|
24
|
-
|
|
25
|
-
Setting | Default | Description
|
|
26
|
-
-------------------- | ------- | -----------------------------------------------
|
|
27
|
-
sync_stack_size | 1 MiB | Stack size for synchronous calls
|
|
28
|
-
sync_heap_size | 2 MiB | Heap size for synchronous calls
|
|
29
|
-
async_stack_size | 256 kiB | Stack size for asynchronous calls
|
|
30
|
-
async_heap_size | 512 kiB | Heap size for asynchronous calls
|
|
31
|
-
resident_async_pools | 2 | Number of resident pools for asynchronous calls
|
|
32
|
-
max_async_calls | 64 | Maximum number of ongoing asynchronous calls
|
|
33
|
-
max_type_size | 64 MiB | Maximum size of Koffi types (for arrays and structs)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|