Search code examples
cpthreads

Thread asynchronous waiting signaling


I need a C code for a program which N threads can communicate with eachother.

each thread id can wait for whichever thread id it wants.

each thread id can signal which ever thread id it wants.

they can wait and signal each other multiple times.

when a thread is signaled it means it can stop waiting for the thread and that the two threads are synched, like a barrier but implemented with mutex and condition variables instead.

each thread that waits are waiting to be signaled by a specific thread with an id called buddy and with the right int:synch_point and int:group, if they are not the same then the thread has to continue waiting until such signal has been received.

void signal_and_wait_for_thread(thread_data_t *thread_data, int myid, int buddy, int sync_point, int stride) {
    // Lock myid mutex and update the shared data
    pthread_mutex_lock(&thread_data->mutexes[myid]);
    thread_data->sync_points[myid] = sync_point;
    thread_data->strides[myid] = stride;
    //thread_data->ready[myid] = 1;
    pthread_cond_broadcast(&thread_data->conds[myid]);
    pthread_mutex_unlock(&thread_data->mutexes[myid]);

    // Lock buddy mutex and wait for the buddy thread to reach the same sync point and stride
    pthread_mutex_lock(&thread_data->mutexes[buddy]);
    while (
             thread_data->sync_points[buddy] != sync_point ||
             thread_data->strides[buddy] != stride) {
        pthread_cond_wait(&thread_data->conds[buddy], &thread_data->mutexes[buddy]);
    }
    //thread_data->ready[buddy] = 0;
    pthread_mutex_unlock(&thread_data->mutexes[buddy]);
}

The code above tries to implement this signal and wait for multiple thread ID's. Problem is it is reaching deadlock. What is the proper way to synchronize two threads amongst N threads that might want to communicate with the same thread. without introducing too much overhead with unneccesary mutexes.


Solution

  • void wait_for_buddy(thread_data_t * thread_data, int myid, int buddy) {
    
        pthread_mutex_lock( & thread_data -> mutexes[buddy + 1]);
    
        while (!thread_data -> ready[myid][buddy]) {
    
                pthread_cond_wait( & thread_data -> conds[buddy], & thread_data -> mutexes[buddy + 1]);
        }
        thread_data -> ready[myid][buddy] = 0; // Reset for next sync point
        pthread_mutex_unlock( & thread_data -> mutexes[buddy + 1]);
    

    }

    void signal_ready(thread_data_t * thread_data, int myid, int buddy) {
    
            pthread_mutex_lock( & thread_data -> mutexes[myid + 1]);
            thread_data -> ready[buddy][myid] = 1;
            pthread_cond_broadcast( & thread_data -> conds[myid]);
            pthread_mutex_unlock( & thread_data -> mutexes[myid + 1]);
    
    }