diff --git a/stdlib/public/runtime/ThreadLocalStorage.h b/stdlib/public/runtime/ThreadLocalStorage.h index c4b63fac0aa36..1db5f70b64818 100644 --- a/stdlib/public/runtime/ThreadLocalStorage.h +++ b/stdlib/public/runtime/ThreadLocalStorage.h @@ -90,7 +90,10 @@ static_assert(std::is_same<__swift_thread_key_t, DWORD>::value, # define SWIFT_THREAD_KEY_CREATE _stdlib_thread_key_create # define SWIFT_THREAD_GETSPECIFIC FlsGetValue # define SWIFT_THREAD_SETSPECIFIC(key, value) (FlsSetValue(key, value) == FALSE) - +# elif defined(__wasi__) +# define SWIFT_THREAD_KEY_CREATE _stdlib_thread_key_create +# define SWIFT_THREAD_GETSPECIFIC _stdlib_thread_getspecific +# define SWIFT_THREAD_SETSPECIFIC _stdlib_thread_setspecific # else // Otherwise use the pthread API. # include diff --git a/stdlib/public/stubs/ThreadLocalStorage.cpp b/stdlib/public/stubs/ThreadLocalStorage.cpp index 50168f955bc6c..2f4d74d61d26a 100644 --- a/stdlib/public/stubs/ThreadLocalStorage.cpp +++ b/stdlib/public/stubs/ThreadLocalStorage.cpp @@ -54,6 +54,44 @@ _stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key, #endif +#if defined(__wasi__) +// WebAssembly doesn't have threading standardized yet, so TLS is emulated +// here, see https://bugs.swift.org/browse/SR-12774. +#include +using __swift_thread_key_destructor = void (*)(void *); + +struct _stdlib_tls_element_t { + const void *value; + __swift_thread_key_destructor destructor; +}; + +using _stdlib_tls_map_t = std::map<__swift_thread_key_t, _stdlib_tls_element_t>; +static void *_stdlib_tls_map; + +static inline int _stdlib_thread_key_create(__swift_thread_key_t *key, + __swift_thread_key_destructor destructor) { + if (!_stdlib_tls_map) + _stdlib_tls_map = new _stdlib_tls_map_t(); + auto *map = (_stdlib_tls_map_t *)_stdlib_tls_map; + *key = map->size(); + _stdlib_tls_element_t element = { nullptr, destructor }; + map->insert(std::make_pair(*key, element)); + return 0; +} + +static inline void *_stdlib_thread_getspecific(__swift_thread_key_t key) { + auto *map = (_stdlib_tls_map_t *)_stdlib_tls_map; + return const_cast(map->operator[](key).value); +} + +static inline int _stdlib_thread_setspecific(__swift_thread_key_t key, const void *value) { + auto *map = (_stdlib_tls_map_t *)_stdlib_tls_map; + map->operator[](key).value = value; + return 0; +} + +#endif + #if SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC SWIFT_RUNTIME_STDLIB_INTERNAL