mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-23 10:35:03 +00:00
Por boost range lock implementation
This commit is contained in:
parent
ff99ad694a
commit
22a974b08a
@ -679,6 +679,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/path_util.h
|
src/common/path_util.h
|
||||||
src/common/object_pool.h
|
src/common/object_pool.h
|
||||||
src/common/polyfill_thread.h
|
src/common/polyfill_thread.h
|
||||||
|
src/common/range_lock.h
|
||||||
src/common/rdtsc.cpp
|
src/common/rdtsc.cpp
|
||||||
src/common/rdtsc.h
|
src/common/rdtsc.h
|
||||||
src/common/recursive_lock.cpp
|
src/common/recursive_lock.cpp
|
||||||
|
101
src/common/range_lock.h
Normal file
101
src/common/range_lock.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// From boost thread locking
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
struct RangeLockGuard {
|
||||||
|
Iterator begin;
|
||||||
|
Iterator end;
|
||||||
|
|
||||||
|
RangeLockGuard(Iterator begin_, Iterator end_) : begin(begin_), end(end_) {
|
||||||
|
LockRange(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
begin = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RangeLockGuard() {
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
begin->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
Iterator TryLockRange(Iterator begin, Iterator end) {
|
||||||
|
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||||
|
|
||||||
|
if (begin == end) {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<LockType> guard(*begin, std::try_to_lock);
|
||||||
|
if (!guard.owns_lock()) {
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator failed = TryLockRange(++begin, end);
|
||||||
|
if (failed == end) {
|
||||||
|
guard.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
void LockRange(Iterator begin, Iterator end) {
|
||||||
|
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||||
|
|
||||||
|
if (begin == end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_with_begin = true;
|
||||||
|
Iterator second = begin;
|
||||||
|
++second;
|
||||||
|
Iterator next = second;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
std::unique_lock<LockType> begin_lock(*begin, std::defer_lock);
|
||||||
|
if (start_with_begin) {
|
||||||
|
begin_lock.lock();
|
||||||
|
|
||||||
|
const Iterator failed_lock = TryLockRange(next, end);
|
||||||
|
if (failed_lock == end) {
|
||||||
|
begin_lock.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_with_begin = false;
|
||||||
|
next = failed_lock;
|
||||||
|
} else {
|
||||||
|
RangeLockGuard<Iterator> guard(next, end);
|
||||||
|
|
||||||
|
if (begin_lock.try_lock()) {
|
||||||
|
const Iterator failed_lock = TryLockRange(second, next);
|
||||||
|
if (failed_lock == next) {
|
||||||
|
begin_lock.release();
|
||||||
|
guard.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_with_begin = false;
|
||||||
|
next = failed_lock;
|
||||||
|
} else {
|
||||||
|
start_with_begin = true;
|
||||||
|
next = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
@ -2,9 +2,9 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <boost/thread/lock_algorithms.hpp>
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/range_lock.h"
|
||||||
#include "common/signal_context.h"
|
#include "common/signal_context.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/signals.h"
|
#include "core/signals.h"
|
||||||
@ -196,13 +196,9 @@ struct PageManager::Impl {
|
|||||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||||
|
|
||||||
// Acquire locks for the range of pages
|
// Acquire locks for the range of pages
|
||||||
size_t lock_start = page / PAGES_PER_LOCK;
|
const auto lock_start = locks.begin() + (page / PAGES_PER_LOCK);
|
||||||
const size_t lock_end = Common::DivCeil(page_end, PAGES_PER_LOCK);
|
const auto lock_end = locks.begin() + Common::DivCeil(page_end, PAGES_PER_LOCK);
|
||||||
boost::container::small_vector<std::unique_lock<LockType>, 8> unique_locks;
|
Common::RangeLockGuard lk(lock_start, lock_end);
|
||||||
for (; lock_start < lock_end; ++lock_start) {
|
|
||||||
unique_locks.emplace_back(locks[lock_start], std::defer_lock);
|
|
||||||
}
|
|
||||||
boost::lock(unique_locks.begin(), unique_locks.end());
|
|
||||||
|
|
||||||
auto perms = cached_pages[page].Perm();
|
auto perms = cached_pages[page].Perm();
|
||||||
u64 range_begin = 0;
|
u64 range_begin = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user