tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Transaction.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_TRANSACTION_H
12 #define STM_ITM2STM_TRANSACTION_H
13 
14 #include "libitm.h"
15 #include "Scope.h"
16 
17 namespace stm {
18 struct TxThread;
19 } // namespace stm
20 
21 /// This needs to be in the global namespace because that's how it's declared in
22 /// Intel's libitm.h header. We forward many of the ITM ABI calls to inlined
23 /// _ITM_transaction member functions. We treat the instance variables as
24 /// private, even though we can't use a private modifier because of the way
25 /// _ITM_transaction is declared.
26 ///
27 /// The implementation of these functions is distributed throughout the
28 /// Transaction.cpp and libitm-*.cpp files, so that we don't have to have all of
29 /// the inline implementations in this header---most of them are only used in
30 /// the single libitm file that is relevent to them. Anything that we need
31 /// inlined in more than one source file is defined here.
32 ///
33 /// We use gcc's "fastcall" calling convention for those things that we don't
34 /// inline here but are used across multiple source files (there aren't that
35 /// many of them).
36 struct _ITM_transaction {
37 
38  /// Right now we manage scopes as a linked-list stack implementation. There
39  /// are obviously alternatives to this, like a vector (or stm::MiniVector),
40  /// but this seemed easiest for our initial implementation.
41  ///
42  /// We use a sort of "intrusive" list node by inheriting from the Scope type
43  /// and adding the "next" pointer. We can do this because this isn't a
44  /// generic list solution, so we know what the Scope constructor looks like.
45  struct Node : public itm2stm::Scope {
46  Node* next_;
47  Node(_ITM_transaction&);
48  ~Node();
49  };
50 
51  stm::TxThread& thread_handle_; // the pointer to the stm library descriptor
52  Node* outer_scope_; // we need fast access to the outer scope
53  Node* scopes_; // the scope stack
54  Node* free_scopes_; // a freelist for scope nodes
55  _ITM_transactionId_t next_tid_; // implements the ABI unique id requirement
56 
57  // The _ITM_abortReason is an enum that doesn't have an enumeration for
58  // 0. We want to be able to detect that there wasn't a previous abort
59  // reason, but there's no _ITM_abortReason we can use for that. This union
60  // allows us to use 0 (false) to indicate that there was no previous abort,
61  // without having type problems (0 is not a valie _ITM_abortReason). This
62  // saves us a word of space, and shouldn't be too complicated to maintain
63  // doing forwards.
64  union {
65  _ITM_abortReason prev_abort_reason_;
66  int32_t prev_abort_;
67  };
68 
69  /// Constructor needs a reference to the stm library descriptor for this
70  /// thread.
73 
74 
75  /// The innermost active scope. This is primarily used internally, and is
76  /// used so that we can change the stack implementation as painlessly as
77  /// possible.
78  inline Node* inner() const {
79  return scopes_;
80  }
81 
82  /// The thread handle for RSTM. Used frequently in the various barrier
83  /// (read/write/log) code.
84  inline stm::TxThread& handle() const {
85  return thread_handle_;
86  }
87 
88  /// Perform whatever actions are required to undo the effects of the inner
89  /// scope. Supports all of the various ways a transaction can abort (cancel,
90  /// retry, conflict abort). We need a stack address that represents the
91  /// lower bound of the protected stack region, so that an undo-log TM
92  /// doesn't clobber any part of the stack that we're going to need before we
93  /// \code{restart} or \code{cancel} the scope.
94  void rollback(void** protected_stack_lower_bound);
95 
96  /// Performs whatever actions are required to commit a scope. Unlike
97  /// rollback, the caller doesn't need to leave the scope---it's done
98  /// internally. We need a stack address that represents the lower bound of
99  /// the protected stack region so that a redo-log TM doesn't clobber any
100  /// part of the stack that we need to complete the ABI call.
101  void commit(void** protected_stack_lower_bound);
102 
103  /// Performs whatever actions are required to commit a scope, but returning
104  /// "false" if the commit fails rather than doing a non-local control
105  /// transfer. Like "commit" the caller does not need to leave the scope. We
106  /// need a stack address that represents the lower bound of the protected
107  /// stack region so that a redo-log TM doesn't clobber any part of the stack
108  /// that we need.
109  bool tryCommit(void** protected_stack_lower_bound);
110 
111  /// This is a bit of a confusing call as described in the ABI. It seems to
112  /// mean that we're supposed to just pop scopes, without rolling back or
113  /// checking for conflicts, until we find the correct transaction ID. We're
114  /// not sure if we need to protect the stack here.
115  void commitToId(_ITM_transactionId_t);
116 
117  /// This is defined for the make "fake_begin" target, and generates an asm
118  /// example that helps us implement the _ITM_beginTransaction asm file.
119 #ifdef FAKE_ITM_BEGIN_TRANSACTION
120 
121  /// Used exclusively in the _ITM_beginTransaction.S barrier to get a
122  /// checkpoint (scope). Generally this will just pull a node off of the
123  /// free list, but it may need to allocate a new scope.
124  ///
125  /// Note that this doesn't actually get called directly, it is just used so
126  /// that we can get an idea of the code required to inline this (see
127  /// itm2stm-5.7.cpp::_FAKE_beginTransaction).
128  Node* getScope() __attribute__((always_inline));
129 
130 #endif // FAKE_ITM_BEGIN_TRANSACTION
131 
132  /// Perform whatever actions are necessary to enter a scope (the scope's
133  /// checkpoint has already been initialized before this call). Returns the
134  /// requested behavior _ITM_action, either run instrumented or run
135  /// uninstrumented---the caller needs to add the restoreLiveVariables or
136  /// saveLiveVariables as necessary.
137  ///
138  /// We give it an explicit asm label so that we can use it in our
139  /// _ITM_beginTransaction.S implementation without relying on a particular
140  /// C++ name-mangling implementation.
141  uint32_t enter(Node* const scope, const uint32_t flags)
142  asm("_stm_itm2stm_transaction_enter") GCC_FASTCALL;
143 
144  /// Reentering a scope on restart is slightly different than entering a
145  /// scope for the first time. This handles that difference.
146  uint32_t reenter(Node* const scope);
147 
148  /// We need to be able to "new" nodes from asm in _ITM_beginTransaction, but
149  /// we can't give a constructor an asm label (it appears to be an
150  /// undocumented restriction), so we use this as a stand-in. The Node
151  /// constructor takes an _ITM_transaction& so we use an _ITM_transaction
152  /// member function to get the "this" pointer automatically. We could use a
153  /// static with an explicit _ITM_transaction& parameter as well.
154  ///
155  /// As with enter we provide an asm label that is independent of the C++
156  /// name-mangler---in this case the entire purpose of this function /is/
157  /// this label.
158  ///
159  /// Defined in itm2stm-5.7.cpp
160  Node* NewNode() asm("_stm_itm2stm_transaction_new_node");
161 
162  /// Leaves the inner scope by popping the scope off the scopes stack.
163  /// Returns the popped scope so that it can be "restored" by cancel or
164  /// restart. The scope should either be rolled back or committed before this
165  /// call. Leave reclaims the scope (though it is still safe to use... it's
166  /// just on the free list for the next call to getScope).
167  ///
168  /// This needs to be fast for the commit code, and it's also used in the
169  /// abort path, so we implement it in libitm-5.9.cpp so it can get inlined
170  /// there (we're not super-concerned about the abort performance).
171  ///
172  /// We use the GCC fastcall calling convention so that it's as efficient as
173  /// possible in the abort path for x86.
174  GCC_FASTCALL Node* leave() __attribute__((used));
175 
176  /// Corresponds to aborting a scope and continuing execution outside of the
177  /// scope---this is the standard C++ cancel mechanism. This calls rollback
178  /// internally, thus we need a stack address to serve as the protected stack
179  /// lower bound.
180  void cancel(void** protected_stack_lower_bound) NORETURN;
181 
182  /// Corresponds to aborting and retrying a scope. Implemented here by
183  /// rolling back and leaving (popping) the scope, and then re-executing the
184  /// enter functionality, which puts the scope back on the scopes stack. This
185  /// calls rollback internally, thus we need a stack address to serve as the
186  /// protected stack lower bound.
187  ///
188  /// Inlined in libitm-5.8, and marked as used for tmabort in libitm-5.1,5.
189  void restart(void** protected_stack_lower_bound) NORETURN
190  __attribute__((used));
191 
192  /// Implements the abort logic layed out in the ABI specification. Abort is
193  /// implemented in terms of "rollback," "leave," "cancel," and "restart."
194  /// This serves as one of the initial entry point to rollback and thus we
195  /// need a stack address to serve as the protected stack lower bound.
196  void abort(_ITM_abortReason why, void** protected_stack_lower_bound)
197  NORETURN;
198 
199  /// Wraps the logic that checks if the library is irrevocable. Used in both
200  /// 5.4 and 5.7, but implemented in 5.7 because we'd like to inine it there.
201  GCC_FASTCALL bool libraryIsInevitable() const;
202 
203  /// These basically just forward to the correct scopes. Defined in
204  /// itm2stm-5.17.cpp, where they are used.
205  void registerOnAbort(_ITM_userUndoFunction, void* arg);
206  void registerOnCommit(_ITM_userCommitFunction, _ITM_transactionId_t, void*
207  arg);
208 };
209 
210 #endif // STM_ITM2STM_TRANSACTION_H
static TM_CALLABLE bool_t cancel(TM_ARGDECL MAP_T *tablePtr, MAP_T *customerTablePtr, long customerId, long id, reservation_type_t type)
Definition: manager.c:737
Definition: stm_fraser.c:61
uint32_t _ITM_transactionId_t
Definition: libitm.h:99
Definition: Scope.h:27
Definition: intruder.c:122
struct _ITM_transaction _ITM_transaction
Definition: libitm.h:98
class simple_queue __attribute__
void(* _ITM_userUndoFunction)(void *)
Definition: libitm.h:100
TM_INLINE void commit(TxThread *tx)
Definition: library.hpp:104
void(* _ITM_userCommitFunction)(void *)
Definition: libitm.h:101
Definition: txthread.hpp:47
void restart()
Definition: txthread.cpp:189
#define GCC_FASTCALL
Definition: platform.hpp:70
_ITM_abortReason
Definition: libitm.h:43
#define NORETURN
Definition: platform.hpp:47