7373#include <cpuinfo.h>
7474#endif
7575
76+ /* Alloca */
77+ #if defined(_MSC_VER )
78+ #include <malloc.h>
79+ #define alloca _alloca
80+ #endif // defined(_MSC_VER)
81+
7682/* Public library header */
7783#include <pthreadpool.h>
7884
@@ -593,6 +599,23 @@ struct pthreadpool* pthreadpool_create_v2(struct pthreadpool_executor* executor,
593599 return threadpool ;
594600}
595601
602+ static void wake_up_threads (void * * contexts ) {
603+ struct pthreadpool * threadpool = (struct pthreadpool * )contexts [0 ];
604+ struct pthreadpool_executor * executor = & threadpool -> executor ;
605+ for (uint32_t k = 1 ; contexts [k ] != NULL ; k ++ ) {
606+ if (contexts [k + 1 ] != NULL ) {
607+ /* Fly, my pretties! Fly, fly, fly! */
608+ executor -> schedule (threadpool -> executor_context , contexts [k ],
609+ (void (* )(void * ))thread_main );
610+ } else {
611+ void * context = contexts [k ];
612+ free (contexts );
613+ thread_main (context );
614+ return ;
615+ }
616+ }
617+ }
618+
596619static void ensure_num_threads (struct pthreadpool * threadpool ,
597620 uint32_t num_threads ) {
598621 assert (num_threads >= 1 );
@@ -604,21 +627,37 @@ static void ensure_num_threads(struct pthreadpool* threadpool,
604627 return ;
605628 }
606629
630+ void * * thread_contexts = alloca (sizeof (void * ) * num_threads );
631+ int32_t num_threads_to_wake = 0 ;
632+
607633 /* Create any missing threads for this threadpool. */
608634 for (uint32_t tid = 1 ;
609635 tid < num_threads &&
610636 pthreadpool_load_consume_int32_t (& threadpool -> num_active_threads ) > 0 ;
611637 tid ++ ) {
612638 struct thread_info * thread = & threadpool -> threads [tid ];
613639
614- // Check whether this thread was active, and if not, start it up.
640+ // Check whether this thread was active, and if not, add it to the list of
641+ // threads that need starting.
615642 if (!pthreadpool_exchange_sequentially_consistent_uint32_t (
616643 & thread -> is_active , 1 )) {
617644 pthreadpool_register_threads (threadpool , 1 );
645+ thread_contexts [num_threads_to_wake ++ ] = thread ;
646+ }
647+ }
618648
649+ if (num_threads_to_wake > 1 ) {
650+ void * * contexts = malloc (sizeof (void * ) * (num_threads_to_wake + 2 ));
651+ contexts [0 ] = threadpool ;
652+ memcpy (contexts + 1 , thread_contexts , sizeof (void * ) * num_threads_to_wake );
653+ contexts [num_threads_to_wake + 1 ] = NULL ;
654+ /* Fly, my pretties! Fly, fly, fly! */
655+ executor -> schedule (threadpool -> executor_context , contexts ,
656+ (void (* )(void * ))wake_up_threads );
657+ } else if (num_threads_to_wake == 1 ) {
658+ for (int k = 0 ; k < num_threads_to_wake ; k ++ ) {
619659 /* Fly, my pretties! Fly, fly, fly! */
620- pthreadpool_log_debug ("starting thread %u (arg=%p)." , tid , thread );
621- executor -> schedule (threadpool -> executor_context , thread ,
660+ executor -> schedule (threadpool -> executor_context , thread_contexts [k ],
622661 (void (* )(void * ))thread_main );
623662 }
624663 }
0 commit comments