@@ -18,6 +18,14 @@ static const char *THREAD_START_FUNCTION = "wasi_thread_start";
1818
1919static korp_mutex thread_id_lock ;
2020
21+ // Stack data structure to track available thread identifiers
22+ #define AVAIL_TIDS_INIT_SIZE CLUSTER_MAX_THREAD_NUM
23+ typedef struct {
24+ int32 * ids ;
25+ uint32 pos , size ;
26+ } AvailableThreadIds ;
27+ static AvailableThreadIds avail_tids ;
28+
2129typedef struct {
2230 /* app's entry function */
2331 wasm_function_inst_t start_func ;
@@ -30,16 +38,56 @@ typedef struct {
3038static int32
3139allocate_thread_id ()
3240{
33- static int32 thread_id = 0 ;
34-
35- int32 id ;
41+ int32 id = -1 ;
3642
3743 os_mutex_lock (& thread_id_lock );
38- id = thread_id ++ ;
44+ if (avail_tids .pos == 0 ) { // Resize stack and push new thread ids
45+ uint32 old_size = avail_tids .size ;
46+ uint32 new_size = avail_tids .size * 2 ;
47+ if (new_size / 2 != avail_tids .size ) {
48+ LOG_ERROR ("Overflow detected during new size calculation" );
49+ goto return_id ;
50+ }
51+
52+ size_t realloc_size = new_size * sizeof (int32 );
53+ if (realloc_size / sizeof (int32 ) != new_size ) {
54+ LOG_ERROR ("Overflow detected during realloc" );
55+ goto return_id ;
56+ }
57+ int32 * tmp =
58+ (int32 * )wasm_runtime_realloc (avail_tids .ids , realloc_size );
59+ if (tmp == NULL ) {
60+ LOG_ERROR ("Thread ID allocator realloc failed" );
61+ goto return_id ;
62+ }
63+
64+ avail_tids .size = new_size ;
65+ avail_tids .pos = old_size ;
66+ avail_tids .ids = tmp ;
67+ for (uint32 i = 0 ; i < old_size ; i ++ )
68+ avail_tids .ids [i ] = new_size - i ;
69+ }
70+
71+ // Pop available thread identifier from `avail_tids` stack
72+ id = avail_tids .ids [-- avail_tids .pos ];
73+
74+ return_id :
3975 os_mutex_unlock (& thread_id_lock );
4076 return id ;
4177}
4278
79+ void
80+ deallocate_thread_id (int32 thread_id )
81+ {
82+ os_mutex_lock (& thread_id_lock );
83+
84+ // Release thread identifier by pushing it into `avail_tids` stack
85+ bh_assert (avail_tids .pos < avail_tids .size );
86+ avail_tids .ids [avail_tids .pos ++ ] = thread_id ;
87+
88+ os_mutex_unlock (& thread_id_lock );
89+ }
90+
4391static void *
4492thread_start (void * arg )
4593{
@@ -57,6 +105,8 @@ thread_start(void *arg)
57105 wasm_cluster_spread_exception (exec_env );
58106 }
59107
108+ // Routine exit
109+ deallocate_thread_id (thread_arg -> thread_id );
60110 wasm_runtime_free (thread_arg );
61111 exec_env -> thread_arg = NULL ;
62112
@@ -101,23 +151,26 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
101151 if (!start_func ) {
102152 LOG_ERROR ("Failed to find thread start function %s" ,
103153 THREAD_START_FUNCTION );
104- goto thread_spawn_fail ;
154+ goto thread_preparation_fail ;
105155 }
106156
107157 if (!(thread_start_arg = wasm_runtime_malloc (sizeof (ThreadStartArg )))) {
108158 LOG_ERROR ("Runtime args allocation failed" );
109- goto thread_spawn_fail ;
159+ goto thread_preparation_fail ;
110160 }
111161
112162 thread_start_arg -> thread_id = thread_id = allocate_thread_id ();
163+ if (thread_id < 0 ) {
164+ LOG_ERROR ("Failed to get thread identifier" );
165+ goto thread_preparation_fail ;
166+ }
113167 thread_start_arg -> arg = start_arg ;
114168 thread_start_arg -> start_func = start_func ;
115169
116170 os_mutex_lock (& exec_env -> wait_lock );
117171 ret = wasm_cluster_create_thread (exec_env , new_module_inst , thread_start ,
118172 thread_start_arg );
119173 if (ret != 0 ) {
120- os_mutex_unlock (& exec_env -> wait_lock );
121174 LOG_ERROR ("Failed to spawn a new thread" );
122175 goto thread_spawn_fail ;
123176 }
@@ -126,9 +179,12 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
126179 return thread_id ;
127180
128181thread_spawn_fail :
182+ os_mutex_unlock (& exec_env -> wait_lock );
183+ deallocate_thread_id (thread_id );
184+
185+ thread_preparation_fail :
129186 if (new_module_inst )
130187 wasm_runtime_deinstantiate_internal (new_module_inst , true);
131-
132188 if (thread_start_arg )
133189 wasm_runtime_free (thread_start_arg );
134190
@@ -156,11 +212,25 @@ lib_wasi_threads_init(void)
156212 if (0 != os_mutex_init (& thread_id_lock ))
157213 return false;
158214
215+ // Initialize stack to store thread identifiers
216+ avail_tids .size = AVAIL_TIDS_INIT_SIZE ;
217+ avail_tids .pos = avail_tids .size ;
218+ avail_tids .ids =
219+ (int32 * )wasm_runtime_malloc (avail_tids .size * sizeof (int32 ));
220+ if (avail_tids .ids == NULL ) {
221+ os_mutex_destroy (& thread_id_lock );
222+ return false;
223+ }
224+ for (uint32 i = 0 ; i < avail_tids .size ; i ++ )
225+ avail_tids .ids [i ] = avail_tids .size - i ;
226+
159227 return true;
160228}
161229
162230void
163231lib_wasi_threads_destroy (void )
164232{
233+ wasm_runtime_free (avail_tids .ids );
234+ avail_tids .ids = NULL ;
165235 os_mutex_destroy (& thread_id_lock );
166236}
0 commit comments