18 #ifndef FOEDUS_XCT_SYSXCT_IMPL_HPP_
19 #define FOEDUS_XCT_SYSXCT_IMPL_HPP_
110 universal_lock_id_ = 0;
114 used_in_this_run_ =
false;
118 universal_lock_id_ = lock_id;
121 page_lock_ = page_lock;
122 used_in_this_run_ =
true;
196 clear_no_assert(enclosing_max_lock_id);
219 template<
typename MCS_ADAPTOR>
221 MCS_ADAPTOR mcs_adaptor,
224 uintptr_t lock_addr =
reinterpret_cast<uintptr_t
>(lock);
225 return request_lock_general(mcs_adaptor, page_id, lock_addr,
false);
229 template<
typename MCS_ADAPTOR>
231 MCS_ADAPTOR mcs_adaptor,
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);
240 template<
typename MCS_ADAPTOR>
242 uintptr_t lock_addr =
reinterpret_cast<uintptr_t
>(page);
251 template<
typename MCS_ADAPTOR>
253 MCS_ADAPTOR mcs_adaptor,
257 for (uint32_t i = 0; i < lock_count; ++i) {
267 template<
typename MCS_ADAPTOR>
290 uintptr_t* lock_addr,
339 if (array_[pos].is_locked()) {
348 ASSERT_ND(correct == last_locked_entry_);
362 if (pos <= last_locked_entry_) {
400 enclosing_max_lock_id_ = enclosing_max_lock_id;
406 ++last_active_entry_;
408 return last_active_entry_;
412 template<
typename MCS_ADAPTOR>
414 MCS_ADAPTOR mcs_adaptor,
417 bool mandatory_locks);
419 template<
typename MCS_ADAPTOR>
421 MCS_ADAPTOR mcs_adaptor,
422 storage::VolatilePagePointer page_id,
427 return batch_request_locks_general(mcs_adaptor, page_id, 1U, &lock, page_lock);
430 template<
typename MCS_ADAPTOR>
432 MCS_ADAPTOR mcs_adaptor,
433 storage::VolatilePagePointer page_id,
464 running_sysxct_ =
false;
465 thread_ = enclosing_thread;
495 template<
typename MCS_ADAPTOR,
typename ENCLOSURE_RELEASE_ALL_LOCKS_FUNCTOR>
498 MCS_ADAPTOR mcs_adaptor,
499 uint32_t max_retries,
502 ENCLOSURE_RELEASE_ALL_LOCKS_FUNCTOR enclosure_release_all_locks_functor) {
510 uint32_t cur_retries = 0;
512 lock_list->clear_entries(enclosing_max_lock_id);
516 lock_list->release_all_locks(mcs_adaptor);
522 if (cur_retries < max_retries) {
527 enclosure_release_all_locks_functor();
556 template<
typename MCS_ADAPTOR>
557 inline ErrorCode SysxctLockList::try_or_acquire_multiple_locks(
558 MCS_ADAPTOR mcs_adaptor,
561 bool mandatory_locks) {
565 if (pos > last_active_entry_) {
567 }
else if (array_[pos].universal_lock_id_ > last_lock_id) {
569 ASSERT_ND(array_[pos - 1].universal_lock_id_ == last_lock_id);
573 SysxctLockEntry* lock_entry =
get_entry(pos);
574 if (mandatory_locks) {
575 lock_entry->used_in_this_run_ =
true;
577 if (lock_entry->is_locked()) {
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_;
587 lock_entry->mcs_block_ = impl.acquire_try(lock_addr);
589 lock_entry->mcs_block_ = impl.acquire_unconditional(lock_addr);
593 McsImpl< MCS_ADAPTOR, typename MCS_ADAPTOR::ThisRwBlock > impl(mcs_adaptor);
594 McsRwLock* lock_addr = &lock_entry->get_as_record_lock()->lock_;
596 lock_entry->mcs_block_ = impl.acquire_try_rw_writer(lock_addr);
598 lock_entry->mcs_block_ = impl.acquire_unconditional_rw_writer(lock_addr);
602 if (lock_entry->mcs_block_) {
603 if (last_locked_entry_ < pos) {
604 last_locked_entry_ = pos;
615 template<
typename MCS_ADAPTOR>
616 inline ErrorCode SysxctLockList::batch_request_locks_general(
617 MCS_ADAPTOR mcs_adaptor,
618 storage::VolatilePagePointer page_id,
622 if (lock_count == 0) {
632 if (last_locked_entry_ < from_pos && enclosing_max_lock_id_ < first_lock_id) {
634 CHECK_ERROR_CODE(try_or_acquire_multiple_locks(mcs_adaptor, 1U, first_lock_id,
false));
643 return try_or_acquire_multiple_locks(mcs_adaptor, from_pos, last_lock_id,
true);
646 template<
typename MCS_ADAPTOR>
648 for (
auto* entry =
begin(); entry !=
end(); ++entry) {
649 if (!entry->is_locked()) {
652 if (entry->page_lock_) {
656 impl.
release(lock_addr, entry->mcs_block_);
657 entry->mcs_block_ = 0;
660 McsRwLock* lock_addr = &entry->get_as_record_lock()->lock_;
662 entry->mcs_block_ = 0;
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).
An entry in CLL/RLL for system transactions.
bool operator()(const SysxctLockEntry &lhs, UniversalLockId rhs) const
Represents one thread running on one NUMA core.
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.
thread::Thread * thread_
Back pointer to the enclosing thread,.
Forward declarations of classes in root package.
const LockListPosition kLockListPositionInvalid
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.
uint32_t get_capacity() const
The MCS reader-writer lock variant of LockableXctId.
0x0AA1 : "XCTION : Lock acquire failed." .
SysxctLockEntry * get_array()
UniversalLockId to_universal_lock_id(storage::VolatilePagePointer page_id, uintptr_t addr)
VolatilePagePointer get_volatile_page_id() const
LockListPosition get_last_locked_entry() const
RwLockableXctId * get_as_record_lock() const
A functor representing the logic in a system transaction via virtual-function.
void assert_sorted_impl() const
friend struct TestIsTryRequired
memory::PagePoolOffset get_offset() const
Definitions of IDs in this package and a few related constant values.
An exclusive-only (WW) MCS lock data structure.
Implements an MCS-locking Algorithm.
uint32_t LockListPosition
Index in a lock-list, either RLL or CLL.
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.
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.
McsBlockIndex mcs_block_
0 means the lock not taken.
Just a marker to denote that the memory region represents a data page.
bool page_lock_
Whether this is a pge lock or not.
bool is_full() const
When this returns full, it's catastrophic.
friend std::ostream & operator<<(std::ostream &o, const SysxctWorkspace &v)
UniversalLockId get_enclosing_max_lock_id() const
virtual ErrorCode run(SysxctWorkspace *sysxct_workspace)=0
Execute the system transaction.
friend std::ostream & operator<<(std::ostream &o, const SysxctLockList &v)
bool operator()(storage::Page *p1, storage::Page *p2) const
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.
void set(UniversalLockId lock_id, uintptr_t lock, bool page_lock)
uint32_t McsBlockIndex
Index in thread-local MCS block.
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.
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.
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.
0x0A05 : "XCTION : Aborted a transaction because of a race condition. This is an expected error in hi...
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'...
uint8_t get_numa_node() const
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.
LockListPosition get_last_active_entry() const
An MCS reader-writer lock data structure.
ErrorCode
Enum of error codes defined in error_code.xmacro.
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. ...
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.
0x0AA4 : "XCTION : The thread is already running a system transaction. This means an incorrect use of...