emnapi 0.34.0 → 0.35.0
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/CMakeLists.txt +43 -1
- package/README.md +93 -19
- package/dist/library_napi.js +125 -108
- package/lib/wasm32/libdlmalloc-mt.a +0 -0
- package/lib/wasm32/libemmalloc-mt.a +0 -0
- package/lib/wasm32/libemnapi-basic-mt.a +0 -0
- package/lib/wasm32-emscripten/libemnapi-mt.a +0 -0
- package/lib/wasm32-wasi/libemnapi-basic-mt.a +0 -0
- package/package.json +1 -1
- package/src/thread/async_worker_create.c +76 -0
- package/src/thread/async_worker_init.S +33 -0
- package/src/uv/threadpool.c +9 -3
package/CMakeLists.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.13)
|
|
2
2
|
|
|
3
|
-
project(emnapi)
|
|
3
|
+
project(emnapi LANGUAGES C ASM)
|
|
4
4
|
|
|
5
5
|
option(EMNAPI_INSTALL_SRC "EMNAPI_INSTALL_SRC" OFF)
|
|
6
6
|
option(EMNAPI_FIND_NODE_ADDON_API "EMNAPI_FIND_NODE_ADDON_API" OFF)
|
|
@@ -50,10 +50,13 @@ else()
|
|
|
50
50
|
endif()
|
|
51
51
|
|
|
52
52
|
set(EMNAPI_BASIC_TARGET_NAME "emnapi-basic")
|
|
53
|
+
set(EMNAPI_BASIC_MT_TARGET_NAME "emnapi-basic-mt")
|
|
53
54
|
set(EMNAPI_TARGET_NAME "emnapi")
|
|
54
55
|
set(EMNAPI_MT_TARGET_NAME "emnapi-mt")
|
|
55
56
|
set(DLMALLOC_TARGET_NAME "dlmalloc")
|
|
57
|
+
set(DLMALLOC_MT_TARGET_NAME "dlmalloc-mt")
|
|
56
58
|
set(EMMALLOC_TARGET_NAME "emmalloc")
|
|
59
|
+
set(EMMALLOC_MT_TARGET_NAME "emmalloc-mt")
|
|
57
60
|
|
|
58
61
|
if(EMNAPI_FIND_NODE_ADDON_API)
|
|
59
62
|
execute_process(
|
|
@@ -82,11 +85,26 @@ if(IS_WASM32)
|
|
|
82
85
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/dlmalloc/dlmalloc.c"
|
|
83
86
|
)
|
|
84
87
|
target_compile_definitions(${DLMALLOC_TARGET_NAME} PRIVATE "PAGESIZE=65536")
|
|
88
|
+
|
|
89
|
+
add_library(${DLMALLOC_MT_TARGET_NAME} STATIC
|
|
90
|
+
${MALLOC_PUBLIC_SOURCES}
|
|
91
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/dlmalloc/dlmalloc.c"
|
|
92
|
+
)
|
|
93
|
+
target_compile_options(${DLMALLOC_MT_TARGET_NAME} PUBLIC "-matomics" "-mbulk-memory")
|
|
94
|
+
target_compile_definitions(${DLMALLOC_MT_TARGET_NAME} PRIVATE "PAGESIZE=65536" "USE_LOCKS=1")
|
|
95
|
+
|
|
85
96
|
add_library(${EMMALLOC_TARGET_NAME} STATIC
|
|
86
97
|
${MALLOC_PUBLIC_SOURCES}
|
|
87
98
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/emmalloc/emmalloc.c"
|
|
88
99
|
)
|
|
89
100
|
target_compile_definitions(${EMMALLOC_TARGET_NAME} PRIVATE "PAGESIZE=65536")
|
|
101
|
+
|
|
102
|
+
add_library(${EMMALLOC_MT_TARGET_NAME} STATIC
|
|
103
|
+
${MALLOC_PUBLIC_SOURCES}
|
|
104
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/emmalloc/emmalloc.c"
|
|
105
|
+
)
|
|
106
|
+
target_compile_options(${EMMALLOC_MT_TARGET_NAME} PUBLIC "-matomics" "-mbulk-memory")
|
|
107
|
+
target_compile_definitions(${EMMALLOC_MT_TARGET_NAME} PRIVATE "PAGESIZE=65536" "__EMSCRIPTEN_SHARED_MEMORY__=1")
|
|
90
108
|
endif()
|
|
91
109
|
|
|
92
110
|
add_library(${EMNAPI_TARGET_NAME} STATIC ${EMNAPI_SRC} ${UV_SRC})
|
|
@@ -101,6 +119,22 @@ if(IS_EMSCRIPTEN)
|
|
|
101
119
|
target_link_options(${EMNAPI_BASIC_TARGET_NAME} INTERFACE "--js-library=${EMNAPI_JS_LIB}")
|
|
102
120
|
endif()
|
|
103
121
|
|
|
122
|
+
if(IS_WASM32 OR (CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi") OR (CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi-threads"))
|
|
123
|
+
set(EMNAPI_BUILD_BASIC_MT ON)
|
|
124
|
+
else()
|
|
125
|
+
set(EMNAPI_BUILD_BASIC_MT OFF)
|
|
126
|
+
endif()
|
|
127
|
+
|
|
128
|
+
if(EMNAPI_BUILD_BASIC_MT)
|
|
129
|
+
add_library(${EMNAPI_BASIC_MT_TARGET_NAME} STATIC
|
|
130
|
+
${ENAPI_BASIC_SRC}
|
|
131
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/src/thread/async_worker_create.c"
|
|
132
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/src/thread/async_worker_init.S"
|
|
133
|
+
)
|
|
134
|
+
target_compile_options(${EMNAPI_BASIC_MT_TARGET_NAME} PUBLIC "-matomics" "-mbulk-memory")
|
|
135
|
+
target_include_directories(${EMNAPI_BASIC_MT_TARGET_NAME} PUBLIC ${EMNAPI_INCLUDE})
|
|
136
|
+
endif()
|
|
137
|
+
|
|
104
138
|
if(IS_EMSCRIPTEN OR (CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi-threads"))
|
|
105
139
|
set(EMNAPI_BUILD_MT ON)
|
|
106
140
|
else()
|
|
@@ -141,9 +175,14 @@ if(LIB_ARCH)
|
|
|
141
175
|
if(EMNAPI_BUILD_MT)
|
|
142
176
|
install(TARGETS ${EMNAPI_MT_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
143
177
|
endif()
|
|
178
|
+
if(EMNAPI_BUILD_BASIC_MT)
|
|
179
|
+
install(TARGETS ${EMNAPI_BASIC_MT_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
180
|
+
endif()
|
|
144
181
|
if(IS_WASM32)
|
|
145
182
|
install(TARGETS ${DLMALLOC_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
183
|
+
install(TARGETS ${DLMALLOC_MT_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
146
184
|
install(TARGETS ${EMMALLOC_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
185
|
+
install(TARGETS ${EMMALLOC_MT_TARGET_NAME} DESTINATION "lib/${LIB_ARCH}")
|
|
147
186
|
endif()
|
|
148
187
|
endif()
|
|
149
188
|
|
|
@@ -178,4 +217,7 @@ if(EMNAPI_INSTALL_SRC)
|
|
|
178
217
|
install(DIRECTORY
|
|
179
218
|
${CMAKE_CURRENT_SOURCE_DIR}/src/malloc
|
|
180
219
|
DESTINATION "src/${PROJECT_NAME}")
|
|
220
|
+
install(DIRECTORY
|
|
221
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/thread
|
|
222
|
+
DESTINATION "src/${PROJECT_NAME}")
|
|
181
223
|
endif()
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://github.com/toyobayashi/emnapi/actions/workflows/main.yml)
|
|
8
8
|
|
|
9
|
-
[Node-API](https://nodejs.org/docs/latest/api/n-api.html) implementation for [Emscripten](https://emscripten.org/index.html), [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) and clang with wasm support.
|
|
9
|
+
[Node-API](https://nodejs.org/docs/latest/api/n-api.html) implementation for [Emscripten](https://emscripten.org/index.html), [wasi-sdk](https://github.com/WebAssembly/wasi-sdk) and clang with wasm support. napi-rs support is comming soon.
|
|
10
10
|
|
|
11
11
|
This project aims to
|
|
12
12
|
|
|
@@ -25,16 +25,6 @@ See documentation for more details:
|
|
|
25
25
|
|
|
26
26
|
[How to build Node-API official examples](https://github.com/toyobayashi/node-addon-examples)
|
|
27
27
|
|
|
28
|
-
Emscripten is the first class support target. If your target is running addon on browser,
|
|
29
|
-
we strongly recommend you to use Emscripten instead of wasi-sdk. Async works and threadsafe
|
|
30
|
-
functions related APIs are only available on Emscripten or `wasm32-wasi-threads` target since
|
|
31
|
-
they are relying on pthread. Though today we have [WASI browser polyfill](https://github.com/toyobayashi/wasm-util),
|
|
32
|
-
`wasm32-wasi-threads` is in very early stage and WASI itself is not designed for browser.
|
|
33
|
-
There are some limitations on browser about wasi-libc's pthread implementation, for example
|
|
34
|
-
`pthread_mutex_lock` may call `__builtin_wasm_memory_atomic_wait32`(`memory.atomic.wait32`)
|
|
35
|
-
which is disallowed in browser JS main thread. While Emscripten's pthread implementation
|
|
36
|
-
has considered usage in browser.
|
|
37
|
-
|
|
38
28
|
## Prerequests
|
|
39
29
|
|
|
40
30
|
You will need to install:
|
|
@@ -275,6 +265,9 @@ declare namespace Module {
|
|
|
275
265
|
* napi_create_async_work and napi_create_threadsafe_function
|
|
276
266
|
*/
|
|
277
267
|
nodeBinding?: typeof import('@emnapi/node-binding')
|
|
268
|
+
|
|
269
|
+
/** See Multithread part */
|
|
270
|
+
asyncWorkPoolSize?: number
|
|
278
271
|
}
|
|
279
272
|
export function emnapiInit (options: EmnapiInitOptions): any
|
|
280
273
|
}
|
|
@@ -732,20 +725,60 @@ pub unsafe extern "C" fn napi_register_wasm_v1(env: napi_env, exports: napi_valu
|
|
|
732
725
|
|
|
733
726
|
### Multithread
|
|
734
727
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
728
|
+
Related API:
|
|
729
|
+
|
|
730
|
+
- [napi_*_async_work](https://nodejs.org/dist/latest/docs/api/n-api.html#napi_create_async_work)
|
|
731
|
+
- [napi_*_threadsafe_function](https://nodejs.org/dist/latest/docs/api/n-api.html#asynchronous-thread-safe-function-calls)
|
|
732
|
+
|
|
733
|
+
They are available in emnapi, but you need to know more details before you start to use them.
|
|
734
|
+
Now emnapi has 3 implementations of async work and 2 implementations of TSFN:
|
|
735
|
+
|
|
736
|
+
- Async work
|
|
737
|
+
- A. Libuv threadpool and pthread based implementation in C
|
|
738
|
+
- B. Single thread mock in JavaScript
|
|
739
|
+
- C. Web worker based implementation in C (stack allocation) and JavaScript
|
|
740
|
+
- TSFN
|
|
741
|
+
- D. Libuv and pthread based implementation in C
|
|
742
|
+
- E. Web worker based implementation in JavaScript
|
|
743
|
+
|
|
744
|
+
| | Library to Link | `wasm32-emscripten` | `wasm32` | `wasm32-wasi` | `wasm32-wasi-threads` |
|
|
745
|
+
|---|------------------------|---------------------|----------|---------------|-----------------------|
|
|
746
|
+
| A | libemnapi-mt.a | ✅ | ❌ | ❌ | ✅ |
|
|
747
|
+
| B | libemnapi-basic(-mt).a | ✅ | ✅ | ✅ | ✅ |
|
|
748
|
+
| C | libemnapi-basic-mt.a | ❌ | ✅ | ❌ | ✅ |
|
|
749
|
+
| D | libemnapi-mt.a | ✅ | ❌ | ❌ | ✅ |
|
|
750
|
+
| E | libemnapi-basic-mt.a | ✅ | ✅ | ✅ | ✅ |
|
|
738
751
|
|
|
739
|
-
|
|
752
|
+
There are some limitations on browser about wasi-libc's pthread implementation, for example
|
|
753
|
+
`pthread_mutex_lock` may call `__builtin_wasm_memory_atomic_wait32`(`memory.atomic.wait32`)
|
|
754
|
+
which is disallowed in browser JS main thread. While Emscripten's pthread implementation
|
|
755
|
+
has considered usage in browser. If you need to run your addon with multithreaded features on browser,
|
|
756
|
+
we recommend you use Emscripten A & D, or bare wasm32 C & E.
|
|
757
|
+
|
|
758
|
+
#### About Prebuilt Libraries
|
|
759
|
+
|
|
760
|
+
Prebuilt libraries can be found in the `lib` directory in `emnapi` npm package.
|
|
761
|
+
|
|
762
|
+
| Library | Description | `wasm32-emscripten` | `wasm32` | `wasm32-wasi` | `wasm32-wasi-threads` |
|
|
763
|
+
|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|----------|---------------|-----------------------------------------|
|
|
764
|
+
| libemnapi.a | no atomics feature.<br/><br/> no libuv port.<br/><br/> `napi_*_async_work` and `napi_*_threadsafe_function` always return `napi_generic_failure`. | ✅ | ✅ | ✅ | waiting wasi-sdk release thread support |
|
|
765
|
+
| libemnapi-mt.a | atomics feature enabled.<br/><br/> `napi_*_async_work` and `napi_*_threadsafe_function` are based on pthread and libuv port. | ✅ | ❌ | ❌ | waiting wasi-sdk release thread support |
|
|
766
|
+
| libemnapi-basic.a | no atomics feature.<br/><br/> no libuv port.<br/><br/> `napi_*_async_work` and `napi_*_threadsafe_function` are imported from JavaScript land. | ✅ | ✅ | ✅ | waiting wasi-sdk release thread support |
|
|
767
|
+
| libemnapi-basic-mt.a | atomics feature enabled.<br/><br/> no libuv port.<br/><br/> `napi_*_async_work` and `napi_*_threadsafe_function` are imported from JavaScript land.<br/><br/> include `emnapi_async_worker_create` and `emnapi_async_worker_init` for WebWorker based async work implementation. | ❌ | ✅ | ✅ | waiting wasi-sdk release thread support |
|
|
768
|
+
| libdlmalloc.a | no atomics feature, no thread safe garanteed. | ❌ | ✅ | ❌ | ❌ |
|
|
769
|
+
| libdlmalloc-mt.a | atomics feature enabled, thread safe. | ❌ | ✅ | ❌ | ❌ |
|
|
770
|
+
| libemmalloc.a | no atomics feature, no thread safe garanteed. | ❌ | ✅ | ❌ | ❌ |
|
|
771
|
+
| libemmalloc-mt.a | atomics feature enabled, thread safe. | ❌ | ✅ | ❌ | ❌ |
|
|
772
|
+
|
|
773
|
+
#### Usage
|
|
740
774
|
|
|
741
775
|
```cmake
|
|
742
776
|
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/node_modules/emnapi")
|
|
743
777
|
|
|
744
778
|
add_executable(hello hello.c)
|
|
745
779
|
|
|
746
|
-
target_link_libraries(hello emnapi-mt)
|
|
747
|
-
|
|
748
780
|
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
|
781
|
+
target_link_libraries(hello emnapi-mt)
|
|
749
782
|
target_compile_options(hello PRIVATE "-pthread")
|
|
750
783
|
target_link_options(hello PRIVATE
|
|
751
784
|
"-sALLOW_MEMORY_GROWTH=1"
|
|
@@ -758,6 +791,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
|
|
758
791
|
)
|
|
759
792
|
elseif(CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi-threads")
|
|
760
793
|
# Experimental
|
|
794
|
+
target_link_libraries(hello emnapi-mt)
|
|
761
795
|
set_target_properties(hello PROPERTIES SUFFIX ".wasm")
|
|
762
796
|
target_compile_options(hello PRIVATE "-fno-exceptions" "-pthread")
|
|
763
797
|
target_link_options(hello PRIVATE
|
|
@@ -771,6 +805,19 @@ elseif(CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-wasi-threads")
|
|
|
771
805
|
"-Wl,--import-undefined"
|
|
772
806
|
"-Wl,--export-table"
|
|
773
807
|
)
|
|
808
|
+
elseif((CMAKE_C_COMPILER_TARGET STREQUAL "wasm32") OR (CMAKE_C_COMPILER_TARGET STREQUAL "wasm32-unknown-unknown"))
|
|
809
|
+
target_link_libraries(hello emnapi-basic-mt)
|
|
810
|
+
set_target_properties(hello PROPERTIES SUFFIX ".wasm")
|
|
811
|
+
target_compile_options(hello PRIVATE "-fno-exceptions" "-matomics" "-mbulk-memory")
|
|
812
|
+
target_link_options(hello PRIVATE
|
|
813
|
+
"-nostdlib"
|
|
814
|
+
"-Wl,--no-entry"
|
|
815
|
+
"-Wl,--export=napi_register_wasm_v1"
|
|
816
|
+
"-Wl,--export=emnapi_async_worker_create"
|
|
817
|
+
"-Wl,--export=emnapi_async_worker_init"
|
|
818
|
+
"-Wl,--import-memory,--shared-memory,--max-memory=2147483648,--import-undefined"
|
|
819
|
+
"-Wl,--export-dynamic,--export=malloc,--export=free,--export-table"
|
|
820
|
+
)
|
|
774
821
|
endif()
|
|
775
822
|
```
|
|
776
823
|
|
|
@@ -784,6 +831,11 @@ cmake -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk-pthread.cmake \
|
|
|
784
831
|
-DCMAKE_BUILD_TYPE=Release \
|
|
785
832
|
-G Ninja -H. -Bbuild
|
|
786
833
|
|
|
834
|
+
cmake -DCMAKE_TOOLCHAIN_FILE=node_modules/emnapi/cmake/wasm32.cmake \
|
|
835
|
+
-DWASI_SDK_PREFIX=$WASI_SDK_PATH \
|
|
836
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
837
|
+
-G Ninja -H. -Bbuild
|
|
838
|
+
|
|
787
839
|
cmake --build build
|
|
788
840
|
```
|
|
789
841
|
|
|
@@ -793,6 +845,15 @@ And additional work is required during instantiating wasm compiled with non-emsc
|
|
|
793
845
|
// emnapi main thread (could be in a Worker)
|
|
794
846
|
instantiateNapiModule(input, {
|
|
795
847
|
context: getDefaultContext(),
|
|
848
|
+
/**
|
|
849
|
+
* emscripten
|
|
850
|
+
* 0: no effect
|
|
851
|
+
* > 0: the same effect to UV_THREADPOOL_SIZE
|
|
852
|
+
* non-emscripten
|
|
853
|
+
* 0: single thread mock
|
|
854
|
+
* > 0 schedule async work in web worker
|
|
855
|
+
*/
|
|
856
|
+
asyncWorkPoolSize: 4, // 0: single thread mock, > 0: schedule async work in web worker
|
|
796
857
|
wasi: new WASI(/* ... */),
|
|
797
858
|
// reuseWorker: true,
|
|
798
859
|
onCreateWorker () {
|
|
@@ -890,17 +951,30 @@ instantiateNapiModule(input, {
|
|
|
890
951
|
|
|
891
952
|
### `-DEMNAPI_WORKER_POOL_SIZE=4`
|
|
892
953
|
|
|
893
|
-
This is [`UV_THREADPOOL_SIZE`](http://docs.libuv.org/en/v1.x/threadpool.html?highlight=UV_THREADPOOL_SIZE) equivalent at compile time, if not predefined, emnapi will read `UV_THREADPOOL_SIZE` from Emscripten [environment variable](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-environment-variables) at runtime
|
|
954
|
+
This is [`UV_THREADPOOL_SIZE`](http://docs.libuv.org/en/v1.x/threadpool.html?highlight=UV_THREADPOOL_SIZE) equivalent at compile time, if not predefined, emnapi will read `asyncWorkPoolSize` option or `UV_THREADPOOL_SIZE` from Emscripten [environment variable](https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#interacting-with-code-environment-variables) at runtime:
|
|
894
955
|
|
|
895
956
|
```js
|
|
957
|
+
Module.init({
|
|
958
|
+
// ...
|
|
959
|
+
asyncWorkPoolSize: 2
|
|
960
|
+
})
|
|
961
|
+
|
|
962
|
+
// if asyncWorkPoolSize is not specified
|
|
896
963
|
Module.preRun = Module.preRun || [];
|
|
897
964
|
Module.preRun.push(function () {
|
|
898
965
|
if (typeof ENV !== 'undefined') {
|
|
899
966
|
ENV.UV_THREADPOOL_SIZE = '2';
|
|
900
967
|
}
|
|
901
968
|
});
|
|
969
|
+
```
|
|
902
970
|
|
|
971
|
+
```js
|
|
903
972
|
// wasi
|
|
973
|
+
instantiateNapiModule({
|
|
974
|
+
// ...
|
|
975
|
+
asyncWorkPoolSize: 2
|
|
976
|
+
})
|
|
977
|
+
// if asyncWorkPoolSize is not specified
|
|
904
978
|
new WASI({
|
|
905
979
|
env: {
|
|
906
980
|
UV_THREADPOOL_SIZE: '2'
|
|
@@ -908,7 +982,7 @@ new WASI({
|
|
|
908
982
|
})
|
|
909
983
|
```
|
|
910
984
|
|
|
911
|
-
It represent max of `EMNAPI_WORKER_POOL_SIZE` async work (`napi_queue_async_work`) can be executed in parallel. Default is not defined
|
|
985
|
+
It represent max of `EMNAPI_WORKER_POOL_SIZE` async work (`napi_queue_async_work`) can be executed in parallel. Default is not defined.
|
|
912
986
|
|
|
913
987
|
You can set both `PTHREAD_POOL_SIZE` and `EMNAPI_WORKER_POOL_SIZE` to `number of CPU cores` in general.
|
|
914
988
|
If you use another library function which may create `N` child threads in async work,
|
package/dist/library_napi.js
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
{{{ ((DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.indexOf("$emnapiInit") === -1 ? DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push("$emnapiInit") : undefined), "") }}}
|
|
2
2
|
{{{ ((EXPORTED_RUNTIME_METHODS.indexOf("emnapiInit") === -1 ? EXPORTED_RUNTIME_METHODS.push("emnapiInit") : undefined), "") }}}
|
|
3
|
-
|
|
4
|
-
function emnapiCreateIdGenerator() {
|
|
5
|
-
var obj = {
|
|
6
|
-
nextId: 1,
|
|
7
|
-
list: [],
|
|
8
|
-
generate: function () {
|
|
9
|
-
var id;
|
|
10
|
-
if (obj.list.length) {
|
|
11
|
-
id = obj.list.shift();
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
id = obj.nextId;
|
|
15
|
-
obj.nextId++;
|
|
16
|
-
}
|
|
17
|
-
return id;
|
|
18
|
-
},
|
|
19
|
-
reuse: function (id) {
|
|
20
|
-
obj.list.push(id);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
return obj;
|
|
24
|
-
}
|
|
25
|
-
var emnapiAsyncWork = {
|
|
3
|
+
var emnapiAWST = {
|
|
26
4
|
idGen: {},
|
|
27
5
|
values: [undefined],
|
|
28
6
|
queued: new Set(),
|
|
29
7
|
pending: [],
|
|
30
8
|
init: function () {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
9
|
+
var idGen = {
|
|
10
|
+
nextId: 1,
|
|
11
|
+
list: [],
|
|
12
|
+
generate: function () {
|
|
13
|
+
var id;
|
|
14
|
+
if (idGen.list.length) {
|
|
15
|
+
id = idGen.list.shift();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
id = idGen.nextId;
|
|
19
|
+
idGen.nextId++;
|
|
20
|
+
}
|
|
21
|
+
return id;
|
|
22
|
+
},
|
|
23
|
+
reuse: function (id) {
|
|
24
|
+
idGen.list.push(id);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
emnapiAWST.idGen = idGen;
|
|
28
|
+
emnapiAWST.values = [undefined];
|
|
29
|
+
emnapiAWST.queued = new Set();
|
|
30
|
+
emnapiAWST.pending = [];
|
|
35
31
|
},
|
|
36
32
|
create: function (env, resource, resourceName, execute, complete, data) {
|
|
37
33
|
var asyncId = 0;
|
|
@@ -41,12 +37,11 @@ var emnapiAsyncWork = {
|
|
|
41
37
|
asyncId = asyncContext.asyncId;
|
|
42
38
|
triggerAsyncId = asyncContext.triggerAsyncId;
|
|
43
39
|
}
|
|
44
|
-
var id =
|
|
45
|
-
|
|
40
|
+
var id = emnapiAWST.idGen.generate();
|
|
41
|
+
emnapiAWST.values[id] = {
|
|
46
42
|
env: env,
|
|
47
43
|
id: id,
|
|
48
44
|
resource: resource,
|
|
49
|
-
resourceName: resourceName,
|
|
50
45
|
asyncId: asyncId,
|
|
51
46
|
triggerAsyncId: triggerAsyncId,
|
|
52
47
|
status: 0,
|
|
@@ -62,6 +57,8 @@ var emnapiAsyncWork = {
|
|
|
62
57
|
var env = work.env;
|
|
63
58
|
var data = work.data;
|
|
64
59
|
var callback = function () {
|
|
60
|
+
if (!complete)
|
|
61
|
+
return;
|
|
65
62
|
var envObject = emnapiCtx.envStore.get(env);
|
|
66
63
|
var scope = emnapiCtx.openScope(envObject);
|
|
67
64
|
try {
|
|
@@ -84,16 +81,16 @@ var emnapiAsyncWork = {
|
|
|
84
81
|
}
|
|
85
82
|
},
|
|
86
83
|
queue: function (id) {
|
|
87
|
-
var work =
|
|
84
|
+
var work = emnapiAWST.values[id];
|
|
88
85
|
if (!work)
|
|
89
86
|
return;
|
|
90
87
|
if (work.status === 0) {
|
|
91
88
|
work.status = 1;
|
|
92
|
-
if (
|
|
93
|
-
|
|
89
|
+
if (emnapiAWST.queued.size >= (Math.abs(emnapiAsyncWorkPoolSize) || 4)) {
|
|
90
|
+
emnapiAWST.pending.push(id);
|
|
94
91
|
return;
|
|
95
92
|
}
|
|
96
|
-
|
|
93
|
+
emnapiAWST.queued.add(id);
|
|
97
94
|
var env_1 = work.env;
|
|
98
95
|
var data_1 = work.data;
|
|
99
96
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -101,25 +98,29 @@ var emnapiAsyncWork = {
|
|
|
101
98
|
work.status = 2;
|
|
102
99
|
emnapiCtx.feature.setImmediate(function () {
|
|
103
100
|
{{{ makeDynCall('vpp', 'execute') }}}(env_1, data_1);
|
|
104
|
-
|
|
101
|
+
emnapiAWST.queued.delete(id);
|
|
105
102
|
work.status = 3;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
emnapiCtx.feature.setImmediate(function () {
|
|
104
|
+
emnapiAWST.callComplete(work, 0 /* napi_status.napi_ok */);
|
|
105
|
+
});
|
|
106
|
+
if (emnapiAWST.pending.length > 0) {
|
|
107
|
+
var nextWorkId = emnapiAWST.pending.shift();
|
|
108
|
+
emnapiAWST.values[nextWorkId].status = 0;
|
|
109
|
+
emnapiAWST.queue(nextWorkId);
|
|
111
110
|
}
|
|
112
111
|
});
|
|
113
112
|
}
|
|
114
113
|
},
|
|
115
114
|
cancel: function (id) {
|
|
116
|
-
var index =
|
|
115
|
+
var index = emnapiAWST.pending.indexOf(id);
|
|
117
116
|
if (index !== -1) {
|
|
118
|
-
var
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
var work_1 = emnapiAWST.values[id];
|
|
118
|
+
if (work_1 && (work_1.status === 1)) {
|
|
119
|
+
work_1.status = 4;
|
|
120
|
+
emnapiAWST.pending.splice(index, 1);
|
|
121
|
+
emnapiCtx.feature.setImmediate(function () {
|
|
122
|
+
emnapiAWST.callComplete(work_1, 11 /* napi_status.napi_cancelled */);
|
|
123
|
+
});
|
|
123
124
|
return 0 /* napi_status.napi_ok */;
|
|
124
125
|
}
|
|
125
126
|
else {
|
|
@@ -129,7 +130,7 @@ var emnapiAsyncWork = {
|
|
|
129
130
|
return 9 /* napi_status.napi_generic_failure */;
|
|
130
131
|
},
|
|
131
132
|
remove: function (id) {
|
|
132
|
-
var work =
|
|
133
|
+
var work = emnapiAWST.values[id];
|
|
133
134
|
if (!work)
|
|
134
135
|
return;
|
|
135
136
|
if (emnapiNodeBinding) {
|
|
@@ -138,68 +139,11 @@ var emnapiAsyncWork = {
|
|
|
138
139
|
triggerAsyncId: work.triggerAsyncId
|
|
139
140
|
});
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
emnapiAWST.values[id] = undefined;
|
|
143
|
+
emnapiAWST.idGen.reuse(id);
|
|
143
144
|
}
|
|
144
145
|
};
|
|
145
|
-
|
|
146
|
-
if (env == 0)
|
|
147
|
-
return 1 /* napi_status.napi_invalid_arg */;
|
|
148
|
-
var envObject = emnapiCtx.envStore.get(env);
|
|
149
|
-
if (execute == 0)
|
|
150
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
151
|
-
if (result == 0)
|
|
152
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
153
|
-
var resourceObject;
|
|
154
|
-
if (resource) {
|
|
155
|
-
resourceObject = Object(emnapiCtx.handleStore.get(resource).value);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
resourceObject = {};
|
|
159
|
-
}
|
|
160
|
-
if (resource_name == 0)
|
|
161
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
162
|
-
var resourceName = String(emnapiCtx.handleStore.get(resource_name).value);
|
|
163
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
164
|
-
var id = emnapiAsyncWork.create(env, resourceObject, resourceName, execute, complete, data);
|
|
165
|
-
{{{ makeSetValue('result', 0, 'id', '*') }}};
|
|
166
|
-
return envObject.clearLastError();
|
|
167
|
-
}
|
|
168
|
-
function _napi_delete_async_work(env, work) {
|
|
169
|
-
if (env == 0)
|
|
170
|
-
return 1 /* napi_status.napi_invalid_arg */;
|
|
171
|
-
var envObject = emnapiCtx.envStore.get(env);
|
|
172
|
-
if (work == 0)
|
|
173
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
174
|
-
emnapiAsyncWork.remove(work);
|
|
175
|
-
return envObject.clearLastError();
|
|
176
|
-
}
|
|
177
|
-
function _napi_queue_async_work(env, work) {
|
|
178
|
-
if (env == 0)
|
|
179
|
-
return 1 /* napi_status.napi_invalid_arg */;
|
|
180
|
-
var envObject = emnapiCtx.envStore.get(env);
|
|
181
|
-
if (work == 0)
|
|
182
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
183
|
-
emnapiAsyncWork.queue(work);
|
|
184
|
-
return envObject.clearLastError();
|
|
185
|
-
}
|
|
186
|
-
function _napi_cancel_async_work(env, work) {
|
|
187
|
-
if (env == 0)
|
|
188
|
-
return 1 /* napi_status.napi_invalid_arg */;
|
|
189
|
-
var envObject = emnapiCtx.envStore.get(env);
|
|
190
|
-
if (work == 0)
|
|
191
|
-
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
192
|
-
var status = emnapiAsyncWork.cancel(work);
|
|
193
|
-
if (status === 0 /* napi_status.napi_ok */)
|
|
194
|
-
return envObject.clearLastError();
|
|
195
|
-
return envObject.setLastError(status);
|
|
196
|
-
}
|
|
197
|
-
emnapiImplementHelper('$emnapiCreateIdGenerator', undefined, emnapiCreateIdGenerator, []);
|
|
198
|
-
emnapiDefineVar('$emnapiAsyncWork', emnapiAsyncWork, ['$emnapiCreateIdGenerator'], 'emnapiAsyncWork.init();');
|
|
199
|
-
emnapiImplement('napi_create_async_work', 'ippppppp', _napi_create_async_work, ['$emnapiAsyncWork']);
|
|
200
|
-
emnapiImplement('napi_delete_async_work', 'ipp', _napi_delete_async_work, ['$emnapiAsyncWork']);
|
|
201
|
-
emnapiImplement('napi_queue_async_work', 'ipp', _napi_queue_async_work, ['$emnapiAsyncWork']);
|
|
202
|
-
emnapiImplement('napi_cancel_async_work', 'ipp', _napi_cancel_async_work, ['$emnapiAsyncWork']);
|
|
146
|
+
emnapiDefineVar('$emnapiAWST', emnapiAWST, ['$emnapiAsyncWorkPoolSize'], 'emnapiAWST.init();');
|
|
203
147
|
function _emnapi_create_memory_view(env, typedarray_type, external_data, byte_length, finalize_cb, finalize_hint, result
|
|
204
148
|
// @ts-expect-error
|
|
205
149
|
) {
|
|
@@ -5468,6 +5412,62 @@ emnapiImplement('napi_get_boolean', 'ipip', napi_get_boolean);
|
|
|
5468
5412
|
emnapiImplement('napi_get_global', 'ipp', napi_get_global);
|
|
5469
5413
|
emnapiImplement('napi_get_null', 'ipp', napi_get_null);
|
|
5470
5414
|
emnapiImplement('napi_get_undefined', 'ipp', napi_get_undefined);
|
|
5415
|
+
function _napi_create_async_work(env, resource, resource_name, execute, complete, data, result) {
|
|
5416
|
+
if (env == 0)
|
|
5417
|
+
return 1 /* napi_status.napi_invalid_arg */;
|
|
5418
|
+
var envObject = emnapiCtx.envStore.get(env);
|
|
5419
|
+
if (execute == 0)
|
|
5420
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5421
|
+
if (result == 0)
|
|
5422
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5423
|
+
var resourceObject;
|
|
5424
|
+
if (resource) {
|
|
5425
|
+
resourceObject = Object(emnapiCtx.handleStore.get(resource).value);
|
|
5426
|
+
}
|
|
5427
|
+
else {
|
|
5428
|
+
resourceObject = {};
|
|
5429
|
+
}
|
|
5430
|
+
if (resource_name == 0)
|
|
5431
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5432
|
+
var resourceName = String(emnapiCtx.handleStore.get(resource_name).value);
|
|
5433
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5434
|
+
var id = emnapiAWST.create(env, resourceObject, resourceName, execute, complete, data);
|
|
5435
|
+
{{{ makeSetValue('result', 0, 'id', '*') }}};
|
|
5436
|
+
return envObject.clearLastError();
|
|
5437
|
+
}
|
|
5438
|
+
function _napi_delete_async_work(env, work) {
|
|
5439
|
+
if (env == 0)
|
|
5440
|
+
return 1 /* napi_status.napi_invalid_arg */;
|
|
5441
|
+
var envObject = emnapiCtx.envStore.get(env);
|
|
5442
|
+
if (work == 0)
|
|
5443
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5444
|
+
emnapiAWST.remove(work);
|
|
5445
|
+
return envObject.clearLastError();
|
|
5446
|
+
}
|
|
5447
|
+
function _napi_queue_async_work(env, work) {
|
|
5448
|
+
if (env == 0)
|
|
5449
|
+
return 1 /* napi_status.napi_invalid_arg */;
|
|
5450
|
+
var envObject = emnapiCtx.envStore.get(env);
|
|
5451
|
+
if (work == 0)
|
|
5452
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5453
|
+
emnapiAWST.queue(work);
|
|
5454
|
+
return envObject.clearLastError();
|
|
5455
|
+
}
|
|
5456
|
+
function _napi_cancel_async_work(env, work) {
|
|
5457
|
+
if (env == 0)
|
|
5458
|
+
return 1 /* napi_status.napi_invalid_arg */;
|
|
5459
|
+
var envObject = emnapiCtx.envStore.get(env);
|
|
5460
|
+
if (work == 0)
|
|
5461
|
+
return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
|
|
5462
|
+
var status = emnapiAWST.cancel(work);
|
|
5463
|
+
if (status === 0 /* napi_status.napi_ok */)
|
|
5464
|
+
return envObject.clearLastError();
|
|
5465
|
+
return envObject.setLastError(status);
|
|
5466
|
+
}
|
|
5467
|
+
emnapiImplement('napi_create_async_work', 'ippppppp', _napi_create_async_work, ['$emnapiAWST']);
|
|
5468
|
+
emnapiImplement('napi_delete_async_work', 'ipp', _napi_delete_async_work, ['$emnapiAWST']);
|
|
5469
|
+
emnapiImplement('napi_queue_async_work', 'ipp', _napi_queue_async_work, ['$emnapiAWST']);
|
|
5470
|
+
emnapiImplement('napi_cancel_async_work', 'ipp', _napi_cancel_async_work, ['$emnapiAWST']);
|
|
5471
5471
|
mergeInto(LibraryManager.library, {
|
|
5472
5472
|
_emnapi_worker_unref__sig: 'vp',
|
|
5473
5473
|
_emnapi_worker_unref__deps: ['$PThread'],
|
|
@@ -5618,6 +5618,7 @@ emnapiDefineVar('$emnapiModule', {
|
|
|
5618
5618
|
loaded: false,
|
|
5619
5619
|
filename: ''
|
|
5620
5620
|
});
|
|
5621
|
+
emnapiDefineVar('$emnapiAsyncWorkPoolSize', 0);
|
|
5621
5622
|
function emnapiInit(options) {
|
|
5622
5623
|
if (emnapiModule.loaded)
|
|
5623
5624
|
return emnapiModule.exports;
|
|
@@ -5639,6 +5640,18 @@ function emnapiInit(options) {
|
|
|
5639
5640
|
}
|
|
5640
5641
|
emnapiNodeBinding = nodeBinding;
|
|
5641
5642
|
}
|
|
5643
|
+
if ('asyncWorkPoolSize' in options) {
|
|
5644
|
+
if (typeof options.asyncWorkPoolSize !== 'number') {
|
|
5645
|
+
throw new TypeError('options.asyncWorkPoolSize must be a integer');
|
|
5646
|
+
}
|
|
5647
|
+
emnapiAsyncWorkPoolSize = options.asyncWorkPoolSize >> 0;
|
|
5648
|
+
if (emnapiAsyncWorkPoolSize > 1024) {
|
|
5649
|
+
emnapiAsyncWorkPoolSize = 1024;
|
|
5650
|
+
}
|
|
5651
|
+
else if (emnapiAsyncWorkPoolSize < -1024) {
|
|
5652
|
+
emnapiAsyncWorkPoolSize = -1024;
|
|
5653
|
+
}
|
|
5654
|
+
}
|
|
5642
5655
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
5643
5656
|
var envObject = emnapiModule.envObject || (emnapiModule.envObject = emnapiCtx.createEnv(function (cb) { return {{{ makeDynCall('vppp', 'cb') }}}; }, function (cb) { return {{{ makeDynCall('vp', 'cb') }}}; }));
|
|
5644
5657
|
var scope = emnapiCtx.openScope(envObject);
|
|
@@ -5660,7 +5673,11 @@ function emnapiInit(options) {
|
|
|
5660
5673
|
delete emnapiModule.envObject;
|
|
5661
5674
|
return emnapiModule.exports;
|
|
5662
5675
|
}
|
|
5663
|
-
emnapiImplementHelper('$emnapiInit', undefined, emnapiInit, ['$emnapiModule', '$emnapiCtx', '$emnapiNodeBinding', 'napi_register_wasm_v1']);
|
|
5676
|
+
emnapiImplementHelper('$emnapiInit', undefined, emnapiInit, ['$emnapiModule', '$emnapiCtx', '$emnapiNodeBinding', '$emnapiAsyncWorkPoolSize', 'napi_register_wasm_v1']);
|
|
5677
|
+
function __emnapi_async_work_pool_size() {
|
|
5678
|
+
return Math.abs(emnapiAsyncWorkPoolSize);
|
|
5679
|
+
}
|
|
5680
|
+
emnapiImplementInternal('_emnapi_async_work_pool_size', 'i', __emnapi_async_work_pool_size, ['$emnapiAsyncWorkPoolSize']);
|
|
5664
5681
|
function __emnapi_get_filename(buf, len) {
|
|
5665
5682
|
if (!buf) {
|
|
5666
5683
|
return lengthBytesUTF8(emnapiModule.filename);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#include <stddef.h>
|
|
2
|
+
#include <stdint.h>
|
|
3
|
+
|
|
4
|
+
void* calloc(size_t n, size_t size);
|
|
5
|
+
|
|
6
|
+
extern unsigned char __heap_base;
|
|
7
|
+
extern unsigned char __data_end;
|
|
8
|
+
extern unsigned char __global_base;
|
|
9
|
+
extern __attribute__((__weak__)) unsigned char __stack_high;
|
|
10
|
+
extern __attribute__((__weak__)) unsigned char __stack_low;
|
|
11
|
+
|
|
12
|
+
#define ROUND_UP(x, ALIGNMENT) (((x)+ALIGNMENT-1)&-ALIGNMENT)
|
|
13
|
+
#define STACK_ALIGN 16
|
|
14
|
+
#define DEFAULT_STACK_MAX (8<<20)
|
|
15
|
+
|
|
16
|
+
struct worker_args {
|
|
17
|
+
void* stack_base;
|
|
18
|
+
void* tls_base;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
extern void __wasm_init_tls(void*);
|
|
22
|
+
|
|
23
|
+
void* __copy_tls(unsigned char *mem) {
|
|
24
|
+
size_t tls_align = __builtin_wasm_tls_align();
|
|
25
|
+
volatile void* tls_base = __builtin_wasm_tls_base();
|
|
26
|
+
mem += tls_align;
|
|
27
|
+
mem -= (uintptr_t)mem & (tls_align-1);
|
|
28
|
+
__wasm_init_tls(mem);
|
|
29
|
+
__asm__("local.get %0\n"
|
|
30
|
+
"global.set __tls_base\n"
|
|
31
|
+
:: "r"(tls_base));
|
|
32
|
+
return mem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
__attribute__((visibility("default")))
|
|
36
|
+
void* emnapi_async_worker_create() {
|
|
37
|
+
size_t args_size = sizeof(struct worker_args);
|
|
38
|
+
size_t size = args_size;
|
|
39
|
+
|
|
40
|
+
size_t tls_size = __builtin_wasm_tls_size();
|
|
41
|
+
|
|
42
|
+
size_t tls_block_size = 0;
|
|
43
|
+
if (tls_size) {
|
|
44
|
+
size_t tls_align = __builtin_wasm_tls_align();
|
|
45
|
+
tls_block_size = ROUND_UP(tls_size + tls_align - 1, tls_align);
|
|
46
|
+
size += tls_block_size;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
ptrdiff_t stack_size = 0;
|
|
50
|
+
if (&__stack_high) {
|
|
51
|
+
stack_size = &__stack_high - &__stack_low;
|
|
52
|
+
} else {
|
|
53
|
+
unsigned char *sp;
|
|
54
|
+
__asm__(
|
|
55
|
+
".globaltype __stack_pointer, i32\n"
|
|
56
|
+
"global.get __stack_pointer\n"
|
|
57
|
+
"local.set %0\n"
|
|
58
|
+
: "=r"(sp));
|
|
59
|
+
stack_size = sp > &__global_base ? &__heap_base - &__data_end : (ptrdiff_t)&__global_base;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
stack_size = ROUND_UP(stack_size, STACK_ALIGN);
|
|
63
|
+
stack_size = stack_size < DEFAULT_STACK_MAX ? stack_size : DEFAULT_STACK_MAX;
|
|
64
|
+
size += stack_size;
|
|
65
|
+
|
|
66
|
+
void* block = calloc(1, size);
|
|
67
|
+
if (!block) return 0;
|
|
68
|
+
|
|
69
|
+
void* tls_base = tls_size ? __copy_tls(block + args_size) : 0;
|
|
70
|
+
|
|
71
|
+
struct worker_args* args = (struct worker_args*)block;
|
|
72
|
+
|
|
73
|
+
args->stack_base = block + args_size + tls_block_size + stack_size;
|
|
74
|
+
args->tls_base = tls_base;
|
|
75
|
+
return block;
|
|
76
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#ifdef __wasm64__
|
|
2
|
+
#define PTR i64
|
|
3
|
+
#else
|
|
4
|
+
#define PTR i32
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
.text
|
|
8
|
+
|
|
9
|
+
.export_name emnapi_async_worker_init, emnapi_async_worker_init
|
|
10
|
+
|
|
11
|
+
.globaltype __stack_pointer, PTR
|
|
12
|
+
.globaltype __tls_base, PTR
|
|
13
|
+
|
|
14
|
+
.hidden emnapi_async_worker_init
|
|
15
|
+
.globl emnapi_async_worker_init
|
|
16
|
+
.type emnapi_async_worker_init,@function
|
|
17
|
+
|
|
18
|
+
emnapi_async_worker_init:
|
|
19
|
+
.functype emnapi_async_worker_init (PTR) -> ()
|
|
20
|
+
|
|
21
|
+
local.get 0
|
|
22
|
+
PTR.load 0
|
|
23
|
+
global.set __stack_pointer
|
|
24
|
+
|
|
25
|
+
local.get 0
|
|
26
|
+
#ifdef __wasm64__
|
|
27
|
+
PTR.load 8
|
|
28
|
+
#else
|
|
29
|
+
PTR.load 4
|
|
30
|
+
#endif
|
|
31
|
+
global.set __tls_base
|
|
32
|
+
|
|
33
|
+
end_function
|
package/src/uv/threadpool.c
CHANGED
|
@@ -209,6 +209,7 @@ static void post(QUEUE* q, enum uv__work_kind kind) {
|
|
|
209
209
|
// nthreads = 0;
|
|
210
210
|
// }
|
|
211
211
|
|
|
212
|
+
EMNAPI_EXTERN int _emnapi_async_work_pool_size();
|
|
212
213
|
|
|
213
214
|
static void init_threads(void) {
|
|
214
215
|
unsigned int i;
|
|
@@ -223,9 +224,14 @@ static void init_threads(void) {
|
|
|
223
224
|
nthreads = EMNAPI_WORKER_POOL_SIZE;
|
|
224
225
|
#else
|
|
225
226
|
nthreads = ARRAY_SIZE(default_threads);
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
nthreads =
|
|
227
|
+
int async_work_pool_size = _emnapi_async_work_pool_size();
|
|
228
|
+
if (async_work_pool_size > 0) {
|
|
229
|
+
nthreads = (unsigned int) async_work_pool_size;
|
|
230
|
+
} else {
|
|
231
|
+
val = getenv("UV_THREADPOOL_SIZE");
|
|
232
|
+
if (val != NULL)
|
|
233
|
+
nthreads = atoi(val);
|
|
234
|
+
}
|
|
229
235
|
#endif
|
|
230
236
|
if (nthreads == 0)
|
|
231
237
|
nthreads = 1;
|