summaryrefslogtreecommitdiff
path: root/src/ot_mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ot_mutex.c')
-rw-r--r--src/ot_mutex.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/ot_mutex.c b/src/ot_mutex.c
new file mode 100644
index 0000000..884b74c
--- /dev/null
+++ b/src/ot_mutex.c
@@ -0,0 +1,70 @@
1/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
2 It is considered beerware. Prost. Skol. Cheers or whatever. */
3
4/* System */
5#include <arpa/inet.h>
6#include <pthread.h>
7#include <stdatomic.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <string.h>
12#include <sys/uio.h>
13
14
15/* Opentracker */
16#include "ot_iovec.h"
17#include "ot_mutex.h"
18#include "ot_stats.h"
19#include "trackerlogic.h"
20
21/* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */
22#define MTX_DBG(STRING)
23
24/* Our global all torrents list */
25static ot_vector all_torrents[OT_BUCKET_COUNT];
26static pthread_mutex_t bucket_mutex[OT_BUCKET_COUNT];
27/* Every bucket's unlock adjusts this, and a bucket lock only keeps other
28 threads out of that one bucket, so the counter needs its own protection */
29static _Atomic size_t g_torrent_count;
30
31ot_vector *mutex_bucket_lock(int bucket) {
32 pthread_mutex_lock(bucket_mutex + bucket);
33 return all_torrents + bucket;
34}
35
36/* Torrents are spread over buckets by the first four bytes of their info_hash,
37 which may sit at any alignment, hence the memcpy */
38static int bucket_from_hash(ot_hash const hash) {
39 uint32_t bucket;
40 memcpy(&bucket, hash, sizeof(bucket));
41 return ntohl(bucket) >> OT_BUCKET_COUNT_SHIFT;
42}
43
44ot_vector *mutex_bucket_lock_by_hash(ot_hash const hash) { return mutex_bucket_lock(bucket_from_hash(hash)); }
45
46void mutex_bucket_unlock(int bucket, int delta_torrentcount) {
47 pthread_mutex_unlock(bucket_mutex + bucket);
48 if (delta_torrentcount)
49 atomic_fetch_add_explicit(&g_torrent_count, (size_t)delta_torrentcount, memory_order_relaxed);
50}
51
52void mutex_bucket_unlock_by_hash(ot_hash const hash, int delta_torrentcount) {
53 mutex_bucket_unlock(bucket_from_hash(hash), delta_torrentcount);
54}
55
56size_t mutex_get_torrent_count(void) { return atomic_load_explicit(&g_torrent_count, memory_order_relaxed); }
57
58void mutex_init(void) {
59 size_t i;
60 for (i = 0; i < OT_BUCKET_COUNT; ++i)
61 pthread_mutex_init(bucket_mutex + i, NULL);
62 memset(all_torrents, 0, sizeof(all_torrents));
63}
64
65void mutex_deinit(void) {
66 size_t i;
67 for (i = 0; i < OT_BUCKET_COUNT; ++i)
68 pthread_mutex_destroy(bucket_mutex + i);
69 memset(all_torrents, 0, sizeof(all_torrents));
70}