tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cm.hpp
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2011
3  * University of Rochester Department of Computer Science
4  * and
5  * Lehigh University Department of Computer Science and Engineering
6  *
7  * License: Modified BSD
8  * Please see the file LICENSE.RSTM for licensing information
9  */
10 
11 #ifndef CM_HPP__
12 #define CM_HPP__
13 
14 #include <stm/config.h>
15 #include <limits.h>
16 #include "stm/txthread.hpp"
17 #include "algs/algs.hpp" // for exp_backoff
18 
19 /**
20  * Timeouts, thresholds, and states
21  */
22 #define TX_ACTIVE 0
23 #define TX_ABORTED 1
24 
25 /**
26  * Define the CM policies that can be plugged into our framework. For the
27  * time being, these only make sense in the context of attacker-wins conflict
28  * management
29  */
30 namespace stm
31 {
32  /**
33  * Backoff CM policy: On abort, perform randomized exponential backoff
34  */
35  struct BackoffCM
36  {
37  static void onAbort(TxThread* tx)
38  {
39  // randomized exponential backoff
40  exp_backoff(tx);
41  }
42  static void onBegin(TxThread*) { }
43  static void onCommit(TxThread*) { }
44  static bool mayKill(TxThread*, uint32_t) { return true; }
45  };
46 
47  /**
48  * HyperAggressive CM policy: don't do backoff, just try to win all the time
49  */
51  {
52  static void onAbort(TxThread*) { }
53  static void onBegin(TxThread*) { }
54  static void onCommit(TxThread*) { }
55  static bool mayKill(TxThread*, uint32_t) { return true; }
56  };
57 
58  /**
59  * Fine-grained CM: we get a timestamp, and use it to decide when to abort
60  * the other thread. This is not exactly an attacker-wins policy anymore
61  *
62  * This is based on a concept from Bobba et al. ISCA 07
63  */
64  struct FCM
65  {
66  static void onAbort(TxThread*) { }
67  static void onCommit(TxThread*) { }
68 
69  /**
70  * On begin, we must get a timestamp. For now, we use a global
71  * counter, which is a bottleneck but ensures uniqueness.
72  */
73  static void onBegin(TxThread* tx)
74  {
75  // acquire timestamp when transaction begins
76  epochs[tx->id-1].val = faiptr(&fcm_timestamp.val);
77  // could use (INT32_MAX & tick())
78  }
79 
80  /**
81  * Permission to kill the other is granted when this transaction's
82  * timestamp is less than the other transaction's timestamp
83  */
84  static bool mayKill(TxThread* tx, uint32_t other)
85  {
86  return (threads[tx->id-1]->alive == TX_ACTIVE)
87  && (epochs[tx->id-1].val < epochs[other].val);
88  }
89  };
90 
91  /**
92  * StrongHourglass CM: a concerned transaction serializes all execution.
93  * The aborted transaction who wishes to enter the hourglass waits until he
94  * can do so
95  */
97  {
98  static const uint32_t ABORT_THRESHOLD = 2;
99 
100  /**
101  * On begin, block if there is a distinguished transaction
102  */
103  static void onBegin(TxThread* tx)
104  {
105  if (!tx->strong_HG)
106  while (fcm_timestamp.val)
108  tx->tmabort(tx);
109  }
110 
111  /**
112  * On abort, get a timestamp if I exceed some threshold
113  */
114  static void onAbort(TxThread* tx)
115  {
116  // if I'm already in the hourglass, just return
117  if (tx->strong_HG) {
118  tx->abort_hist.onHGAbort();
119  return;
120  }
121 
122  // acquire a timestamp if consecutive aborts exceed a threshold
123  if (tx->consec_aborts > ABORT_THRESHOLD) {
124  while (true) {
125  if (bcasptr(&fcm_timestamp.val, 0ul, 1ul)) {
126  tx->strong_HG = true;
127  return;
128  }
129  while (fcm_timestamp.val) { }
130  }
131  }
132  // NB: It would be good to explore what happens if I have a
133  // strong_HG already? Can we count how many times I abort with
134  // strong_HG?
135  }
136 
137  /**
138  * On commit, release my timestamp
139  */
140  static void onCommit(TxThread* tx)
141  {
142  if (tx->strong_HG) {
143  fcm_timestamp.val = 0;
144  tx->strong_HG = false;
145  tx->abort_hist.onHGCommit();
146  }
147  }
148 
149  /**
150  * During the transaction, always abort conflicting transactions
151  */
152  static bool mayKill(TxThread*, uint32_t) { return true; }
153  };
154 
155  /**
156  * Hourglass CM: a concerned transaction serializes all execution
157  */
158  struct HourglassCM
159  {
160  static const uint32_t ABORT_THRESHOLD = 2;
161 
162  /**
163  * On begin, block if there is a distinguished transaction
164  */
165  static void onBegin(TxThread* tx)
166  {
167  if (!tx->strong_HG)
168  while (fcm_timestamp.val)
170  tx->tmabort(tx);
171  }
172 
173  /**
174  * On abort, get a timestamp if I exceed some threshold
175  */
176  static void onAbort(TxThread* tx)
177  {
178  // if I'm already in the hourglass, just return
179  if (tx->strong_HG) {
180  tx->abort_hist.onHGAbort();
181  return;
182  }
183 
184  // acquire a timestamp if consecutive aborts exceed a threshold
185  if (tx->consec_aborts > ABORT_THRESHOLD)
186  if (bcasptr(&fcm_timestamp.val, 0ul, 1ul))
187  tx->strong_HG = true;
188  // NB: as before, some counting opportunities here
189  }
190 
191  /**
192  * On commit, release my timestamp
193  */
194  static void onCommit(TxThread* tx)
195  {
196  if (tx->strong_HG) {
197  fcm_timestamp.val = 0;
198  tx->strong_HG = false;
199  tx->abort_hist.onHGCommit();
200  }
201  }
202 
203  /**
204  * During the transaction, always abort conflicting transactions
205  */
206  static bool mayKill(TxThread*, uint32_t) { return true; }
207  };
208 
209  /**
210  * Hourglass+Backoff CM: a concerned transaction serializes all execution
211  */
213  {
214  static const uint32_t ABORT_THRESHOLD = 2;
215 
216  /**
217  * On begin, block if there is a distinguished transaction
218  */
219  static void onBegin(TxThread* tx)
220  {
221  if (!tx->strong_HG)
222  while (fcm_timestamp.val)
224  tx->tmabort(tx);
225  }
226 
227  /**
228  * On abort, get a timestamp if I exceed some threshold
229  */
230  static void onAbort(TxThread* tx)
231  {
232  // if I'm already in the hourglass, just return
233  if (tx->strong_HG) {
234  tx->abort_hist.onHGAbort();
235  return;
236  }
237 
238  // acquire a timestamp if consecutive aborts exceed a threshold
239  if (tx->consec_aborts > ABORT_THRESHOLD) {
240  if (bcasptr(&fcm_timestamp.val, 0ul, 1ul))
241  tx->strong_HG = true;
242  }
243  else {
244  // randomized exponential backoff
245  exp_backoff(tx);
246  }
247  }
248 
249  /**
250  * On commit, release my timestamp
251  */
252  static void onCommit(TxThread* tx)
253  {
254  if (tx->strong_HG) {
255  fcm_timestamp.val = 0;
256  tx->strong_HG = false;
257  tx->abort_hist.onHGCommit();
258  }
259  }
260 
261  /**
262  * During the transaction, always abort conflicting transactions
263  */
264  static bool mayKill(TxThread*, uint32_t) { return true; }
265  };
266 
267 }
268 
269 #endif // CM_HPP__
Definition: cm.hpp:96
TxThread * threads[MAX_THREADS]
Definition: txthread.cpp:56
bool strong_HG
Definition: txthread.hpp:88
Definition: stm_fraser.c:61
uint32_t id
Definition: txthread.hpp:50
static bool mayKill(TxThread *, uint32_t)
Definition: cm.hpp:206
TM_INLINE void exp_backoff(TxThread *tx)
Definition: algs.hpp:218
static bool mayKill(TxThread *, uint32_t)
Definition: cm.hpp:152
Definition: cm.hpp:64
static NORETURN void(* tmabort)(TxThread *)
Definition: txthread.hpp:139
static bool mayKill(TxThread *tx, uint32_t other)
Definition: cm.hpp:84
static void onCommit(TxThread *tx)
Definition: cm.hpp:194
volatile uintptr_t val
Definition: metadata.hpp:117
pad_word_t fcm_timestamp
Definition: algs.cpp:68
static void onBegin(TxThread *tx)
Definition: cm.hpp:165
static void onAbort(TxThread *)
Definition: cm.hpp:52
static void onCommit(TxThread *)
Definition: cm.hpp:54
pad_word_t epochs[MAX_THREADS]
Definition: algs.cpp:56
void onHGAbort()
Definition: metadata.hpp:236
Definition: cm.hpp:35
static void onCommit(TxThread *)
Definition: cm.hpp:43
static void onBegin(TxThread *tx)
Definition: cm.hpp:219
toxic_t abort_hist
Definition: txthread.hpp:86
static void onCommit(TxThread *tx)
Definition: cm.hpp:140
static const uint32_t ABORT_THRESHOLD
Definition: cm.hpp:98
bool begin_blocker(TxThread *tx)
Definition: irrevocability.cpp:213
stm_tx * tx
Definition: stmskip.cc:245
static void onAbort(TxThread *tx)
Definition: cm.hpp:37
static void onBegin(TxThread *)
Definition: cm.hpp:42
static void onAbort(TxThread *)
Definition: cm.hpp:66
void onHGCommit()
Definition: metadata.hpp:235
static void onCommit(TxThread *)
Definition: cm.hpp:67
static void onBegin(TxThread *tx)
Definition: cm.hpp:103
static void onCommit(TxThread *tx)
Definition: cm.hpp:252
Definition: cm.hpp:158
uint32_t consec_aborts
Definition: txthread.hpp:71
static bool mayKill(TxThread *, uint32_t)
Definition: cm.hpp:55
static bool mayKill(TxThread *, uint32_t)
Definition: cm.hpp:44
Definition: txthread.hpp:47
static void onAbort(TxThread *tx)
Definition: cm.hpp:176
static void onBegin(TxThread *)
Definition: cm.hpp:53
static TM_FASTCALL bool(*volatile tmbegin)(TxThread *)
Definition: txthread.hpp:115
volatile uint32_t alive
Definition: txthread.hpp:75
#define TX_ACTIVE
Definition: cm.hpp:22
Definition: cm.hpp:50
static void onBegin(TxThread *tx)
Definition: cm.hpp:73
Definition: cm.hpp:212
static void onAbort(TxThread *tx)
Definition: cm.hpp:230
static bool mayKill(TxThread *, uint32_t)
Definition: cm.hpp:264
static void onAbort(TxThread *tx)
Definition: cm.hpp:114
static const uint32_t ABORT_THRESHOLD
Definition: cm.hpp:214
static const uint32_t ABORT_THRESHOLD
Definition: cm.hpp:160