Skip to content

Commit 0c7e043

Browse files
committed
use previous gaurd
1 parent fed500c commit 0c7e043

File tree

1 file changed

+25
-26
lines changed

1 file changed

+25
-26
lines changed

system/lib/pthread/proxying.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
struct em_proxying_queue {
2222
// Protects all accesses to em_task_queues, size, and capacity.
2323
pthread_mutex_t mutex;
24-
// If the mutex is locked this is the thread that is using it.
25-
pthread_t active_thread;
2624
// `size` task queue pointers stored in an array of size `capacity`.
2725
em_task_queue** task_queues;
2826
int size;
@@ -32,12 +30,13 @@ struct em_proxying_queue {
3230
// The system proxying queue.
3331
static em_proxying_queue system_proxying_queue = {
3432
.mutex = PTHREAD_MUTEX_INITIALIZER,
35-
.active_thread = NULL,
3633
.task_queues = NULL,
3734
.size = 0,
3835
.capacity = 0,
3936
};
4037

38+
static _Thread_local int system_queue_in_use = 0;
39+
4140
em_proxying_queue* emscripten_proxy_get_system_queue(void) {
4241
return &system_proxying_queue;
4342
}
@@ -50,7 +49,6 @@ em_proxying_queue* em_proxying_queue_create(void) {
5049
}
5150
*q = (em_proxying_queue){
5251
.mutex = PTHREAD_MUTEX_INITIALIZER,
53-
.active_thread = NULL,
5452
.task_queues = NULL,
5553
.size = 0,
5654
.capacity = 0,
@@ -110,32 +108,28 @@ static em_task_queue* get_or_add_tasks_for_thread(em_proxying_queue* q,
110108
return tasks;
111109
}
112110

113-
static _Thread_local bool executing_system_queue = false;
114-
115111
void emscripten_proxy_execute_queue(em_proxying_queue* q) {
116112
assert(q != NULL);
117113
assert(pthread_self());
118114

119-
// Recursion guard to avoid infinite recursion when we arrive here from the
120-
// pthread_lock call below that executes the system queue. The per-task_queue
121-
// recursion lock can't catch these recursions because it can only be checked
122-
// after the lock has been acquired.
123-
bool is_system_queue = q == &system_proxying_queue;
124-
if (is_system_queue) {
125-
if (executing_system_queue) {
126-
return;
127-
}
128-
executing_system_queue = true;
129-
}
130-
131-
// When the current thread is adding tasks it locks the queue, but we can
115+
// Below is a recursion and deadlock guard:
116+
// The recursion guard is to avoid infinite recursion when we arrive here from
117+
// the pthread_lock call below that executes the system queue. The
118+
// per-task_queue recursion lock can't catch these recursions because it can
119+
// only be checked after the lock has been acquired.
120+
//
121+
// This also guards against deadlocks when adding to the system queue. When
122+
// the current thread is adding tasks, it locks the queue, but we can
132123
// potentially try to execute the queue during the add (from
133124
// emscripten_yield). This will deadlock the thread, so only try to take the
134-
// lock if the current thread is not adding to the queue. We then hope the
125+
// lock if the current thread is not using the queue. We then hope the
135126
// queue is executed later when it is unlocked.
136-
// XXX: This could leave to starvation if we never process the queue.
137-
if (q->active_thread == pthread_self()) {
138-
return;
127+
int is_system_queue = q == &system_proxying_queue;
128+
if (is_system_queue) {
129+
if (system_queue_in_use) {
130+
return;
131+
}
132+
system_queue_in_use = true;
139133
}
140134

141135
pthread_mutex_lock(&q->mutex);
@@ -148,16 +142,21 @@ void emscripten_proxy_execute_queue(em_proxying_queue* q) {
148142
}
149143

150144
if (is_system_queue) {
151-
executing_system_queue = false;
145+
system_queue_in_use = false;
152146
}
153147
}
154148

155149
static int do_proxy(em_proxying_queue* q, pthread_t target_thread, task t) {
156150
assert(q != NULL);
157151
pthread_mutex_lock(&q->mutex);
158-
q->active_thread = pthread_self();
152+
int is_system_queue = q == &system_proxying_queue;
153+
if (is_system_queue) {
154+
system_queue_in_use = 1;
155+
}
159156
em_task_queue* tasks = get_or_add_tasks_for_thread(q, target_thread);
160-
q->active_thread = NULL;
157+
if (is_system_queue) {
158+
system_queue_in_use = 0;
159+
}
161160
pthread_mutex_unlock(&q->mutex);
162161
if (tasks == NULL) {
163162
return 0;

0 commit comments

Comments
 (0)