From e9b4f8e38998813df7601651898672ae10b2bc5b Mon Sep 17 00:00:00 2001 From: PowerUser64 Date: Tue, 19 Nov 2024 15:08:22 -0800 Subject: [PATCH 1/3] mutex(fix): prevent race condition (part 2) In addition to the previous commit, this commit makes threads need to wait for the thread manager to say it took the mutex from them before they can ask for it again. --- main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index ca4be50..49cea53 100644 --- a/main.cpp +++ b/main.cpp @@ -56,9 +56,10 @@ void *thread_task_increment(const struct thread_data &thread) { { // tell the thread manager we want the mutex + while (!*thread.manager_took_mutex) (*thread.wants_mutex) = true; // block until we have the mutex - while (!*thread.has_mutex && *thread.manager_took_mutex) + while (!*thread.has_mutex) ; // enter the mutex From dc89fc4ce2bdbc69657913c0514c307fe51b9118 Mon Sep 17 00:00:00 2001 From: PowerUser64 Date: Tue, 19 Nov 2024 15:08:22 -0800 Subject: [PATCH 2/3] mutex(fix): prevent race condition (part 2) In addition to the previous commit, this commit makes threads need to wait for the thread manager to say it took the mutex from them before they can ask for it again. --- main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index ca4be50..4ff5749 100644 --- a/main.cpp +++ b/main.cpp @@ -55,10 +55,13 @@ void *thread_task_increment(const struct thread_data &thread) { // mutex { - // tell the thread manager we want the mutex + // wait for permission to ask for the mutex + while (!*thread.manager_took_mutex) + ; + // say we want the mutex (*thread.wants_mutex) = true; // block until we have the mutex - while (!*thread.has_mutex && *thread.manager_took_mutex) + while (!*thread.has_mutex) ; // enter the mutex From d9089c4348ce69c2bbb61c162e4ee4a3a90c1db5 Mon Sep 17 00:00:00 2001 From: PowerUser64 Date: Tue, 19 Nov 2024 15:28:19 -0800 Subject: [PATCH 3/3] mutex: comments and name clarity --- main.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 4ff5749..2912aad 100644 --- a/main.cpp +++ b/main.cpp @@ -18,10 +18,10 @@ typedef void *(*ThreadTask)(const struct thread_data &); typedef void *(*PthreadFun)(void *arg); struct thread_group { - bool wants_mutex[NUM_THREADS] = {0}; - bool has_mutex[NUM_THREADS] = {0}; - bool manager_took_mutex[NUM_THREADS] = {0}; - bool threads_finished[NUM_THREADS] = {0}; + bool wants_mutex[NUM_THREADS] = {0}; // set by the thread + bool has_mutex[NUM_THREADS] = {0}; // set by us, read by thread + bool can_ask_for_mutex[NUM_THREADS] = {1}; // set by us, read by thread + bool threads_finished[NUM_THREADS] = {0}; // set by thread ThreadTask task; size_t total_threads; void *data; @@ -31,7 +31,7 @@ struct thread_data { size_t id; bool *wants_mutex; const bool *has_mutex; - const bool *manager_took_mutex; + const bool *can_ask_for_mutex; bool *is_finished; void *data; }; @@ -56,7 +56,7 @@ void *thread_task_increment(const struct thread_data &thread) { { // wait for permission to ask for the mutex - while (!*thread.manager_took_mutex) + while (!*thread.can_ask_for_mutex) ; // say we want the mutex (*thread.wants_mutex) = true; @@ -105,8 +105,8 @@ void do_threading(struct thread_group threads) { threads.total_threads * sizeof(*threads.threads_finished)); // at the start, we have the mutex and haven't given it - memset(threads.manager_took_mutex, 1, - threads.total_threads * sizeof(*threads.manager_took_mutex)); + memset(threads.can_ask_for_mutex, 1, + threads.total_threads * sizeof(*threads.can_ask_for_mutex)); // create thread data for (size_t tid = 0; tid < threads.total_threads; ++tid) { @@ -114,7 +114,7 @@ void do_threading(struct thread_group threads) { .id = tid, .wants_mutex = &threads.wants_mutex[tid], .has_mutex = &threads.has_mutex[tid], - .manager_took_mutex = &threads.manager_took_mutex[tid], + .can_ask_for_mutex = &threads.can_ask_for_mutex[tid], .is_finished = &threads.threads_finished[tid], .data = threads.data, }; @@ -154,9 +154,9 @@ void do_threading(struct thread_group threads) { // take the mutex from the thread that has it threads.has_mutex[tid_has] = false; - threads.manager_took_mutex[tid_has] = true; + threads.can_ask_for_mutex[tid_has] = true; // give the mutex to the thread that wants it - threads.manager_took_mutex[tid_wants] = false; + threads.can_ask_for_mutex[tid_wants] = false; threads.has_mutex[tid_wants] = true; }