Skip to content

Commit 534dd0a

Browse files
committed
use dispatch_unfair_locks around registered worker critical sections
1 parent afec572 commit 534dd0a

File tree

1 file changed

+12
-24
lines changed

1 file changed

+12
-24
lines changed

src/event/workqueue.c

+12-24
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static volatile int32_t _dispatch_workq_runnable_workers;
5151
* The desired number of runnable worker threads
5252
* for a workqueue (assuming sufficient work).
5353
*/
54-
static int _dispatch_workq_target_runnable_workers;
54+
static int32_t _dispatch_workq_target_runnable_workers;
5555

5656
#if DISPATCH_ENABLE_PWQ_KEXT
5757
/* Are we using user-level or kext based management? */
@@ -63,10 +63,10 @@ static bool _dispatch_workq_kext_active;
6363
*/
6464
typedef struct dispatch_workq_manager_s {
6565
/*
66-
* Tracking of registered workers; all updates and reads are performed
67-
* holding the mutex.
66+
* Tracking of registered workers; all updates and reads
67+
* are performed while holding the lock.
6868
*/
69-
pthread_mutex_t registered_worker_mutex;
69+
dispatch_unfair_lock_s registered_worker_lock;
7070
int num_registered_workers;
7171
pid_t *registered_workers;
7272

@@ -116,17 +116,15 @@ dispatch_workq_worker_register(dispatch_queue_t root_q)
116116
#endif
117117
bool rc;
118118
int tid = syscall(SYS_gettid);
119-
int r = pthread_mutex_lock(&_dispatch_workq_manager.registered_worker_mutex);
120-
(void)dispatch_assume_zero(r);
119+
_dispatch_unfair_lock_lock(&_dispatch_workq_manager.registered_worker_lock);
121120
if (_dispatch_workq_manager.num_registered_workers < WORKQ_MAX_TRACKED_WORKERS-1) {
122121
int worker_id = _dispatch_workq_manager.num_registered_workers++;
123122
_dispatch_workq_manager.registered_workers[worker_id] = tid;
124123
rc = true;
125124
} else {
126125
rc = false;
127126
}
128-
r = pthread_mutex_unlock(&_dispatch_workq_manager.registered_worker_mutex);
129-
(void)dispatch_assume_zero(r);
127+
_dispatch_unfair_lock_unlock(&_dispatch_workq_manager.registered_worker_lock);
130128

131129
return rc;
132130
}
@@ -146,8 +144,7 @@ dispatch_workq_worker_unregister(dispatch_queue_t root_q)
146144
}
147145
#endif
148146
int tid = syscall(SYS_gettid);
149-
int r = pthread_mutex_lock(&_dispatch_workq_manager.registered_worker_mutex);
150-
(void)dispatch_assume_zero(r);
147+
_dispatch_unfair_lock_lock(&_dispatch_workq_manager.registered_worker_lock);
151148
for (int i=0; i<_dispatch_workq_manager.num_registered_workers; i++) {
152149
if (_dispatch_workq_manager.registered_workers[i] == tid) {
153150
int last = _dispatch_workq_manager.num_registered_workers - 1;
@@ -157,8 +154,7 @@ dispatch_workq_worker_unregister(dispatch_queue_t root_q)
157154
break;
158155
}
159156
}
160-
r = pthread_mutex_unlock(&_dispatch_workq_manager.registered_worker_mutex);
161-
(void)dispatch_assume_zero(r);
157+
_dispatch_unfair_lock_unlock(&_dispatch_workq_manager.registered_worker_lock);
162158
}
163159

164160

@@ -173,26 +169,24 @@ _dispatch_workq_count_runnable_workers(void)
173169
char path[128];
174170
char buf[4096];
175171
int running_count = 0;
176-
int r;
177172

178173
memset(buf, 0, sizeof(buf));
179174

180-
r = pthread_mutex_lock(&_dispatch_workq_manager.registered_worker_mutex);
181-
(void)dispatch_assume_zero(r);
175+
_dispatch_unfair_lock_lock(&_dispatch_workq_manager.registered_worker_lock);
182176

183177
for (int i=0; i<_dispatch_workq_manager.num_registered_workers; i++) {
184178
pid_t worker_pid = _dispatch_workq_manager.registered_workers[i];
185179
int fd;
186180
size_t bytes_read = -1;
187181

188-
r = snprintf(path, sizeof(path), "/proc/%d/stat", worker_pid);
182+
int r = snprintf(path, sizeof(path), "/proc/%d/stat", worker_pid);
189183
(void)dispatch_assume(r > 0 && r < sizeof(path));
190184

191185
fd = open(path, O_RDONLY | O_NONBLOCK);
192186
if (unlikely(fd == -1)) {
193187
// Unable to open file.
194188
// Must mean worker exited uncleanly (without executing _dispatch_worker_unregister())
195-
// Clean up by removing pid and decrementing number of workers in pool
189+
// Clean up by removing pid and decrementing number of registered workers
196190
_dispatch_debug("workq: Unable to open /proc/%d/stat; removing worker from monitoring list", worker_pid);
197191
int last = _dispatch_workq_manager.num_registered_workers-1;
198192
_dispatch_workq_manager.registered_workers[i] = _dispatch_workq_manager.registered_workers[last];
@@ -219,8 +213,7 @@ _dispatch_workq_count_runnable_workers(void)
219213
}
220214
}
221215

222-
r = pthread_mutex_unlock(&_dispatch_workq_manager.registered_worker_mutex);
223-
(void)dispatch_assume_zero(r);
216+
_dispatch_unfair_lock_unlock(&_dispatch_workq_manager.registered_worker_lock);
224217

225218
return running_count;
226219
}
@@ -264,11 +257,6 @@ _dispatch_workq_init_once(void *context DISPATCH_UNUSED)
264257
return;
265258
}
266259
#endif
267-
int r;
268-
269-
r = pthread_mutex_init(&_dispatch_workq_manager.registered_worker_mutex, NULL);
270-
(void)dispatch_assume_zero(r);
271-
272260
_dispatch_workq_manager.registered_workers =
273261
_dispatch_calloc(WORKQ_MAX_TRACKED_WORKERS, sizeof(pid_t));
274262

0 commit comments

Comments
 (0)