summaryrefslogtreecommitdiff
path: root/ot_mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_mutex.c')
-rw-r--r--ot_mutex.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/ot_mutex.c b/ot_mutex.c
index 37d9962..5392264 100644
--- a/ot_mutex.c
+++ b/ot_mutex.c
@@ -6,6 +6,7 @@
6/* System */ 6/* System */
7#include <arpa/inet.h> 7#include <arpa/inet.h>
8#include <pthread.h> 8#include <pthread.h>
9#include <stdatomic.h>
9#include <stdio.h> 10#include <stdio.h>
10#include <stdlib.h> 11#include <stdlib.h>
11#include <unistd.h> 12#include <unistd.h>
@@ -25,7 +26,9 @@
25/* Our global all torrents list */ 26/* Our global all torrents list */
26static ot_vector all_torrents[OT_BUCKET_COUNT]; 27static ot_vector all_torrents[OT_BUCKET_COUNT];
27static pthread_mutex_t bucket_mutex[OT_BUCKET_COUNT]; 28static pthread_mutex_t bucket_mutex[OT_BUCKET_COUNT];
28static size_t g_torrent_count; 29/* Every bucket's unlock adjusts this, and a bucket lock only keeps other
30 threads out of that one bucket, so the counter needs its own protection */
31static _Atomic size_t g_torrent_count;
29 32
30/* Self pipe from opentracker.c */ 33/* Self pipe from opentracker.c */
31extern int g_self_pipe[2]; 34extern int g_self_pipe[2];
@@ -47,14 +50,15 @@ ot_vector *mutex_bucket_lock_by_hash(ot_hash const hash) { return mutex_bucket_l
47 50
48void mutex_bucket_unlock(int bucket, int delta_torrentcount) { 51void mutex_bucket_unlock(int bucket, int delta_torrentcount) {
49 pthread_mutex_unlock(bucket_mutex + bucket); 52 pthread_mutex_unlock(bucket_mutex + bucket);
50 g_torrent_count += delta_torrentcount; 53 if (delta_torrentcount)
54 atomic_fetch_add_explicit(&g_torrent_count, (size_t)delta_torrentcount, memory_order_relaxed);
51} 55}
52 56
53void mutex_bucket_unlock_by_hash(ot_hash const hash, int delta_torrentcount) { 57void mutex_bucket_unlock_by_hash(ot_hash const hash, int delta_torrentcount) {
54 mutex_bucket_unlock(bucket_from_hash(hash), delta_torrentcount); 58 mutex_bucket_unlock(bucket_from_hash(hash), delta_torrentcount);
55} 59}
56 60
57size_t mutex_get_torrent_count(void) { return g_torrent_count; } 61size_t mutex_get_torrent_count(void) { return atomic_load_explicit(&g_torrent_count, memory_order_relaxed); }
58 62
59/* TaskQueue Magic */ 63/* TaskQueue Magic */
60 64
@@ -145,9 +149,13 @@ ot_taskid mutex_workqueue_poptask(ot_tasktype *tasktype) {
145 break; 149 break;
146 } 150 }
147 151
148 /* Wait until the next task is being fed */ 152 /* Wait until the next task is being fed, unless the tracker is on its
149 if (!taskid) 153 way out, in which case the worker is meant to leave rather than wait */
154 if (!taskid) {
155 if (!g_opentracker_running)
156 break;
150 pthread_cond_wait(&tasklist_being_filled, &tasklist_mutex); 157 pthread_cond_wait(&tasklist_being_filled, &tasklist_mutex);
158 }
151 } 159 }
152 160
153 /* Release lock */ 161 /* Release lock */
@@ -271,6 +279,13 @@ void mutex_init(void) {
271 memset(all_torrents, 0, sizeof(all_torrents)); 279 memset(all_torrents, 0, sizeof(all_torrents));
272} 280}
273 281
282/* Let every worker parked on the queue see that the tracker is stopping */
283void mutex_workqueue_wakeall(void) {
284 pthread_mutex_lock(&tasklist_mutex);
285 pthread_cond_broadcast(&tasklist_being_filled);
286 pthread_mutex_unlock(&tasklist_mutex);
287}
288
274void mutex_deinit(void) { 289void mutex_deinit(void) {
275 size_t i; 290 size_t i;
276 for (i = 0; i < OT_BUCKET_COUNT; ++i) 291 for (i = 0; i < OT_BUCKET_COUNT; ++i)