libfoedus-core
FOEDUS Core Library
sysxct_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
18 #ifndef FOEDUS_XCT_SYSXCT_IMPL_HPP_
19 #define FOEDUS_XCT_SYSXCT_IMPL_HPP_
20 
21 #include <algorithm>
22 #include <iosfwd>
23 
24 #include "foedus/assert_nd.hpp"
25 #include "foedus/compiler.hpp"
26 #include "foedus/error_code.hpp"
27 #include "foedus/fwd.hpp"
28 #include "foedus/storage/page.hpp"
30 #include "foedus/thread/fwd.hpp"
31 #include "foedus/xct/fwd.hpp"
33 #include "foedus/xct/xct_id.hpp"
35 
36 namespace foedus {
37 namespace xct {
38 
62 // TASK(Hideaki) this comparator probably has a common use. move to somewhere.
64  return to_universal_lock_id(page_id.get_numa_node(), page_id.get_offset(), addr);
65 }
67  bool operator()(storage::Page* p1, storage::Page* p2) const {
68  auto id1 = to_universal_lock_id(p1->get_volatile_page_id(), reinterpret_cast<uintptr_t>(p1));
69  auto id2 = to_universal_lock_id(p2->get_volatile_page_id(), reinterpret_cast<uintptr_t>(p2));
70  return id1 < id2;
71  }
72 };
73 
86 
91  uintptr_t lock_;
92 
93  // No "preferred"/"taken" mode because system transactions always take W-locks, record or page.
94 
99 
102 
108 
109  void clear() {
110  universal_lock_id_ = 0;
111  lock_ = kNullUniversalLockId;
112  mcs_block_ = 0;
113  page_lock_ = false;
114  used_in_this_run_ = false;
115  }
116 
117  void set(UniversalLockId lock_id, uintptr_t lock, bool page_lock) {
118  universal_lock_id_ = lock_id;
119  lock_ = lock;
120  mcs_block_ = 0;
121  page_lock_ = page_lock;
122  used_in_this_run_ = true;
123  }
124 
126  ASSERT_ND(!page_lock_);
127  return reinterpret_cast<RwLockableXctId*>(lock_);
128  }
130  ASSERT_ND(page_lock_);
131  return reinterpret_cast<storage::Page*>(lock_);
132  }
133 
134  bool is_locked() const { return mcs_block_ != 0; }
135 
136  bool operator<(const SysxctLockEntry& rhs) const {
137  return universal_lock_id_ < rhs.universal_lock_id_;
138  }
139 
140  friend std::ostream& operator<<(std::ostream& o, const SysxctLockEntry& v);
141 
143  struct LessThan {
144  bool operator()(UniversalLockId lhs, const SysxctLockEntry& rhs) const {
145  return lhs < rhs.universal_lock_id_;
146  }
147  bool operator()(const SysxctLockEntry& lhs, UniversalLockId rhs) const {
148  return lhs.universal_lock_id_ < rhs;
149  }
150  };
151 };
152 
167  public:
168  friend struct TestIsTryRequired; // For unit test. A bit of whitebox test involved.
169 
170  enum Constants {
176  kMaxSysxctLocks = 1 << 10,
177  };
178 
181 
182  // No copy
183  SysxctLockList(const SysxctLockList& other) = delete;
184  SysxctLockList& operator=(const SysxctLockList& other) = delete;
185 
186  void init() {
187  clear_no_assert(kNullUniversalLockId);
188  }
189 
193  void clear_entries(UniversalLockId enclosing_max_lock_id) {
194  ASSERT_ND(last_locked_entry_ == kLockListPositionInvalid);
195  assert_sorted();
196  clear_no_assert(enclosing_max_lock_id);
197  }
198 
203  void compress_entries(UniversalLockId enclosing_max_lock_id);
204 
212 
219  template<typename MCS_ADAPTOR>
221  MCS_ADAPTOR mcs_adaptor,
223  RwLockableXctId* lock) {
224  uintptr_t lock_addr = reinterpret_cast<uintptr_t>(lock);
225  return request_lock_general(mcs_adaptor, page_id, lock_addr, false);
226  }
227 
229  template<typename MCS_ADAPTOR>
231  MCS_ADAPTOR mcs_adaptor,
233  uint32_t lock_count,
234  RwLockableXctId** locks) {
235  uintptr_t* lock_addr = reinterpret_cast<uintptr_t*>(locks);
236  return batch_request_locks_general(mcs_adaptor, page_id, lock_count, lock_addr, false);
237  }
238 
240  template<typename MCS_ADAPTOR>
241  ErrorCode request_page_lock(MCS_ADAPTOR mcs_adaptor, storage::Page* page) {
242  uintptr_t lock_addr = reinterpret_cast<uintptr_t>(page);
243  return request_lock_general(mcs_adaptor, page->get_volatile_page_id(), lock_addr, true);
244  }
245 
251  template<typename MCS_ADAPTOR>
253  MCS_ADAPTOR mcs_adaptor,
254  uint32_t lock_count,
255  storage::Page** pages) {
256  std::sort(pages, pages + lock_count, PageComparator());
257  for (uint32_t i = 0; i < lock_count; ++i) {
258  CHECK_ERROR_CODE(request_page_lock(mcs_adaptor, pages[i]));
259  }
260  return kErrorCodeOk;
261  }
262 
267  template<typename MCS_ADAPTOR>
268  void release_all_locks(MCS_ADAPTOR mcs_adaptor);
269 
276  uintptr_t lock_addr,
277  bool page_lock);
278 
289  uint32_t lock_count,
290  uintptr_t* lock_addr,
291  bool page_lock);
292 
293  const SysxctLockEntry* get_array() const { return array_; }
294  SysxctLockEntry* get_array() { return array_; }
297  return array_ + pos;
298  }
301  return array_ + pos;
302  }
303  uint32_t get_capacity() const { return kMaxSysxctLocks; }
305  bool is_full() const { return last_active_entry_ == kMaxSysxctLocks; }
306  LockListPosition get_last_active_entry() const { return last_active_entry_; }
308  return pos != kLockListPositionInvalid && pos <= last_active_entry_;
309  }
310  bool is_empty() const { return last_active_entry_ == kLockListPositionInvalid; }
311 
312  friend std::ostream& operator<<(std::ostream& o, const SysxctLockList& v);
313  void assert_sorted() const ALWAYS_INLINE;
314  void assert_sorted_impl() const;
315 
316  SysxctLockEntry* begin() { return array_ + 1U; }
317  SysxctLockEntry* end() { return array_ + 1U + last_active_entry_; }
318  const SysxctLockEntry* cbegin() const { return array_ + 1U; }
319  const SysxctLockEntry* cend() const { return array_ + 1U + last_active_entry_; }
321  ASSERT_ND(entry > array_);
322  LockListPosition pos = entry - array_;
324  return pos;
325  }
326 
331  LockListPosition get_last_locked_entry() const { return last_locked_entry_; }
334  return calculate_last_locked_entry_from(last_active_entry_);
335  }
338  for (LockListPosition pos = from; pos > kLockListPositionInvalid; --pos) {
339  if (array_[pos].is_locked()) {
340  return pos;
341  }
342  }
344  }
346 #ifndef NDEBUG
348  ASSERT_ND(correct == last_locked_entry_);
349 #endif // NDEBUG
350  }
351 
352  UniversalLockId get_enclosing_max_lock_id() const { return enclosing_max_lock_id_; }
355  const SysxctLockEntry* entry = get_entry(pos);
356  // If the enclosing thread took a lock after this, we must be careful.
357  if (entry->universal_lock_id_ <= enclosing_max_lock_id_) {
358  return true;
359  }
360 
361  // If this list contains an already-taken lock after this, we must be careful.
362  if (pos <= last_locked_entry_) {
363  return true;
364  }
365 
366  return false;
367  }
368 
369  private:
374  LockListPosition last_active_entry_;
379  LockListPosition last_locked_entry_;
380 
388  UniversalLockId enclosing_max_lock_id_;
389 
396 
397  void clear_no_assert(UniversalLockId enclosing_max_lock_id) {
398  last_locked_entry_ = kLockListPositionInvalid;
399  last_active_entry_ = kLockListPositionInvalid;
400  enclosing_max_lock_id_ = enclosing_max_lock_id;
402  }
403 
404  LockListPosition issue_new_position() {
406  ++last_active_entry_;
407  ASSERT_ND(last_active_entry_ < get_capacity());
408  return last_active_entry_;
409  }
410 
412  template<typename MCS_ADAPTOR>
413  ErrorCode try_or_acquire_multiple_locks(
414  MCS_ADAPTOR mcs_adaptor,
415  LockListPosition from_pos,
416  UniversalLockId last_lock_id,
417  bool mandatory_locks);
418 
419  template<typename MCS_ADAPTOR>
420  ErrorCode request_lock_general(
421  MCS_ADAPTOR mcs_adaptor,
422  storage::VolatilePagePointer page_id,
423  uintptr_t lock,
424  bool page_lock) {
425  // Just reuse the batched version. Shouldn't have any significant overhead.
426  // Using the same codepath is better also for testing/robustness. Not just I'm lazy!
427  return batch_request_locks_general(mcs_adaptor, page_id, 1U, &lock, page_lock);
428  }
429 
430  template<typename MCS_ADAPTOR>
431  ErrorCode batch_request_locks_general(
432  MCS_ADAPTOR mcs_adaptor,
433  storage::VolatilePagePointer page_id,
434  uint32_t lock_count,
435  uintptr_t* locks,
436  bool page_lock);
437 };
438 
452  bool running_sysxct_; // +1 -> 1
453  char pad1_[7]; // +7 -> 8
454 
456  thread::Thread* thread_; // +8 -> 16
457  char pad2_[48]; // +48 -> 64
458 
461 
462  void init(thread::Thread* enclosing_thread) {
463  ASSERT_ND(enclosing_thread);
464  running_sysxct_ = false;
465  thread_ = enclosing_thread;
466  lock_list_.init();
467  }
468 
469  friend std::ostream& operator<<(std::ostream& o, const SysxctWorkspace& v);
470 };
471 
495 template<typename MCS_ADAPTOR, typename ENCLOSURE_RELEASE_ALL_LOCKS_FUNCTOR>
497  SysxctFunctor* functor,
498  MCS_ADAPTOR mcs_adaptor,
499  uint32_t max_retries,
500  SysxctWorkspace* workspace,
501  UniversalLockId enclosing_max_lock_id,
502  ENCLOSURE_RELEASE_ALL_LOCKS_FUNCTOR enclosure_release_all_locks_functor) {
503  if (UNLIKELY(workspace->running_sysxct_)) {
504  // so far each thread can convey only one system transaction.
505  // this is 1) to reuse SysxctWorkspace, and 2) to avoid deadlocks.
507  }
508 
509  workspace->running_sysxct_ = true;
510  uint32_t cur_retries = 0;
511  auto* lock_list = &(workspace->lock_list_);
512  lock_list->clear_entries(enclosing_max_lock_id);
513  while (true) {
514  ErrorCode ret = functor->run(workspace);
515  // In any case, release all locks.
516  lock_list->release_all_locks(mcs_adaptor);
517 
518  // The first run of the system transaction takes locks only in "try" mode
519  // to avoid deadlocks. They thus have higher chance to get aborted.
521  // consider retry
522  if (cur_retries < max_retries) {
523  // When we retry, we release all locks in _outer_ transaction to eliminate the
524  // chance of deadlocks. Then the next run of the system transaction can
525  // take locks unconditionally, waiting for an arbitrary period.
526  if (enclosing_max_lock_id != kNullUniversalLockId) {
527  enclosure_release_all_locks_functor();
528  lock_list->compress_entries(kNullUniversalLockId);
529  enclosing_max_lock_id = kNullUniversalLockId;
530  // Now the next run, helped by inherited entries, should be in unconditional mode
531  }
532  ++cur_retries;
533  continue;
534  }
535  }
536 
537  workspace->running_sysxct_ = false;
538  return ret;
539  }
540 }
541 
542 
543 // TASK(Hideaki) standalone sysxct... Needed in a few places.
544 
545 
549 inline void SysxctLockList::assert_sorted() const {
550  // In release mode, this code must be completely erased by compiler
551 #ifndef NDEBUG
553 #endif // NDEBUG
554 }
555 
556 template<typename MCS_ADAPTOR>
557 inline ErrorCode SysxctLockList::try_or_acquire_multiple_locks(
558  MCS_ADAPTOR mcs_adaptor,
559  LockListPosition from_pos,
560  UniversalLockId last_lock_id,
561  bool mandatory_locks) {
562  ASSERT_ND(from_pos != kLockListPositionInvalid);
563  assert_sorted();
564  for (LockListPosition pos = from_pos;; ++pos) {
565  if (pos > last_active_entry_) {
566  break;
567  } else if (array_[pos].universal_lock_id_ > last_lock_id) {
568  // The only use of this func is batch_request_locks_general, where last_lock_id surely exists
569  ASSERT_ND(array_[pos - 1].universal_lock_id_ == last_lock_id);
570  break;
571  }
572 
573  SysxctLockEntry* lock_entry = get_entry(pos);
574  if (mandatory_locks) {
575  lock_entry->used_in_this_run_ = true;
576  }
577  if (lock_entry->is_locked()) {
578  continue;
579  }
580 
581  const bool needs_try = is_try_mode_required(pos);
582  if (lock_entry->page_lock_) {
583  McsWwImpl< MCS_ADAPTOR > impl(mcs_adaptor);
584  storage::Page* page = lock_entry->get_as_page_lock();
585  McsWwLock* lock_addr = &page->get_header().page_version_.lock_;
586  if (needs_try) {
587  lock_entry->mcs_block_ = impl.acquire_try(lock_addr);
588  } else {
589  lock_entry->mcs_block_ = impl.acquire_unconditional(lock_addr);
590  ASSERT_ND(lock_entry->is_locked());
591  }
592  } else {
593  McsImpl< MCS_ADAPTOR, typename MCS_ADAPTOR::ThisRwBlock > impl(mcs_adaptor);
594  McsRwLock* lock_addr = &lock_entry->get_as_record_lock()->lock_;
595  if (needs_try) {
596  lock_entry->mcs_block_ = impl.acquire_try_rw_writer(lock_addr);
597  } else {
598  lock_entry->mcs_block_ = impl.acquire_unconditional_rw_writer(lock_addr);
599  ASSERT_ND(lock_entry->is_locked());
600  }
601  }
602  if (lock_entry->mcs_block_) {
603  if (last_locked_entry_ < pos) {
604  last_locked_entry_ = pos;
605  }
607  } else {
608  return kErrorCodeXctRaceAbort;
609  }
610  }
611 
612  return kErrorCodeOk;
613 }
614 
615 template<typename MCS_ADAPTOR>
616 inline ErrorCode SysxctLockList::batch_request_locks_general(
617  MCS_ADAPTOR mcs_adaptor,
618  storage::VolatilePagePointer page_id,
619  uint32_t lock_count,
620  uintptr_t* locks,
621  bool page_lock) {
622  if (lock_count == 0) {
623  return kErrorCodeOk;
624  }
625 
626  // First, put corresponding entries to the list. either existing or just confirming.
627  LockListPosition from_pos = batch_get_or_add_entries(page_id, lock_count, locks, page_lock);
628  if (from_pos > 1U) {
629  // To reduce the chance of deadlocks, we take locks before these locks.
630  // But, if we have already taken any lock after that, it won't help.
631  UniversalLockId first_lock_id = to_universal_lock_id(page_id, locks[0]);
632  if (last_locked_entry_ < from_pos && enclosing_max_lock_id_ < first_lock_id) {
633  // These are non-mandatory locks, so we don't turn on the "used_in_this_run_" flags
634  CHECK_ERROR_CODE(try_or_acquire_multiple_locks(mcs_adaptor, 1U, first_lock_id, false));
635  }
636  }
637 
638 
639  // Upto which lock ID are we locking? Note, this param is lock-id, not pos.
640  UniversalLockId last_lock_id = to_universal_lock_id(page_id, locks[lock_count - 1]);
641 
642  // Then, lock them all! These are "mandatory" locks.
643  return try_or_acquire_multiple_locks(mcs_adaptor, from_pos, last_lock_id, true);
644 }
645 
646 template<typename MCS_ADAPTOR>
647 inline void SysxctLockList::release_all_locks(MCS_ADAPTOR mcs_adaptor) {
648  for (auto* entry = begin(); entry != end(); ++entry) {
649  if (!entry->is_locked()) {
650  continue;
651  }
652  if (entry->page_lock_) {
653  McsWwImpl< MCS_ADAPTOR > impl(mcs_adaptor);
654  storage::Page* page = entry->get_as_page_lock();
655  McsWwLock* lock_addr = &page->get_header().page_version_.lock_;
656  impl.release(lock_addr, entry->mcs_block_);
657  entry->mcs_block_ = 0;
658  } else {
660  McsRwLock* lock_addr = &entry->get_as_record_lock()->lock_;
661  impl.release_rw_writer(lock_addr, entry->mcs_block_);
662  entry->mcs_block_ = 0;
663  }
664  }
665  last_locked_entry_ = kLockListPositionInvalid;
666 }
667 
668 } // namespace xct
669 } // namespace foedus
670 #endif // FOEDUS_XCT_SYSXCT_IMPL_HPP_
LockListPosition get_or_add_entry(storage::VolatilePagePointer page_id, uintptr_t lock_addr, bool page_lock)
ErrorCode run_nested_sysxct_impl(SysxctFunctor *functor, MCS_ADAPTOR mcs_adaptor, uint32_t max_retries, SysxctWorkspace *workspace, UniversalLockId enclosing_max_lock_id, ENCLOSURE_RELEASE_ALL_LOCKS_FUNCTOR enclosure_release_all_locks_functor)
Runs a system transaction nested in a user transaction.
SysxctLockList & operator=(const SysxctLockList &other)=delete
LockListPosition calculate_last_locked_entry_from(LockListPosition from) const
Only searches among entries at or before "from".
SysxctLockEntry * get_entry(LockListPosition pos)
const SysxctLockEntry * cbegin() const
ErrorCode batch_request_record_locks(MCS_ADAPTOR mcs_adaptor, storage::VolatilePagePointer page_id, uint32_t lock_count, RwLockableXctId **locks)
Used to acquire many locks in a page at once.
storage::Page * get_as_page_lock() const
SysxctLockList lock_list_
Lock list for the system transaction.
void clear_entries(UniversalLockId enclosing_max_lock_id)
Remove all entries.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
An entry in CLL/RLL for system transactions.
Definition: sysxct_impl.hpp:80
bool operator()(const SysxctLockEntry &lhs, UniversalLockId rhs) const
Represents one thread running on one NUMA core.
Definition: thread.hpp:48
const SysxctLockEntry * cend() const
Forward declarations of classes in transaction package.
SysxctLockEntry * begin()
Represents a pointer to a volatile page with modification count for preventing ABA.
Definition: storage_id.hpp:194
thread::Thread * thread_
Back pointer to the enclosing thread,.
Forward declarations of classes in root package.
const LockListPosition kLockListPositionInvalid
Definition: xct_id.hpp:149
void release(McsWwLock *lock, McsBlockIndex block_index)
[WW] Unlcok an MCS lock acquired by this thread.
void release_all_locks(MCS_ADAPTOR mcs_adaptor)
Releases all locks that were acquired.
const SysxctLockEntry * get_entry(LockListPosition pos) const
bool is_valid_entry(LockListPosition pos) const
Maximum number of locks one system transaction might take.
uintptr_t UniversalLockId
Universally ordered identifier of each lock.
Definition: xct_id.hpp:134
uint32_t get_capacity() const
The MCS reader-writer lock variant of LockableXctId.
Definition: xct_id.hpp:1132
0x0AA1 : "XCTION : Lock acquire failed." .
Definition: error_code.hpp:206
SysxctLockEntry * get_array()
UniversalLockId to_universal_lock_id(storage::VolatilePagePointer page_id, uintptr_t addr)
Definition: sysxct_impl.hpp:63
VolatilePagePointer get_volatile_page_id() const
Definition: page.hpp:339
LockListPosition get_last_locked_entry() const
RwLockableXctId * get_as_record_lock() const
0 means no-error.
Definition: error_code.hpp:87
A functor representing the logic in a system transaction via virtual-function.
void assert_sorted_impl() const
Definition: sysxct_impl.cpp:78
memory::PagePoolOffset get_offset() const
Definition: storage_id.hpp:202
Definitions of IDs in this package and a few related constant values.
An exclusive-only (WW) MCS lock data structure.
Definition: xct_id.hpp:324
xct::McsWwLock lock_
Definition: page.hpp:171
Implements an MCS-locking Algorithm.
uint32_t LockListPosition
Index in a lock-list, either RLL or CLL.
Definition: xct_id.hpp:148
bool operator()(UniversalLockId lhs, const SysxctLockEntry &rhs) const
bool used_in_this_run_
whether the lock was requested at least once in this run.
LockListPosition lower_bound(UniversalLockId lock) const
Analogous to std::lower_bound() for the given lock.
Definition: sysxct_impl.cpp:98
A specialized/simplified implementation of an MCS-locking Algorithm for exclusive-only (WW) locks...
friend std::ostream & operator<<(std::ostream &o, const SysxctLockEntry &v)
Debugging.
Definition: sysxct_impl.cpp:35
McsBlockIndex mcs_block_
0 means the lock not taken.
Definition: sysxct_impl.hpp:98
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
bool page_lock_
Whether this is a pge lock or not.
PageVersion page_version_
Used in several storage types as concurrency control mechanism for the page.
Definition: page.hpp:272
bool is_full() const
When this returns full, it's catastrophic.
friend std::ostream & operator<<(std::ostream &o, const SysxctWorkspace &v)
Definition: sysxct_impl.cpp:70
UniversalLockId get_enclosing_max_lock_id() const
SysxctLockEntry * end()
virtual ErrorCode run(SysxctWorkspace *sysxct_workspace)=0
Execute the system transaction.
friend std::ostream & operator<<(std::ostream &o, const SysxctLockList &v)
Definition: sysxct_impl.cpp:53
bool operator()(storage::Page *p1, storage::Page *p2) const
Definition: sysxct_impl.hpp:67
RLL/CLL of a system transaction.
void release_rw_writer(McsRwLock *lock, McsBlockIndex block_index)
[RW] Releases a writer lock.
ErrorCode batch_request_page_locks(MCS_ADAPTOR mcs_adaptor, uint32_t lock_count, storage::Page **pages)
The interface is same as the record version, but this one doesn't do much optimization.
LockListPosition to_pos(const SysxctLockEntry *entry) const
#define CHECK_ERROR_CODE(x)
This macro calls x and checks its returned error code.
Definition: error_code.hpp:155
void set(UniversalLockId lock_id, uintptr_t lock, bool page_lock)
uint32_t McsBlockIndex
Index in thread-local MCS block.
Definition: xct_id.hpp:153
ErrorCode request_page_lock(MCS_ADAPTOR mcs_adaptor, storage::Page *page)
Acquires a page lock.
for std::binary_search() etc without creating the object
void assert_sorted() const __attribute__((always_inline))
Inline definitions of SysxctLockList methods.
UniversalLockId universal_lock_id_
Used to order locks in canonical order.
Definition: sysxct_impl.hpp:85
void init(thread::Thread *enclosing_thread)
ErrorCode request_record_lock(MCS_ADAPTOR mcs_adaptor, storage::VolatilePagePointer page_id, RwLockableXctId *lock)
If not yet acquired, acquires a record lock and adds an entry to this list, re-sorting part of the li...
PageHeader & get_header()
At least the basic header exists in all pages.
Definition: page.hpp:336
bool running_sysxct_
Whether we are already running a sysxct using this workspace.
void assert_last_locked_entry() const
void compress_entries(UniversalLockId enclosing_max_lock_id)
Unlike clear_entries(), this is used when a sysxct is aborted and will be retried.
#define UNLIKELY(x)
Hints that x is highly likely false.
Definition: compiler.hpp:104
0x0A05 : "XCTION : Aborted a transaction because of a race condition. This is an expected error in hi...
Definition: error_code.hpp:200
bool operator<(const SysxctLockEntry &rhs) const
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
bool is_try_mode_required(LockListPosition pos) const
Forward declarations of classes in thread package.
#define ALWAYS_INLINE
A function suffix to hint that the function should always be inlined.
Definition: compiler.hpp:106
LockListPosition get_last_active_entry() const
An MCS reader-writer lock data structure.
Definition: xct_id.hpp:795
ErrorCode
Enum of error codes defined in error_code.xmacro.
Definition: error_code.hpp:85
Per-thread reused work memory for system transactions.
LockListPosition batch_get_or_add_entries(storage::VolatilePagePointer page_id, uint32_t lock_count, uintptr_t *lock_addr, bool page_lock)
Batched version of get_or_add_entry().
const SysxctLockEntry * get_array() const
const UniversalLockId kNullUniversalLockId
This never points to a valid lock, and also evaluates less than any vaild alocks. ...
Definition: xct_id.hpp:137
LockListPosition calculate_last_locked_entry() const
Calculate last_locked_entry_ by really checking the whole list.
uintptr_t lock_
Virtual address of a record lock.
Definition: sysxct_impl.hpp:91
0x0AA4 : "XCTION : The thread is already running a system transaction. This means an incorrect use of...
Definition: error_code.hpp:209