@@ -119,7 +119,7 @@ static void _jl_free_stack(jl_ptls_t ptls, void *stkbuf, size_t bufsz)
119119    if  (bufsz  <= pool_sizes [JL_N_STACK_POOLS  -  1 ]) {
120120        unsigned  pool_id  =  select_pool (bufsz );
121121        if  (pool_sizes [pool_id ] ==  bufsz ) {
122-             arraylist_push (& ptls -> heap .free_stacks [pool_id ], stkbuf );
122+             small_arraylist_push (& ptls -> heap .free_stacks [pool_id ], stkbuf );
123123            return ;
124124        }
125125    }
@@ -148,7 +148,7 @@ void jl_release_task_stack(jl_ptls_t ptls, jl_task_t *task)
148148#ifdef  _COMPILER_ASAN_ENABLED_ 
149149            __asan_unpoison_stack_memory ((uintptr_t )stkbuf , bufsz );
150150#endif 
151-             arraylist_push (& ptls -> heap .free_stacks [pool_id ], stkbuf );
151+             small_arraylist_push (& ptls -> heap .free_stacks [pool_id ], stkbuf );
152152        }
153153    }
154154}
@@ -163,9 +163,9 @@ JL_DLLEXPORT void *jl_malloc_stack(size_t *bufsz, jl_task_t *owner) JL_NOTSAFEPO
163163    if  (ssize  <= pool_sizes [JL_N_STACK_POOLS  -  1 ]) {
164164        unsigned  pool_id  =  select_pool (ssize );
165165        ssize  =  pool_sizes [pool_id ];
166-         arraylist_t  * pool  =  & ptls -> heap .free_stacks [pool_id ];
166+         small_arraylist_t  * pool  =  & ptls -> heap .free_stacks [pool_id ];
167167        if  (pool -> len  >  0 ) {
168-             stk  =  arraylist_pop (pool );
168+             stk  =  small_arraylist_pop (pool );
169169        }
170170    }
171171    else  {
@@ -184,8 +184,8 @@ JL_DLLEXPORT void *jl_malloc_stack(size_t *bufsz, jl_task_t *owner) JL_NOTSAFEPO
184184    }
185185    * bufsz  =  ssize ;
186186    if  (owner ) {
187-         arraylist_t  * live_tasks  =  & ptls -> heap .live_tasks ;
188-         arraylist_push (live_tasks , owner );
187+         small_arraylist_t  * live_tasks  =  & ptls -> heap .live_tasks ;
188+         mtarraylist_push (live_tasks , owner );
189189    }
190190    return  stk ;
191191}
@@ -209,7 +209,7 @@ void sweep_stack_pools(void)
209209
210210        // free half of stacks that remain unused since last sweep 
211211        for  (int  p  =  0 ; p  <  JL_N_STACK_POOLS ; p ++ ) {
212-             arraylist_t  * al  =  & ptls2 -> heap .free_stacks [p ];
212+             small_arraylist_t  * al  =  & ptls2 -> heap .free_stacks [p ];
213213            size_t  n_to_free ;
214214            if  (al -> len  >  MIN_STACK_MAPPINGS_PER_POOL ) {
215215                n_to_free  =  al -> len  / 2 ;
@@ -220,12 +220,12 @@ void sweep_stack_pools(void)
220220                n_to_free  =  0 ;
221221            }
222222            for  (int  n  =  0 ; n  <  n_to_free ; n ++ ) {
223-                 void  * stk  =  arraylist_pop (al );
223+                 void  * stk  =  small_arraylist_pop (al );
224224                free_stack (stk , pool_sizes [p ]);
225225            }
226226        }
227227
228-         arraylist_t  * live_tasks  =  & ptls2 -> heap .live_tasks ;
228+         small_arraylist_t  * live_tasks  =  & ptls2 -> heap .live_tasks ;
229229        size_t  n  =  0 ;
230230        size_t  ndel  =  0 ;
231231        size_t  l  =  live_tasks -> len ;
@@ -268,24 +268,52 @@ void sweep_stack_pools(void)
268268
269269JL_DLLEXPORT  jl_array_t  * jl_live_tasks (void )
270270{
271-     jl_task_t  * ct  =  jl_current_task ;
272-     jl_ptls_t  ptls  =  ct -> ptls ;
273-     arraylist_t  * live_tasks  =  & ptls -> heap .live_tasks ;
274-     size_t  i , j , l ;
275-     jl_array_t  * a ;
276-     do  {
277-         l  =  live_tasks -> len ;
278-         a  =  jl_alloc_vec_any (l  +  1 ); // may gc, changing the number of tasks 
279-     } while  (l  +  1  <  live_tasks -> len );
280-     l  =  live_tasks -> len ;
281-     void  * * lst  =  live_tasks -> items ;
282-     j  =  0 ;
283-     ((void * * )jl_array_data (a ))[j ++ ] =  ptls -> root_task ;
284-     for  (i  =  0 ; i  <  l ; i ++ ) {
285-         if  (((jl_task_t * )lst [i ])-> stkbuf  !=  NULL )
286-             ((void * * )jl_array_data (a ))[j ++ ] =  lst [i ];
271+     size_t  nthreads  =  jl_atomic_load_acquire (& jl_n_threads );
272+     jl_ptls_t  * allstates  =  jl_atomic_load_relaxed (& jl_all_tls_states );
273+     size_t  l  =  0 ; // l is not reset on restart, so we keep getting more aggressive at making a big enough list everything it fails 
274+ restart :
275+     for  (size_t  i  =  0 ; i  <  nthreads ; i ++ ) {
276+         // skip GC threads since they don't have tasks 
277+         if  (gc_first_tid  <= i  &&  i  <  gc_first_tid  +  jl_n_gcthreads ) {
278+             continue ;
279+         }
280+         jl_ptls_t  ptls2  =  allstates [i ];
281+         if  (ptls2  ==  NULL )
282+             continue ;
283+         small_arraylist_t  * live_tasks  =  & ptls2 -> heap .live_tasks ;
284+         size_t  n  =  mtarraylist_length (live_tasks );
285+         l  +=  n  +  (ptls2 -> root_task -> stkbuf  !=  NULL );
286+     }
287+     l  +=  l  / 20 ; // add 5% for margin of estimation error 
288+     jl_array_t  * a  =  jl_alloc_vec_any (l ); // may gc, changing the number of tasks and forcing us to reload everything 
289+     nthreads  =  jl_atomic_load_acquire (& jl_n_threads );
290+     allstates  =  jl_atomic_load_relaxed (& jl_all_tls_states );
291+     size_t  j  =  0 ;
292+     for  (size_t  i  =  0 ; i  <  nthreads ; i ++ ) {
293+         // skip GC threads since they don't have tasks 
294+         if  (gc_first_tid  <= i  &&  i  <  gc_first_tid  +  jl_n_gcthreads ) {
295+             continue ;
296+         }
297+         jl_ptls_t  ptls2  =  allstates [i ];
298+         if  (ptls2  ==  NULL )
299+             continue ;
300+         jl_task_t  * t  =  ptls2 -> root_task ;
301+         if  (t -> stkbuf  !=  NULL ) {
302+             if  (j  ==  l )
303+                 goto restart ;
304+             ((void * * )jl_array_data (a ))[j ++ ] =  t ;
305+         }
306+         small_arraylist_t  * live_tasks  =  & ptls2 -> heap .live_tasks ;
307+         size_t  n  =  mtarraylist_length (live_tasks );
308+         for  (size_t  i  =  0 ; i  <  n ; i ++ ) {
309+             jl_task_t  * t  =  (jl_task_t * )mtarraylist_get (live_tasks , i );
310+             if  (t -> stkbuf  !=  NULL ) {
311+                 if  (j  ==  l )
312+                     goto restart ;
313+                 ((void * * )jl_array_data (a ))[j ++ ] =  t ;
314+             }
315+         }
287316    }
288-     l  =  jl_array_len (a );
289317    if  (j  <  l ) {
290318        JL_GC_PUSH1 (& a );
291319        jl_array_del_end (a , l  -  j );
0 commit comments