aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@gmail.com>2017-03-05 17:42:04 -0500
committerMarat Dukhan <maratek@gmail.com>2017-03-05 17:42:04 -0500
commit630dfb6638927df1f3181eee339662a86b3cea0b (patch)
tree3ab980e82302f23083c7e003231ede3f13250ff6 /src
parenteecec4d76ec7ca27c461bd65208013b5d772e44d (diff)
downloadpthreadpool-630dfb6638927df1f3181eee339662a86b3cea0b.tar.gz
Fix race condition
Diffstat (limited to 'src')
-rw-r--r--src/pthreadpool.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/pthreadpool.c b/src/pthreadpool.c
index 6008429..a62bd44 100644
--- a/src/pthreadpool.c
+++ b/src/pthreadpool.c
@@ -163,13 +163,6 @@ static void wait_worker_threads(struct pthreadpool* threadpool) {
}
}
-static void wakeup_worker_threads(struct pthreadpool* threadpool) {
- pthread_mutex_lock(&threadpool->state_mutex);
- threadpool->checkedin_threads = 0; /* Locking of barrier_mutex not needed: readers are sleeping */
- pthread_cond_broadcast(&threadpool->state_condvar);
- pthread_mutex_unlock(&threadpool->state_mutex); /* Do wake up */
-}
-
inline static bool atomic_decrement(volatile size_t* value) {
size_t actual_value = *value;
if (actual_value != 0) {
@@ -301,6 +294,9 @@ void pthreadpool_compute_1d(
threadpool->function = function;
threadpool->argument = argument;
+ /* Locking of barrier_mutex not needed: readers are sleeping on state_condvar */
+ threadpool->checkedin_threads = 0;
+
/* Spread the work between threads */
for (size_t tid = 0; tid < threadpool->threads_count; tid++) {
struct thread_info* thread = &threadpool->threads[tid];
@@ -314,7 +310,7 @@ void pthreadpool_compute_1d(
pthread_mutex_unlock(&threadpool->state_mutex);
/* Wake up the threads */
- wakeup_worker_threads(threadpool);
+ pthread_cond_broadcast(&threadpool->state_condvar);
/* Wait until the threads finish computation */
wait_worker_threads(threadpool);
@@ -456,13 +452,22 @@ void pthreadpool_compute_2d_tiled(
}
void pthreadpool_destroy(struct pthreadpool* threadpool) {
+ /* Lock the state variables to ensure that threads don't start processing before they observe complete state */
+ pthread_mutex_lock(&threadpool->state_mutex);
+
+ /* Locking of barrier_mutex not needed: readers are sleeping on state_condvar */
+ threadpool->checkedin_threads = 0;
+
/* Update threads' states */
for (size_t tid = 0; tid < threadpool->threads_count; tid++) {
threadpool->threads[tid].state = thread_state_shutdown;
}
- /* Wake up the threads */
- wakeup_worker_threads(threadpool);
+ /* Wake up worker threads */
+ pthread_cond_broadcast(&threadpool->state_condvar);
+
+ /* Commit the state changes and let workers start processing */
+ pthread_mutex_unlock(&threadpool->state_mutex);
/* Wait until all threads return */
for (size_t tid = 0; tid < threadpool->threads_count; tid++) {