emnapi 0.41.0 → 0.42.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 CHANGED
@@ -97,12 +97,14 @@ if(IS_WASM32)
97
97
  ${MALLOC_PUBLIC_SOURCES}
98
98
  "${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/emmalloc/emmalloc.c"
99
99
  )
100
+ target_compile_options(${EMMALLOC_TARGET_NAME} PRIVATE "-fno-strict-aliasing")
100
101
  target_compile_definitions(${EMMALLOC_TARGET_NAME} PRIVATE "PAGESIZE=65536")
101
102
 
102
103
  add_library(${EMMALLOC_MT_TARGET_NAME} STATIC
103
104
  ${MALLOC_PUBLIC_SOURCES}
104
105
  "${CMAKE_CURRENT_SOURCE_DIR}/src/malloc/emmalloc/emmalloc.c"
105
106
  )
107
+ target_compile_options(${EMMALLOC_MT_TARGET_NAME} PRIVATE "-fno-strict-aliasing")
106
108
  target_compile_options(${EMMALLOC_MT_TARGET_NAME} PUBLIC "-matomics" "-mbulk-memory")
107
109
  target_compile_definitions(${EMMALLOC_MT_TARGET_NAME} PRIVATE "PAGESIZE=65536" "__EMSCRIPTEN_SHARED_MEMORY__=1")
108
110
  endif()
package/README.md CHANGED
@@ -109,7 +109,7 @@ Create `hello.c`.
109
109
  ```c
110
110
  #include <node_api.h>
111
111
 
112
- #define NAPI_CALL(env, the_call) \
112
+ #define NODE_API_CALL(env, the_call) \
113
113
  do { \
114
114
  if ((the_call) != napi_ok) { \
115
115
  const napi_extended_error_info *error_info; \
@@ -130,15 +130,15 @@ Create `hello.c`.
130
130
  static napi_value js_hello(napi_env env, napi_callback_info info) {
131
131
  napi_value world;
132
132
  const char* str = "world";
133
- NAPI_CALL(env, napi_create_string_utf8(env, str, NAPI_AUTO_LENGTH, &world));
133
+ NODE_API_CALL(env, napi_create_string_utf8(env, str, NAPI_AUTO_LENGTH, &world));
134
134
  return world;
135
135
  }
136
136
 
137
137
  NAPI_MODULE_INIT() {
138
138
  napi_value hello;
139
- NAPI_CALL(env, napi_create_function(env, "hello", NAPI_AUTO_LENGTH,
139
+ NODE_API_CALL(env, napi_create_function(env, "hello", NAPI_AUTO_LENGTH,
140
140
  js_hello, NULL, &hello));
141
- NAPI_CALL(env, napi_set_named_property(env, exports, "hello", hello));
141
+ NODE_API_CALL(env, napi_set_named_property(env, exports, "hello", hello));
142
142
  return exports;
143
143
  }
144
144
  ```
@@ -802,11 +802,11 @@ function napi_create_function(env, utf8name, length, cb, data, result) {
802
802
  return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
803
803
  }
804
804
  }
