i have weird problem pthread_cond_wait , pthread_cond_signal. have arranged series of threads. in sleep state when started. wake function signal these threads, work, , wait results.
in setup below, td thread data, containing mutex , conditions, , th array containing pointer threads:
for (size_t = 0; < num_threads; i++) { pthread_cond_init(&td[i].cond, null); pthread_mutex_init(&td[i].cond_mutex, null); pthread_mutex_init(&td[i].work_mutex, null); pthread_mutex_lock(&td[i].cond_mutex); pthread_mutex_lock(&td[i].work_mutex); pthread_create(&th[i], null, thread_worker, (void *)&td[i]); } thread worker this:
void* thread_worker(void* data) { thread_data *td = (thread_data *)data; while (1) { pthread_cond_wait(&td->cond, &td->cond_mutex); // marker // work ... pthread_mutex_unlock(&td->work_mutex); } pthread_exit(null); } this job function supposed wake threads, job, , wait them finish:
void job() { (size_t = 0; < num_threads; i++) { pthread_cond_signal(&td[i].cond); } (size_t = 0; < num_threads; i++) { pthread_mutex_lock(&td[i].work_mutex); // block until work done } } in rare situations (1 out of 1000 runs maybe), above setup encounter freeze. when happens, 'marker' line in thread_worker not signaled pthread_cond_signal, kept on waiting. it's rare happens time time. i've produced numerous log messages, , verified pthread_cond_wait called before pthread_cond_signal. doing wrong here?
there nothing there forces pthread_cond_wait() called before pthread_cond_signal(). despite logging, it's entirely possible logged lines out-of-sequence happened.
you aren't using mutexes , condition variables correctly: mutexes should unlocked same thread locked them, , condition variables should paired test on shared state (called predicate). shared state supposed protected mutex passed pthread_cond_wait().
for example, example can reworked correctly use mutexes , condition variables. first, add int work_status thread_data structure, 0 indicates thread waiting work, 1 indicates work available , 2 indicates work complete.
you don't appear need 2 mutexes in each thread_data, , don't want lock mutex in main thread when you're setting up:
for (size_t = 0; < num_threads; i++) { pthread_cond_init(&td[i].cond, null); pthread_mutex_init(&td[i].cond_mutex, null); td[i].work_status = 0; pthread_create(&th[i], null, thread_worker, (void *)&td[i]); } have threads wait on work_status using condition variable:
void* thread_worker(void* data) { thread_data *td = (thread_data *)data; while (1) { /* wait work available */ pthread_mutex_lock(&td->cond_mutex); while (td->work_status != 1) pthread_cond_wait(&td->cond, &td->cond_mutex); pthread_mutex_unlock(&td->cond_mutex); // work ... /* tell main thread work has finished */ pthread_mutex_lock(&td->cond_mutex); td->work_status = 2; pthread_cond_signal(&td->cond); pthread_mutex_unlock(&td->cond_mutex); } pthread_exit(null); } ...and set , wait on work_status appropriate in job():
void job() { /* tell threads work available */ (size_t = 0; < num_threads; i++) { pthread_mutex_lock(&td[i].cond_mutex); td[i].work_status = 1; pthread_cond_signal(&td[i].cond); pthread_mutex_unlock(&td[i].cond_mutex); } /* wait threads signal work complete */ (size_t = 0; < num_threads; i++) { pthread_mutex_lock(&td[i].cond_mutex); while (td[i].work_status != 2) pthread_cond_wait(&td[i].cond, &td[i].cond_mutex); pthread_mutex_unlock(&td[i].cond_mutex); } }
Comments
Post a Comment