summaryrefslogtreecommitdiff
path: root/src/lib/lock/compat_mutex_winthreads.c
blob: 151a7b80f770a730fd96180a3a2bf99aeb08b0bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* Copyright (c) 2003-2004, Roger Dingledine
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file compat_mutex_winthreads.c
 *
 * \brief Implement the tor_mutex API using CRITICAL_SECTION.
 **/

#include "orconfig.h"

/* For SRW locks support */
#ifndef WINVER
#error "orconfig.h didn't define WINVER"
#endif
#ifndef _WIN32_WINNT
#error "orconfig.h didn't define _WIN32_WINNT"
#endif
#if WINVER < 0x0600
#error "winver too low"
#endif
#if _WIN32_WINNT < 0x0600
#error "winver too low"
#endif

#include <windows.h>
#include "lib/lock/compat_mutex.h"
#include "lib/err/torerr.h"

void
tor_locking_init(void)
{
}

void
tor_mutex_init(tor_mutex_t *m)
{
  m->type = RECURSIVE;
  m->lock_owner = 0;
  m->lock_count = 0;
  InitializeSRWLock(&m->mutex);
}
void
tor_mutex_init_nonrecursive(tor_mutex_t *m)
{
  m->type = NON_RECURSIVE;
  InitializeSRWLock(&m->mutex);
}

void
tor_mutex_uninit(tor_mutex_t *m)
{
  (void) m;
}

static void
tor_mutex_acquire_recursive(tor_mutex_t *m)
{
  LONG thread_id = GetCurrentThreadId();
  // use InterlockedCompareExchange to perform an atomic read
  LONG lock_owner = InterlockedCompareExchange(&m->lock_owner, 0, 0);
  if (thread_id == lock_owner) {
    ++m->lock_count;
    return;
  }
  AcquireSRWLockExclusive(&m->mutex);
  InterlockedExchange(&m->lock_owner, thread_id);
  m->lock_count = 1;
}

static void
tor_mutex_acquire_nonrecursive(tor_mutex_t *m)
{
  AcquireSRWLockExclusive(&m->mutex);
}

void
tor_mutex_acquire(tor_mutex_t *m)
{
  raw_assert(m);
  if (m->type == NON_RECURSIVE) {
    tor_mutex_acquire_nonrecursive(m);
  } else {
    tor_mutex_acquire_recursive(m);
  }
}

static void
tor_mutex_release_recursive(tor_mutex_t *m)
{
  if (--m->lock_count) {
    return;
  }
  InterlockedExchange(&m->lock_owner, 0);
  ReleaseSRWLockExclusive(&m->mutex);
}

static void
tor_mutex_release_nonrecursive(tor_mutex_t *m)
{
  ReleaseSRWLockExclusive(&m->mutex);
}

void
tor_mutex_release(tor_mutex_t *m)
{
  if (m->type == NON_RECURSIVE) {
    tor_mutex_release_nonrecursive(m);
  } else {
    tor_mutex_release_recursive(m);
  }
}