805
- function napi_get_cb_info(env, _cbinfo, argc, argv, this_arg, data) {
805
+ function napi_get_cb_info(env, cbinfo, argc, argv, this_arg, data) {
806
806
  if (!env)
807
807
  return 1 /* napi_status.napi_invalid_arg */;
808
808
  var envObject = emnapiCtx.envStore.get(env);
809
- var cbinfoValue = emnapiCtx.cbinfoStack.current;
809
+ var cbinfoValue = emnapiCtx.cbinfoStack.get(cbinfo);
810
810
  {{{ from64('argc') }}};
811
811
  {{{ from64('argv') }}};
812
812
  if (argv) {
@@ -949,14 +949,14 @@ function napi_new_instance(env, constructor, argc, argv, result) {
949
949
  return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
950
950
  }
951
951
  }
952
- function napi_get_new_target(env, _cbinfo, result) {
952
+ function napi_get_new_target(env, cbinfo, result) {
953
953
  if (!env)
954
954
  return 1 /* napi_status.napi_invalid_arg */;
955
955
  var envObject = emnapiCtx.envStore.get(env);
956
956
  if (!result)
957
957
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
958
958
  {{{ from64('result') }}};
959
- var cbinfoValue = emnapiCtx.cbinfoStack.current;
959
+ var cbinfoValue = emnapiCtx.cbinfoStack.get(cbinfo);
960
960
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
961
961
  var value = cbinfoValue.getNewTarget(envObject);
962
962
  {{{ makeSetValue('result', 0, 'value', '*') }}};
@@ -976,11 +976,11 @@ function emnapiCreateFunction(envObject, utf8name, length, cb, data) {
976
976
  var f;
977
977
  var makeFunction = function () { return function () {
978
978
  'use strict';
979
- emnapiCtx.cbinfoStack.push(this, data, arguments, f);
979
+ var cbinfo = emnapiCtx.cbinfoStack.push(this, data, arguments, f);
980
980
  var scope = emnapiCtx.openScope(envObject);
981
981
  try {
982
982
  return envObject.callIntoModule(function (envObject) {
983
- var napiValue = {{{ makeDynCall('ppp', 'cb') }}}(envObject.id, 0);
983
+ var napiValue = {{{ makeDynCall('ppp', 'cb') }}}(envObject.id, cbinfo);
984
984
  return (!napiValue) ? undefined : emnapiCtx.handleStore.get(napiValue).value;
985
985
  });
986
986
  }
@@ -1548,13 +1548,13 @@ function __emnapi_node_emit_async_destroy(async_id, trigger_async_id) {
1548
1548
  })
1549
1549
 
1550
1550
  {{{ from64('result') }}}
1551
- {{{ makeSetValue('result', 0, 'nativeCallbackScopePointer', 'i64') }}}
1551
+ $_TODO_makeSetValue('result', 0, 'nativeCallbackScopePointer', 'i64')
1552
1552
  }
1553
1553
 
1554
1554
  function __emnapi_node_close_callback_scope (scope: Pointer<int64_t>): void {
1555
1555
  if (!emnapiNodeBinding || !scope) return
1556
1556
  {{{ from64('scope') }}}
1557
- const nativeCallbackScopePointer = {{{ makeGetValue('scope', 0, 'i64') }}}
1557
+ const nativeCallbackScopePointer = $_TODO_makeGetValue('scope', 0, 'i64')
1558
1558
  emnapiNodeBinding.node.closeCallbackScope(BigInt(nativeCallbackScopePointer))
1559
1559
  } */
1560
1560
  function __emnapi_node_make_callback(env, async_resource, cb, argv, size, async_id, trigger_async_id, result) {
@@ -1685,7 +1685,7 @@ function napi_make_callback(env, async_context, recv, func, argc, argv, result)
1685
1685
  v = envObject.ensureHandleId(ret.value);
1686
1686
  {{{ makeSetValue('result', 0, 'v', '*') }}};
1687
1687
  }
1688
- return envObject.clearLastError();
1688
+ return envObject.getReturnStatus();
1689
1689
  }
1690
1690
  catch (err) {
1691
1691
  envObject.tryCatch.setError(err);
@@ -2171,7 +2171,7 @@ function napi_set_named_property(env, object, cname, value) {
2171
2171
  }
2172
2172
  {{{ from64('cname') }}};
2173
2173
  emnapiCtx.handleStore.get(object).value[emnapiString.UTF8ToString(cname, -1)] = emnapiCtx.handleStore.get(value).value;
2174
- return 0 /* napi_status.napi_ok */;
2174
+ return envObject.getReturnStatus();
2175
2175
  }
2176
2176
  catch (err) {
2177
2177
  envObject.tryCatch.setError(err);
@@ -2462,7 +2462,7 @@ function napi_define_properties(env, object, property_count, properties) {
2462
2462
  }
2463
2463
  emnapiDefineProperty(envObject, maybeObject, propertyName, method, getter, setter, value, attributes, data);
2464
2464
  }
2465
- return 0 /* napi_status.napi_ok */;
2465
+ return envObject.getReturnStatus();
2466
2466
  }
2467
2467
  catch (err) {
2468
2468
  envObject.tryCatch.setError(err);
@@ -4141,9 +4141,8 @@ function napi_detach_arraybuffer(env, arraybuffer) {
4141
4141
  var messageChannel = new MessageChannel_1();
4142
4142
  messageChannel.port1.postMessage(value, [value]);
4143
4143
  }
4144
- catch (err) {
4145
- envObject.tryCatch.setError(err);
4146
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
4144
+ catch (_) {
4145
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
4147
4146
  }
4148
4147
  return envObject.clearLastError();
4149
4148
  }
@@ -4205,8 +4204,8 @@ function _napi_get_version(env, result) {
4205
4204
  if (!result)
4206
4205
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
4207
4206
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
4208
- var NAPI_VERSION = 9 /* Version.NAPI_VERSION */;
4209
- {{{ makeSetValue('result', 0, 'NAPI_VERSION', 'u32') }}};
4207
+ var NODE_API_SUPPORTED_VERSION_MAX = 9 /* Version.NODE_API_SUPPORTED_VERSION_MAX */;
4208
+ {{{ makeSetValue('result', 0, 'NODE_API_SUPPORTED_VERSION_MAX', 'u32') }}};
4210
4209
  return envObject.clearLastError();
4211
4210
  }
4212
4211
  emnapiImplement('napi_get_version', 'ipp', _napi_get_version, []);
@@ -4685,8 +4684,7 @@ function napi_get_value_bigint_int64(env, value, result, lossless) {
4685
4684
  return 1 /* napi_status.napi_invalid_arg */;
4686
4685
  var envObject = emnapiCtx.envStore.get(env);
4687
4686
  if (!emnapiCtx.feature.supportBigInt) {
4688
- envObject.tryCatch.setError(emnapiCtx.createNotSupportBigIntError('napi_get_value_bigint_int64', 'This API is unavailable'));
4689
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
4687
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
4690
4688
  }
4691
4689
  if (!value)
4692
4690
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
@@ -4724,8 +4722,7 @@ function napi_get_value_bigint_uint64(env, value, result, lossless) {
4724
4722
  return 1 /* napi_status.napi_invalid_arg */;
4725
4723
  var envObject = emnapiCtx.envStore.get(env);
4726
4724
  if (!emnapiCtx.feature.supportBigInt) {
4727
- envObject.tryCatch.setError(emnapiCtx.createNotSupportBigIntError('napi_get_value_bigint_uint64', 'This API is unavailable'));
4728
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
4725
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
4729
4726
  }
4730
4727
  if (!value)
4731
4728
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
@@ -4760,8 +4757,7 @@ function napi_get_value_bigint_words(env, value, sign_bit, word_count, words) {
4760
4757
  return 1 /* napi_status.napi_invalid_arg */;
4761
4758
  var envObject = emnapiCtx.envStore.get(env);
4762
4759
  if (!emnapiCtx.feature.supportBigInt) {
4763
- envObject.tryCatch.setError(emnapiCtx.createNotSupportBigIntError('napi_get_value_bigint_words', 'This API is unavailable'));
4764
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
4760
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
4765
4761
  }
4766
4762
  if (!value)
4767
4763
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
@@ -5130,8 +5126,7 @@ function napi_create_bigint_int64(env, low, high, result) {
5130
5126
  return 1 /* napi_status.napi_invalid_arg */;
5131
5127
  var envObject = emnapiCtx.envStore.get(env);
5132
5128
  if (!emnapiCtx.feature.supportBigInt) {
5133
- envObject.tryCatch.setError(emnapiCtx.createNotSupportBigIntError('napi_create_bigint_int64', 'This API is unavailable'));
5134
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
5129
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
5135
5130
  }
5136
5131
  var value;
5137
5132
  #if WASM_BIGINT
@@ -5157,8 +5152,7 @@ function napi_create_bigint_uint64(env, low, high, result) {
5157
5152
  return 1 /* napi_status.napi_invalid_arg */;
5158
5153
  var envObject = emnapiCtx.envStore.get(env);
5159
5154
  if (!emnapiCtx.feature.supportBigInt) {
5160
- envObject.tryCatch.setError(emnapiCtx.createNotSupportBigIntError('napi_create_bigint_uint64', 'This API is unavailable'));
5161
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
5155
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
5162
5156
  }
5163
5157
  var value;
5164
5158
  #if WASM_BIGINT
@@ -5193,7 +5187,7 @@ function napi_create_bigint_words(env, sign_bit, word_count, words, result) {
5193
5187
  envObject.clearLastError();
5194
5188
  try {
5195
5189
  if (!emnapiCtx.feature.supportBigInt) {
5196
- throw emnapiCtx.createNotSupportBigIntError('napi_create_bigint_words', 'This API is unavailable');
5190
+ return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
5197
5191
  }
5198
5192
  if (!result)
5199
5193
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
@@ -5217,7 +5211,7 @@ function napi_create_bigint_words(env, sign_bit, word_count, words, result) {
5217
5211
  {{{ from64('result') }}};
5218
5212
  v = emnapiCtx.addToCurrentScope(value).id;
5219
5213
  {{{ makeSetValue('result', 0, 'v', '*') }}};
5220
- return envObject.clearLastError();
5214
+ return envObject.getReturnStatus();
5221
5215
  }
5222
5216
  catch (err) {
5223
5217
  envObject.tryCatch.setError(err);
@@ -5675,8 +5669,7 @@ function napi_create_dataview(env, byte_length, arraybuffer, byte_offset, result
5675
5669
  if ((byte_length + byte_offset) > buffer.byteLength) {
5676
5670
  var err = new RangeError('byte_offset + byte_length should be less than or equal to the size in bytes of the array passed in');
5677
5671
  err.code = 'ERR_NAPI_INVALID_DATAVIEW_ARGS';
5678
- envObject.tryCatch.setError(err);
5679
- return envObject.setLastError(10 /* napi_status.napi_pending_exception */);
5672
+ throw err;
5680
5673
  }
5681
5674
  var dataview = new DataView(buffer, byte_offset, byte_length);
5682
5675
  if (buffer === wasmMemory.buffer) {
@@ -40,7 +40,7 @@ struct uv_loop_s; // Forward declaration.
40
40
 
41
41
  typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env,
42
42
  napi_value exports);
43
- typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)();
43
+ typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(void);
44
44
 
45
45
  // Used by deprecated registration method napi_module_register.
46
46
  typedef struct napi_module {
@@ -84,7 +84,7 @@ typedef struct napi_module {
84
84
 
85
85
  #define NAPI_MODULE_INIT() \
86
86
  EXTERN_C_START \
87
- NAPI_MODULE_EXPORT int32_t NODE_API_MODULE_GET_API_VERSION() { \
87
+ NAPI_MODULE_EXPORT int32_t NODE_API_MODULE_GET_API_VERSION(void) { \
88
88
  return NAPI_VERSION; \
89
89
  } \
90
90
  NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \
package/include/uv.h CHANGED
@@ -84,6 +84,23 @@ typedef void (*uv_thread_cb)(void* arg);
84
84
  UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
85
85
  UV_EXTERN int uv_thread_join(uv_thread_t *tid);
86
86
 
87
+ typedef enum {
88
+ UV_THREAD_NO_FLAGS = 0x00,
89
+ UV_THREAD_HAS_STACK_SIZE = 0x01
90
+ } uv_thread_create_flags;
91
+
92
+ struct uv_thread_options_s {
93
+ unsigned int flags;
94
+ size_t stack_size;
95
+ };
96
+
97
+ typedef struct uv_thread_options_s uv_thread_options_t;
98
+
99
+ UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
100
+ const uv_thread_options_t* params,
101
+ uv_thread_cb entry,
102
+ void* arg);
103
+
87
104
  typedef void (*uv_close_cb)(uv_handle_t* handle);
88
105
  typedef void (*uv_async_cb)(uv_async_t* handle);
89
106
 
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emnapi",
3
- "version": "0.41.0",
3
+ "version": "0.42.0",
4
4
  "description": "Node-API implementation for Emscripten",
5
5
  "main": "index.js",
6
6
  "peerDependencies": {
@@ -4619,14 +4619,14 @@ void* dlmalloc(size_t bytes) {
4619
4619
  ensure_initialization(); /* initialize in sys_alloc if not using locks */
4620
4620
  #endif
4621
4621
 
4622
+ if (!PREACTION(gm)) {
4622
4623
  #if __wasilibc_unmodified_upstream // Try to initialize the allocator.
4623
4624
  #else
4624
- if (!is_initialized(gm)) {
4625
- try_init_allocator();
4626
- }
4625
+ if (!is_initialized(gm)) {
4626
+ try_init_allocator();
4627
+ }
4627
4628
  #endif
4628
4629
 
4629
- if (!PREACTION(gm)) {
4630
4630
  void* mem;
4631
4631
  size_t nb;
4632
4632
  if (bytes <= MAX_SMALL_REQUEST) {
@@ -5241,7 +5241,7 @@ static void internal_inspect_all(mstate m,
5241
5241
 
5242
5242
  /* Symbol marking the end of data, bss and explicit stack, provided by wasm-ld. */
5243
5243
  extern char __heap_base;
5244
- extern char __heap_end __attribute__((__weak__));
5244
+ extern char __heap_end;
5245
5245
 
5246
5246
  /* Initialize the initial state of dlmalloc to be able to use free memory between __heap_base and initial. */
5247
5247
  static void try_init_allocator(void) {
@@ -5253,23 +5253,18 @@ static void try_init_allocator(void) {
5253
5253
 
5254
5254
  char *base = &__heap_base;
5255
5255
  // Try to use the linker pseudo-symbol `__heap_end` for the initial size of
5256
- // the heap, but if that's not defined due to LLVM being too old perhaps then
5257
- // round up `base` to the nearest `PAGESIZE`. The initial size of linear
5258
- // memory will be at least the heap base to this page boundary, and it's then
5259
- // assumed that the initial linear memory image was truncated at that point.
5260
- // While this reflects the default behavior of `wasm-ld` it is also possible
5261
- // for users to craft larger linear memories by passing options to extend
5262
- // beyond this threshold. In this situation the memory will not be used for
5263
- // dlmalloc.
5264
- //
5265
- // Note that `sbrk(0)`, or in dlmalloc-ese `CALL_MORECORE(0)`, is specifically
5266
- // not used here. That captures the current size of the heap but is only
5267
- // correct if the we're the first to try to grow the heap. If the heap has
5268
- // grown elsewhere, such as a different allocator in place, then this would
5269
- // incorrectly claim such memroy as our own.
5256
+ // the heap.
5270
5257
  char *end = &__heap_end;
5271
- if (end == NULL)
5272
- end = (char*) page_align((size_t) base);
5258
+ if (end < base) {
5259
+ // "end" can be NULL when 1. you are using an old wasm-ld which doesn't
5260
+ // provide `__heap_end` (< 15.0.7) and 2. something (other libraries
5261
+ // or maybe your app?) includes a weak reference to `__heap_end` and
5262
+ // 3. the weak reference is found by the linker before this strong
5263
+ // reference.
5264
+ //
5265
+ // Note: This is a linker bug: https://github.com/llvm/llvm-project/issues/60829
5266
+ __builtin_trap();
5267
+ }
5273
5268
  size_t initial_heap_size = end - base;
5274
5269
 
5275
5270
  /* Check that initial heap is long enough to serve a minimal allocation request. */
@@ -209,9 +209,10 @@ void uv__threadpool_cleanup(void) {
209
209
  nthreads = 0;
210
210
  }
211
211
 
212
- EMNAPI_EXTERN int _emnapi_async_work_pool_size();
212
+ EMNAPI_INTERNAL_EXTERN int _emnapi_async_work_pool_size();
213
213
 
214
214
  static void init_threads(void) {
215
+ uv_thread_options_t config;
215
216
  unsigned int i;
216
217
  #if !defined(EMNAPI_WORKER_POOL_SIZE) || !(EMNAPI_WORKER_POOL_SIZE > 0)
217
218
  const char* val;
@@ -262,11 +263,17 @@ static void init_threads(void) {
262
263
  abort();
263
264
  #endif
264
265
 
266
+ // config.flags = UV_THREAD_HAS_STACK_SIZE;
267
+ // config.stack_size = 8u << 20; /* 8 MB */
268
+
269
+ // use DEFAULT_PTHREAD_STACK_SIZE
270
+ config.flags = UV_THREAD_NO_FLAGS;
271
+
265
272
  for (i = 0; i < nthreads; i++)
266
273
  #ifndef __EMNAPI_WASI_THREADS__
267
- if (uv_thread_create(threads + i, (uv_thread_cb) worker, &sem))
274
+ if (uv_thread_create_ex(threads + i, &config, (uv_thread_cb) worker, &sem))
268
275
  #else
269
- if (uv_thread_create(threads + i, (uv_thread_cb) worker, NULL))
276
+ if (uv_thread_create_ex(threads + i, &config, (uv_thread_cb) worker, NULL))
270
277
  #endif
271
278
  abort();
272
279
 
@@ -15,6 +15,31 @@
15
15
  // } \
16
16
  // } while (0)
17
17
 
18
+ static size_t uv__min_stack_size(void) {
19
+ static const size_t min = 8192;
20
+
21
+ #ifdef PTHREAD_STACK_MIN /* Not defined on NetBSD. */
22
+ if (min < (size_t) PTHREAD_STACK_MIN)
23
+ return PTHREAD_STACK_MIN;
24
+ #endif /* PTHREAD_STACK_MIN */
25
+
26
+ return min;
27
+ }
28
+
29
+ static size_t uv__default_stack_size(void) {
30
+ #if !defined(__linux__)
31
+ return 0;
32
+ #elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
33
+ return 4 << 20; /* glibc default. */
34
+ #else
35
+ return 2 << 20; /* glibc default. */
36
+ #endif
37
+ }
38
+
39
+ size_t uv__thread_stack_size(void) {
40
+ return uv__default_stack_size();
41
+ }
42
+
18
43
  void uv_sem_post(sem_t* sem) {
19
44
  if (sem_post(sem))
20
45
  abort();
@@ -104,10 +129,15 @@ void uv_cond_destroy(uv_cond_t* cond) {
104
129
  }
105
130
 
106
131
  int uv_thread_create_ex(uv_thread_t* tid,
107
- void* params,
132
+ const uv_thread_options_t* params,
108
133
  void (*entry)(void *arg),
109
134
  void *arg) {
110
135
  int err;
136
+ pthread_attr_t* attr;
137
+ pthread_attr_t attr_storage;
138
+ size_t pagesize;
139
+ size_t stack_size;
140
+ size_t min_stack_size;
111
141
 
112
142
  /* Used to squelch a -Wcast-function-type warning. */
113
143
  union {
@@ -115,14 +145,43 @@ int uv_thread_create_ex(uv_thread_t* tid,
115
145
  void* (*out)(void*);
116
146
  } f;
117
147
 
148
+ stack_size =
149
+ params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
150
+
151
+ attr = NULL;
152
+ if (stack_size == 0) {
153
+ stack_size = uv__thread_stack_size();
154
+ } else {
155
+ pagesize = 65536;
156
+ stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
157
+ min_stack_size = uv__min_stack_size();
158
+ if (stack_size < min_stack_size)
159
+ stack_size = min_stack_size;
160
+ }
161
+
162
+ if (stack_size > 0) {
163
+ attr = &attr_storage;
164
+
165
+ if (pthread_attr_init(attr))
166
+ abort();
167
+
168
+ if (pthread_attr_setstacksize(attr, stack_size))
169
+ abort();
170
+ }
171
+
118
172
  f.in = entry;
119
- err = pthread_create(tid, NULL, f.out, arg);
173
+ err = pthread_create(tid, attr, f.out, arg);
174
+
175
+ if (attr != NULL)
176
+ pthread_attr_destroy(attr);
120
177
 
121
178
  return err;
122
179
  }
123
180
 
124
181
  int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
125
- return uv_thread_create_ex(tid, NULL, entry, arg);
182
+ uv_thread_options_t params;
183
+ params.flags = UV_THREAD_NO_FLAGS;
184
+ return uv_thread_create_ex(tid, &params, entry, arg);
126
185
  }
127
186
 
128
187
  int uv_thread_join(uv_thread_t *tid) {