forked from torch/TH
-
Notifications
You must be signed in to change notification settings - Fork 0
/
THAtomic.c
103 lines (93 loc) · 2.19 KB
/
THAtomic.c
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
#include "THAtomic.h"
/*
Note: I thank Leon Bottou for his useful comments.
Ronan.
*/
#if defined(USE_C11_ATOMICS)
#include <stdatomic.h>
#endif
#if defined(USE_MSC_ATOMICS)
#include <intrin.h>
#endif
#if !defined(USE_MSC_ATOMICS) && !defined(USE_GCC_ATOMICS) && defined(USE_PTHREAD_ATOMICS)
#include <pthread.h>
static pthread_mutex_t ptm = PTHREAD_MUTEX_INITIALIZER;
#endif
void THAtomicSet(int volatile *a, int newvalue)
{
#if defined(USE_C11_ATOMICS)
atomic_store(a, newvalue);
#elif defined(USE_MSC_ATOMICS)
_InterlockedExchange((long*)a, newvalue);
#elif defined(USE_GCC_ATOMICS)
__sync_lock_test_and_set(a, newvalue);
#else
int oldvalue;
do {
oldvalue = *a;
} while (!THAtomicCompareAndSwap(a, oldvalue, newvalue));
#endif
}
int THAtomicGet(int volatile *a)
{
#if defined(USE_C11_ATOMICS)
return atomic_load(a);
#else
int value;
do {
value = *a;
} while (!THAtomicCompareAndSwap(a, value, value));
return value;
#endif
}
int THAtomicAdd(int volatile *a, int value)
{
#if defined(USE_C11_ATOMICS)
return atomic_fetch_add(a, value);
#elif defined(USE_MSC_ATOMICS)
return _InterlockedExchangeAdd((long*)a, value);
#elif defined(USE_GCC_ATOMICS)
return __sync_fetch_and_add(a, value);
#else
int oldvalue;
do {
oldvalue = *a;
} while (!THAtomicCompareAndSwap(a, oldvalue, (oldvalue + value)));
return oldvalue;
#endif
}
void THAtomicIncrementRef(int volatile *a)
{
THAtomicAdd(a, 1);
}
int THAtomicDecrementRef(int volatile *a)
{
return (THAtomicAdd(a, -1) == 1);
}
int THAtomicCompareAndSwap(int volatile *a, int oldvalue, int newvalue)
{
#if defined(USE_C11_ATOMICS)
return atomic_compare_exchange_strong(a, &oldvalue, newvalue);
#elif defined(USE_MSC_ATOMICS)
return (_InterlockedCompareExchange((long*)a, (long)newvalue, (long)oldvalue) == (long)oldvalue);
#elif defined(USE_GCC_ATOMICS)
return __sync_bool_compare_and_swap(a, oldvalue, newvalue);
#elif defined(USE_PTHREAD_ATOMICS)
int ret = 0;
pthread_mutex_lock(&ptm);
if(*a == oldvalue) {
*a = newvalue;
ret = 1;
}
pthread_mutex_unlock(&ptm);
return ret;
#else
#warning THAtomic is not thread safe
if(*a == oldvalue) {
*a = newvalue;
return 1;
}
else
return 0;
#endif
}