tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Scope.h
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 STM_ITM2STM_SCOPE_H
12 #define STM_ITM2STM_SCOPE_H
13 
14 #include <vector> // std::vector, std::pair
15 #include "libitm.h" // _ITM_ stuff
16 #include "Checkpoint.h" // class Checkpoint
17 
18 namespace itm2stm {
19 /// A Scope maintains the data associated with a nested transaction. This
20 /// includes the transaction's checkpoint, the flags that it began with, a flag
21 /// that tells us if it has been aborted (an ABI-required behavior), an address
22 /// range used to register a thrown exception, lists of user-registered onUndo
23 /// and onCommit handlers, and a list of logged values.
24 ///
25 /// The runtime can commit a scope, rollback a scope, and restore the scope's
26 /// checkpoint (which performs a longjmp).
27 class Scope : public Checkpoint /* asm needs this as first superclass */
28 {
29  public:
31 
32  /// Read access to the Scope's id. The id is set during the Scope::enter
33  /// call from a parameter.
35  return id_;
36  }
37 
38  /// Used by the Transaction during a restart, to simplify re-calling
39  /// Scope::enter during Transaction::restart.
40  uint32_t getFlags() const {
41  return flags_;
42  }
43 
44  /// Used by the Transaction's rollback functionality.
45  bool isExceptionBlock() const {
46  return flags_ & pr_exceptionBlock;
47  }
48 
49  /// Read/write accessors for the aborted flag. The write accessor is only
50  /// used by the Transaction during rollback when it finds that it must mark
51  /// the "outermost" scope as aborted, before the outermost scope gets
52  /// completely rolled back. This is an ITM-ABI required behavior.
53  void setAborted(bool val) {
54  aborted_ = val;
55  }
56 
57  bool getAborted() const {
58  return aborted_;
59  }
60 
61  /// Used from the libstm conflict abort handler
62  /// (itm2stm-5.7.cpp:stm::TxThread::tmabort).
64  return owner_;
65  }
66 
67  /// Called every time that a transaction begins (includes outer transactions
68  /// and nested transactions, on their first entry and on every
69  /// restart). After this call the scope must be entirely clean and ready to
70  /// go. We inline this because it is important for performance in a number
71  /// of places.
72  void enter(_ITM_transactionId_t id, uint32_t flags) {
73  id_ = id;
74  flags_ = flags;
75  aborted_ = false;
76  thrown_.reset();
77  }
78 
79  /// Called when a transaction is either aborted or restarted. From the
80  /// scope's perspective there isn't any difference between these two
81  /// operations. We don't really care about rollback performance so this is
82  /// outlined. The return value is a pair indicating a range of addresses
83  /// that should not be rolled back by the library---this corresponds with a
84  /// registered thrown object, but there isn't any reason to expose the
85  /// ThrownObject type externally. If there was no thrown object then the
86  /// returned value will be the pair (NULL, 0).
87  ///
88  /// The stack maintains an undo log in support of the _ITM_L* calls. We need
89  /// to make sure not to clobber the protected stack during rollback, hence
90  /// the protected_stack address parameter.
91  std::pair<void**, size_t>& rollback(void** protected_stack);
92 
93  /// Called to commit a scope. Inlined because we care about commit
94  /// performance.
95  void commit() {
96  for (CommitList::iterator i = do_on_commit_.begin(),
97  e = do_on_commit_.end(); i != e; ++i)
98  i->eval();
99  do_on_rollback_.clear();
100  undo_on_rollback_.clear();
101  // don't reset thrown, it's reset by Scope::enter.
102  }
103 
104  /// Self explanatory, precondition thrown_.address == NULL.
105  void setThrownObject(void** addr, size_t length);
106 
107  // Resets the thrown object.
108  void clearThrownObject();
109 
110  /// This is called from the logging functions (_ITM_L*) which do all of the
111  /// heavy lifting. All the scope has to do is save the data being passed.
112  void log(void** addr, void* value, size_t bytes) {
113  undo_on_rollback_.push_back(LoggedWord(addr, value, bytes));
114  }
115 
116  /// Registration handler is trivial so we inline it.
118  do_on_commit_.push_back(make_callback(f, arg));
119  }
120 
121  /// Registration handler is trivial so we inline it.
123  do_on_rollback_.push_back(make_callback(f, arg));
124  }
125 
126  private:
127  /// The ITM interface is designed to register thrown objects to support
128  /// abort-on-throw semantics. This pair represent such a thrown-object
129  /// address range.
130  struct ThrownObject : public std::pair<void**, size_t> {
131  void** begin() const;
132  void** end() const;
133  void reset() {
134  first = NULL;
135  second = 0;
136  }
137  };
138 
139  /// ITM allows users to register onCommit and onAbort handlers to execute
140  /// user code during those events. The ITM interface defines the callbacks
141  /// with independent type name (userCommitAction and userAbortAction), even
142  /// though they are structurally equivalent (void (*)(void*)). We don't want
143  /// to rely on the structural equivalence, so we use this templated struct
144  /// to store and evaluate both types of callbacks.
145  template <typename F>
146  struct Callback {
148  void* arg_;
149 
150  Callback(F f, void* arg) : function_(f), arg_(arg) {
151  }
152 
153  void eval() const {
154  function_(arg_);
155  }
156  };
157 
158  /// Standard metaprogramming type-dispatcher picks up the necessary type
159  /// from the parameter (see std::make_pair);
160  template <typename F>
161  static Callback<F> make_callback(F f, void* arg) {
162  return Callback<F>(f, arg);
163  }
164 
165  /// ITM will sometimes want to log a thread-local value, but instead of
166  /// using stack-space and well-known control flow, it will ask the library
167  /// to perform the logging on its behalf. We could simply use existing
168  /// transactional metadata structures to log them, but these logged values
169  /// do not need conflict detection, and we don't expect them to be
170  /// common. For this reason, we do simple logging in the shim, and undo the
171  /// logged values during rollback.
172  ///
173  /// We log in word-sized maximum chunks. *These are not assumed to have any
174  /// specific alignment.*
175  struct LoggedWord {
176  private:
177  void** address_;
178  void* value_;
179  size_t bytes_;
180 
181  /// The clip routine is used to protect against undoing to both thrown
182  /// objects and the protected stack. We aren't capable of undoing to a
183  /// discontinuous range (i.e., if the logged value is larger than the
184  /// range, and the range is completely contained withing the logged
185  /// address range, and there is some "left-over" space on each side).
186  ///
187  /// The range is [lower, upper)
188  void clip(void** lower, void** upper);
189 
190  public:
191  LoggedWord(void** addr, void* val, size_t bytes)
192  : address_(addr), value_(val), bytes_(bytes) {
193  }
194 
195  void** begin() const;
196  void** end() const;
197  void undo(ThrownObject&, void** protected_stack_lower_bound);
198  };
199 
200  /// We expect these features to be used uncommonly, thus we're happy just to
201  /// store them as vectors. Should this become a bottleneck, particularly
202  /// calls to "clear" them, we could go with something more optimized like an
203  /// stm::MiniVector.
204  typedef std::vector<Callback<_ITM_userUndoFunction> > RollbackList;
205  typedef std::vector<Callback<_ITM_userCommitFunction> > CommitList;
206  typedef std::vector<LoggedWord> UndoList;
207 
208  bool aborted_;
209  uint32_t flags_;
215  _ITM_transaction& owner_; // this is needed to handle conflict
216  // aborts---see
217  // itm2stm-5.8.cpp:stm::TxThread::tmabort
218 };
219 } // namespace itm2stm
220 
221 #endif // STM_ITM2STM_SCOPE_H
void setAborted(bool val)
Definition: Scope.h:53
ThrownObject thrown_
Definition: Scope.h:211
void setThrownObject(void **addr, size_t length)
Self explanatory, precondition thrown_.address == NULL.
Definition: Scope.cpp:131
void ** address_
Definition: Scope.h:177
void enter(_ITM_transactionId_t id, uint32_t flags)
Definition: Scope.h:72
uint32_t _ITM_transactionId_t
Definition: libitm.h:99
void ** end() const
Definition: Scope.cpp:24
void undo(ThrownObject &, void **protected_stack_lower_bound)
Definition: Scope.cpp:77
F function_
Definition: Scope.h:147
Definition: Scope.h:27
void ** begin() const
Definition: Scope.cpp:31
_ITM_transactionId_t getId() const
Definition: Scope.h:34
bool aborted_
Definition: Scope.h:208
static Callback< F > make_callback(F f, void *arg)
Definition: Scope.h:161
void reset()
Definition: Scope.h:133
uint32_t getFlags() const
Definition: Scope.h:40
void clip(void **lower, void **upper)
Definition: Scope.cpp:43
Definition: intruder.c:122
std::vector< LoggedWord > UndoList
Definition: Scope.h:206
bool isExceptionBlock() const
Used by the Transaction's rollback functionality.
Definition: Scope.h:45
Definition: Scope.h:130
struct _ITM_transaction _ITM_transaction
Definition: libitm.h:98
void clearThrownObject()
Definition: Scope.cpp:139
Definition: Scope.h:175
void(* _ITM_userUndoFunction)(void *)
Definition: libitm.h:100
Definition: Scope.h:146
Scope(_ITM_transaction &)
Definition: Scope.cpp:92
void ** begin() const
Definition: Scope.cpp:19
size_t bytes_
Definition: Scope.h:179
CommitList do_on_commit_
Definition: Scope.h:214
_ITM_transactionId_t id_
Definition: Scope.h:210
void commit()
Definition: Scope.h:95
uint32_t flags_
Definition: Scope.h:209
void registerOnCommit(_ITM_userCommitFunction f, void *arg)
Registration handler is trivial so we inline it.
Definition: Scope.h:117
void eval() const
Definition: Scope.h:153
std::vector< Callback< _ITM_userUndoFunction > > RollbackList
Definition: Scope.h:204
RollbackList do_on_rollback_
Definition: Scope.h:212
LoggedWord(void **addr, void *val, size_t bytes)
Definition: Scope.h:191
UndoList undo_on_rollback_
Definition: Scope.h:213
Definition: libitm.h:77
void * arg_
Definition: Scope.h:148
void(* _ITM_userCommitFunction)(void *)
Definition: libitm.h:101
_ITM_transaction & owner_
Definition: Scope.h:215
void ** end() const
Definition: Scope.cpp:36
std::vector< Callback< _ITM_userCommitFunction > > CommitList
Definition: Scope.h:205
void log(void **addr, void *value, size_t bytes)
Definition: Scope.h:112
void registerOnAbort(_ITM_userUndoFunction f, void *arg)
Registration handler is trivial so we inline it.
Definition: Scope.h:122
void * value_
Definition: Scope.h:178
Callback(F f, void *arg)
Definition: Scope.h:150
bool getAborted() const
Definition: Scope.h:57
Definition: Checkpoint.h:18
std::pair< void **, size_t > & rollback(void **protected_stack)
Definition: Scope.cpp:108
_ITM_transaction & getOwner() const
Definition: Scope.h:63