Awakening individual threads instead of busy in pthreads

I am not sure that the name reflects what I ask here, but this is the best way I can do without a very short title. I am trying to implement a worker thread model in pthreads . I want to create a set of threads from the main function, after which the main thread delegates the task to the worker and waits for all the threads to finish before assigning them the next task (in fact, the requirement is to arrange the stream in a block similar to the CUDA programming model, but on the CPU. Although this does not apply to the current issue). The job array is used to indicate the type of job for each thread. I have currently implemented this with semaphores that impose lively expectation. I am looking for ways to make it so that threads sleep and wake up only when they are required, and not poll continuously.

Function performed by each thread

 volatile int jobs[MAX_THREADS]; // global job indicator array sem_t semaphore; // semaphore to indicate completion thread_execute(void *args) { tid = get_id(args); while(jobs[tid] != -1) { if(jobs[tid] == 0) continue; // no job if(jobs[tid] == JOBS_1) { jobs1(); jobs[tid] = 0; // go back to idle state sem_post(&semapahore); } if(jobs[tid] == JOBS_2) { jobs2(); jobs[tid] = 0; // go back to idle state sem_post(&semapahore); } } pthread_exit(NULL); } 

The main function is as follows

 int main() { sem_init(&semaphore, 0, 0); jobs[0...MAX_THREADS] = 0; spawn_threads(); // Dispatch first job jobs[0...MAX_THREADS] = JOBS_1; int semvalue = 0; while (semvalue < MAX_THREADS) // Wait till all threads increment the semaphore sem_getvalue(&sempaphore, &semvalue); sem_init(&semaphore, 0, 0); // Init semaphore back to 0 for the next job // I'm actually using diff. semaphores for diff. jobs jobs[0...MAX_THREADS] = JOBS_2; while (semvalue < MAX_THREADS) sem_getvalue(&sempaphore, &semvalue); jobs[0...MAX_THREADS] = -1; // No more jobs pthread_join(); } 

The problem with this implementation is that the main thread is busy waiting for all workflows to complete, and the workflows are also constantly polling an array of jobs to check for a new job. Is there a better way to do this when the threads fall asleep and wake up, when necessary, along the lines of a single handler and using pthread_kill() , but this is pretty messy with a separate signal handler.

+4
source share
1 answer

You can use a conditional variable to keep threads asleep until they are signaled.

 volatile int jobs[MAX_THREADS]; // global job indicator array pthread_cond_t th_cond; // threads wait on this pthread_mutex_t th_mutex; // mutex to protect the signal int busyThreads = MAX_THREADS; pthread_cond_t m_cond; // main thread waits on this pthread_mutex_t m_mutex; // mutex to protect main signal thread_execute(void *args) { tid = get_id(args); while(jobs[tid] != -1) { if(jobs[tid] == 0) continue; // no job if(jobs[tid] == JOBS_1) { jobs1(); jobs[tid] = 0; // go back to idle state pthread_mutex_lock(&th_mutex); pthread_mutex_lock(&m_mutex); --busyThreads; // one less worker pthread_cond_signal(&m_cond); // signal main to check progress pthread_mutex_unlock(&m_mutex); pthread_cond_wait(&th_cond, &th_mutex); // wait for next job pthread_mutex_unlock(&th_mutex); } if(jobs[tid] == JOBS_2) { jobs2(); jobs[tid] = 0; // go back to idle state pthread_mutex_lock(&th_mutex); --busyThreads; pthread_cond_wait(&th_cond, &th_mutex); pthread_mutex_unlock(&th_mutex); } } pthread_exit(NULL); } 

then basically:

 int main() { sem_init(&semaphore, 0, 0); jobs[0...MAX_THREADS] = 0; spawn_threads(); // Dispatch first job jobs[0...MAX_THREADS] = JOBS_1; int semvalue = 0; pthread_mutex_lock(&m_mutex); while(busyThreads > 0) // check number of active workers pthread_cond_wait(&m_cond, &m_mutex); pthread_mutex_unlock(&m_mutex); busyThreads = MAX_THREADS; pthread_mutex_lock(&th_mutex); pthread_cond_broadcast(&th_cond); // signal all workers to resume pthread_mutex_unlock(&th_mutex); // same for JOBS_2; jobs[0...MAX_THREADS] = -1; // No more jobs pthread_join(); } 
+3
source

Source: https://habr.com/ru/post/1398883/


All Articles