-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTransRegion.hpp
More file actions
142 lines (127 loc) · 3.54 KB
/
TransRegion.hpp
File metadata and controls
142 lines (127 loc) · 3.54 KB
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
136
137
138
139
140
141
142
#ifndef TRANSREGION_HPP
#define TRANSREGION_HPP
#include "FallbackLock.hpp"
#include <stdio.h>
#include <pthread.h>
typedef enum {
RTM_SUCCESS = -1,
RTM_ZERO = 0x0,
RTM_MIN = RTM_ZERO,
RTM_ABORT = 0x1,
RTM_RETRY = 0x2,
RTM_CONFLICT = 0x4,
RTM_OVFLOW = 0x8,
RTM_DEBUGP = 0x10,
RTM_NESTED = 0x20,
RTM_USER = 0x40,
RTM_UNSAFE = 0xff,
RTM_MAX = RTM_UNSAFE
} RTM_Status;
/*
char *RTM_StatusStrings[] = {
"RTM_SUCCESS",
"RTM_ZERO",
"RTM_ABORT",
"RTM_RETRY",
"RTM_CONFLICT",
"RTM_OVERFLOW",
"RTM_DEBUG",
"RTM_NESTED",
"RTM_USER"
"RTM_UNSAFE"
};
*/
#define TX_SUCCESS -1
#define TRACE_PRINT(tLevel, cLevel, msg) \
if ((tLevel) >= (cLevel)) { \
printf((msg)); \
}
int
txBegin()
{
int rv;
__asm__ __volatile__("movl $-1, %%eax\n"
".byte 0xc7, 0xf8, 0, 0, 0, 0\n"
:"=a" (rv) : :);
return rv;
}
void
txEnd()
{
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd5\n");
}
void
txAbort(int s)
{
__asm__ __volatile__(".byte 0xc6, 0xf8, 0xff\n");
}
int
txTest()
{
int rv = 0;
__asm__ __volatile__(".byte 0x0f, 0x01, 0xd6\n"
:"=a" (rv));
}
class TransRegion {
public:
TransRegion(FallbackLock* fLock,
unsigned int& nAcqs,
bool& TxSucc,
unsigned int nRetries = 5,
unsigned int traceLevel = 0) :
fLock_(fLock), nRetries_(nRetries), nAcqs_(nAcqs), TxSucc_(TxSucc),
traceLevel_(traceLevel)
{
for (unsigned int tryCount = 0; tryCount <= nRetries_; ++tryCount) {
int status = txBegin();
if (status == TX_SUCCESS) {
if (txTest()) {
if (!fLock_->isLocked()) {
return;
}
} else {
printf("TxBegin stats ==== %d\n", status);
// Abort the TX, as some other thread is executing the critical
// section in a non-RTM way, i.e. acquired the fallback lock.
TRACE_PRINT(traceLevel_, 1, "Another thread entered the region "
"non transactionally. Aborting...\n")
txAbort(RTM_UNSAFE);
status = RTM_UNSAFE;
}
}
// Atomically increment the abort count.
if (status == RTM_UNSAFE) {
printf("TxUnsafe %d \n", status);
TRACE_PRINT(traceLevel_, 2, "Spinnig till a TX can be started\n")
while (fLock_->isLocked()) {
for (int i = 10000; i > 0; --i);
}
} else if ((status != RTM_RETRY)) {
printf("TxRetry %d \n", status);
TRACE_PRINT(traceLevel_, 2, "Processor does not hint RETRY\n")
tryCount = nRetries_ + 1;
break;
}
}
TRACE_PRINT(traceLevel_, 2, "Acquiring fallback lock\n")
fLock_->lock();
++nAcqs_;
}
~TransRegion() {
if (fLock_->isLocked()) {
TRACE_PRINT(traceLevel_, 2, "Releasing fallback lock\n")
fLock_->unlock();
} else {
txEnd();
}
}
private:
FallbackLock* fLock_;
unsigned int nRetries_;
unsigned int& nAcqs_;
bool& TxSucc_;
unsigned int traceLevel_;
// Private default constructor to prevent illegal initialization
TransRegion();
};
#endif // TRANSREGION_HPP