-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
01b5fdd
commit f48e21a
Showing
9 changed files
with
324 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ | |
node_modules | ||
/dist | ||
/src/emnapi/**/*.js | ||
/test/**/*.wasm | ||
/test/**/*.wat |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ node_modules | |
.npmignore | ||
api-extractor.json | ||
tsconfig.json | ||
/test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** @public */ | ||
export enum ExecutionModel { | ||
Command = 'command', | ||
Reactor = 'reactor' | ||
} | ||
|
||
/** @public */ | ||
export function createInstanceProxy ( | ||
instance: WebAssembly.Instance, | ||
memory: WebAssembly.Memory | (() => WebAssembly.Memory), | ||
model: ExecutionModel = ExecutionModel.Reactor | ||
): WebAssembly.Instance { | ||
// https://github.com/nodejs/help/issues/4102 | ||
const originalExports = instance.exports | ||
const createHandler = function (target: WebAssembly.Exports): ProxyHandler<WebAssembly.Exports> { | ||
const handlers = [ | ||
'apply', | ||
'construct', | ||
'defineProperty', | ||
'deleteProperty', | ||
'get', | ||
'getOwnPropertyDescriptor', | ||
'getPrototypeOf', | ||
'has', | ||
'isExtensible', | ||
'ownKeys', | ||
'preventExtensions', | ||
'set', | ||
'setPrototypeOf' | ||
] | ||
const handler: ProxyHandler<WebAssembly.Exports> = {} | ||
for (let i = 0; i < handlers.length; i++) { | ||
const name = handlers[i] as keyof ProxyHandler<WebAssembly.Exports> | ||
handler[name] = function () { | ||
const args = Array.prototype.slice.call(arguments, 1) | ||
args.unshift(target) | ||
return (Reflect[name] as any).apply(Reflect, args) | ||
} | ||
} | ||
return handler | ||
} | ||
const handler = createHandler(originalExports) | ||
const _initialize = (): void => {} | ||
const _start = (): number => 0 | ||
handler.get = function (_target, p, receiver) { | ||
if (p === 'memory') { | ||
return typeof memory === 'function' ? memory() : memory | ||
} | ||
if (p === '_initialize') { | ||
return model === ExecutionModel.Reactor ? _initialize : undefined | ||
} | ||
if (p === '_start') { | ||
return model === ExecutionModel.Command ? _start : undefined | ||
} | ||
return Reflect.get(originalExports, p, receiver) | ||
} | ||
handler.has = function (_target, p) { | ||
if (p === 'memory') return true | ||
if (p === '_initialize') return model === ExecutionModel.Reactor | ||
if (p === '_start') return model === ExecutionModel.Command | ||
return Reflect.has(originalExports, p) | ||
} | ||
const exportsProxy = new Proxy(Object.create(null), handler) | ||
return new Proxy(instance, { | ||
get (target, p, receiver) { | ||
if (p === 'exports') { | ||
return exportsProxy | ||
} | ||
return Reflect.get(target, p, receiver) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,98 @@ | ||
// TODO | ||
const fs = require('node:fs') | ||
const { join } = require('node:path') | ||
const { spawnSync } = require('node:child_process') | ||
const { Worker } = require('node:worker_threads') | ||
const { WASI } = require('wasi') | ||
const { WASIThreads, ThreadManager, ExecutionModel } = require('..') | ||
|
||
function build (model = ExecutionModel.Reactor) { | ||
const bin = join(process.env.WASI_SDK_PATH, 'bin', 'clang') + (process.platform === 'win32' ? '.exe' : '') | ||
const args = [ | ||
'-o', join(__dirname, model === ExecutionModel.Command ? 'main.wasm' : 'lib.wasm'), | ||
'-mbulk-memory', | ||
'-matomics', | ||
`-mexec-model=${model}`, | ||
...(model === ExecutionModel.Command | ||
? [ | ||
'-D__WASI_COMMAND__=1' | ||
] | ||
: [ | ||
'-Wl,--no-entry' | ||
] | ||
), | ||
'--target=wasm32-wasi-threads', | ||
// '-O3', | ||
'-g', | ||
'-pthread', | ||
'-Wl,--import-memory', | ||
'-Wl,--shared-memory', | ||
'-Wl,--export-memory', | ||
'-Wl,--export-dynamic', | ||
'-Wl,--max-memory=2147483648', | ||
'-Wl,--export=malloc,--export=free', | ||
join(__dirname, 'main.c') | ||
] | ||
console.log(`> "${bin}" ${args.map(s => s.includes(' ') ? `"${s}"` : s).join(' ')}`) | ||
spawnSync(bin, args, { | ||
stdio: 'inherit', | ||
env: process.env | ||
}) | ||
} | ||
|
||
function run (model = ExecutionModel.Reactor) { | ||
const wasi = new WASI({ | ||
version: 'preview1', | ||
env: process.env | ||
}) | ||
const wasiThreads = new WASIThreads({ | ||
threadManager: new ThreadManager({ | ||
printErr: console.error.bind(console), | ||
onCreateWorker: ({ name }) => { | ||
return new Worker(join(__dirname, 'worker.js'), { | ||
name, | ||
workerData: { | ||
name, | ||
model | ||
}, | ||
env: process.env, | ||
execArgv: ['--experimental-wasi-unstable-preview1'] | ||
}) | ||
} | ||
}) | ||
}) | ||
const memory = new WebAssembly.Memory({ | ||
initial: 16777216 / 65536, | ||
maximum: 2147483648 / 65536, | ||
shared: true | ||
}) | ||
const file = join(__dirname, model === ExecutionModel.Command ? 'main.wasm' : 'lib.wasm') | ||
return WebAssembly.instantiate(fs.readFileSync(file), { | ||
env: { | ||
memory | ||
}, | ||
...wasi.getImportObject(), | ||
...wasiThreads.getImportObject() | ||
}).then(({ module, instance }) => { | ||
wasiThreads.setup(instance, module, memory) | ||
if (model === ExecutionModel.Command) { | ||
return wasi.start(instance) | ||
} else { | ||
wasi.initialize(instance) | ||
return instance.exports.fn() | ||
} | ||
}) | ||
} | ||
|
||
async function main () { | ||
build(ExecutionModel.Command) | ||
build(ExecutionModel.Reactor) | ||
console.log('-------- command --------') | ||
await run(ExecutionModel.Command) | ||
console.log('-------- reactor --------') | ||
await run(ExecutionModel.Reactor) | ||
} | ||
|
||
main().catch(err => { | ||
console.error(err) | ||
process.exit(1) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#include <pthread.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
void *print_message_function(void *ptr) { | ||
char *message; | ||
message = (char *)ptr; | ||
printf("%s \n", message); | ||
return NULL; | ||
} | ||
|
||
__attribute__((visibility("default"))) | ||
int fn() { | ||
pthread_t thread1, thread2; | ||
const char *message1 = "Thread 1"; | ||
const char *message2 = "Thread 2"; | ||
int iret1, iret2; | ||
|
||
iret1 = pthread_create(&thread1, NULL, print_message_function, | ||
(void *)message1); | ||
iret2 = pthread_create(&thread2, NULL, print_message_function, | ||
(void *)message2); | ||
|
||
pthread_join(thread1, NULL); | ||
pthread_join(thread2, NULL); | ||
|
||
printf("Thread 1 returns: %d\n", iret1); | ||
printf("Thread 2 returns: %d\n", iret2); | ||
return 0; | ||
} | ||
|
||
#ifdef __WASI_COMMAND__ | ||
int main() { | ||
return fn(); | ||
} | ||
#endif |
Oops, something went wrong.