-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutex.h
135 lines (117 loc) · 3.25 KB
/
mutex.h
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#ifndef _BR_MUTEX_LOCKER_H_
#define _BR_MUTEX_LOCKER_H_
#if defined(__GNUC__) || defined(__GNUG__)
#include <time.h>
#define __br_compare_and_swap(x, o, n) __sync_val_compare_and_swap(x, o, n)
#define __br_fetch_and_add(x, v) __sync_fetch_and_add(x, v)
#define __br_fetch_and_sub(x, v) __sync_fetch_and_sub(x, v)
#define __br_set(x,v) __sync_lock_test_and_set(x, v)
#elif defined(_MSC_VER)
#include <windows.h>
#include <time.h>
#define __br_compare_and_swap(x, o, n) InterlockedCompareExchange(x, n, o)
#define __br_fetch_and_add(x, v) InterlockedExchangeAdd(x, v)
#define __br_fetch_and_sub(x, v) InterlockedExchangeAdd(x, -v)
#define __br_set(x,v) InterlockedExchange(x, v)
#endif
static void msleep(int ms)
{
#ifdef WIN32
Sleep(ms);
#else
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
}
struct mutex {
volatile long sem;
volatile long askwrite;
};
static void init_mutex(struct mutex* m)
{
m->sem = 0;
m->askwrite = 0;
}
static void lock_for_read(struct mutex* m)
{
while (1) {
if (m->askwrite) { // the big brother is looking for it, stand by
msleep(1);
} else if (__br_fetch_and_add(&m->sem, 2) <= -1) { // big brother is enjoying
__br_fetch_and_sub(&m->sem, 2); // sorry, I'm not mean it, step back
msleep(1);
} else { // we can share it now
break;
}
};
}
static void lock_for_write(struct mutex* m)
{
while (__br_compare_and_swap(&m->sem, 0, -1) != 0) { //someone taking my toy
m->askwrite = 1; // I need the toy right now!!!
msleep(1); // wait
}
m->askwrite = 0; // your buddies can competing for it now
}
static void lock(struct mutex* m)
{
while (__br_compare_and_swap(&m->sem, 0, -1) != 0) { //someone taking my toy
m->askwrite = 1; // I need the toy right now!!!
msleep(1); // wait
}
m->askwrite = 0; // your buddies can competing for it now
}
static void unlock_for_read(struct mutex* m)
{
__br_fetch_and_sub(&m->sem, 2);
}
static void unlock_for_write(struct mutex* m)
{
__br_fetch_and_add(&m->sem, 1);
}
static void unlock(struct mutex* m)
{
__br_fetch_and_add(&m->sem, 1);
}
struct condition_variable
{
volatile long count;
volatile long signal;
};
static void init_condition_variable(struct condition_variable* cond)
{
cond->count = 0;;
cond->signal = 0;
}
static void destory_condition_variable(struct condition_variable* cond)
{
while (cond->count > 0) {
__br_fetch_and_add(&cond->signal, 1);
}
}
static int wait(struct condition_variable* cond, unsigned long timeout_ms)
{
int ret = 0;
__br_fetch_and_add(&cond->count, 1);
clock_t start = clock();
while (__br_fetch_and_sub(&cond->signal, 1) <= 0) {
__br_fetch_and_add(&cond->signal, 1);
clock_t now = clock();
if ((unsigned long)((now - start) * 1000 / CLOCKS_PER_SEC) > timeout_ms) {
ret = 1;
break;
}
msleep(1);
}
__br_fetch_and_sub(&cond->count, 1);
return ret;
}
static void notify_one(struct condition_variable* cond)
{
__br_fetch_and_add(&cond->signal, 1);
}
static void notify_all(struct condition_variable* cond)
{
__br_set(&cond->signal, cond->count);
}
#endif