mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-02 11:03:34 -06:00
* no no * Adjust locking strategy Use a separate mutex for the initial error checks + GPU unmap instead of using the reader lock. Make sure all writers lock this separate mutex, and for those that don't perform GPU unmaps, lock the writer lock immediately too. This gets around every race condition I've envisioned so far, and hopefully does the trick? * Clang * Always GPU unmap GPU unmaps have logic built-in to only run on mapped areas. Not sure if userfaultfd would work with this, but since that's already broken anyway, I'll let reviewers decide that. Without doing this, I'd need to do an extra pass through VMAs to find what all needs to be GPU modified before I can unmap from GPU, then perform remaining unmap work. Especially for places like MapMemory, that's a lot of code bloat. * Fixups * Update memory.cpp * Rename mutex It's really just a mutex for the sole purpose of dealing with GPU unmaps, so unmap_mutex is a bit more fitting than transition_mutex
56 lines
1.2 KiB
C++
56 lines
1.2 KiB
C++
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
|
|
namespace Common {
|
|
|
|
// Like std::shared_mutex, but reader has priority over writer.
|
|
class SharedFirstMutex {
|
|
public:
|
|
void lock() {
|
|
std::unique_lock<std::mutex> lock(mtx);
|
|
cv.wait(lock, [this]() { return !writer_active && readers == 0; });
|
|
writer_active = true;
|
|
}
|
|
|
|
bool try_lock() {
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
if (writer_active || readers > 0) {
|
|
return false;
|
|
}
|
|
writer_active = true;
|
|
return true;
|
|
}
|
|
|
|
void unlock() {
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
writer_active = false;
|
|
cv.notify_all();
|
|
}
|
|
|
|
void lock_shared() {
|
|
std::unique_lock<std::mutex> lock(mtx);
|
|
cv.wait(lock, [this]() { return !writer_active; });
|
|
++readers;
|
|
}
|
|
|
|
void unlock_shared() {
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
if (--readers == 0) {
|
|
cv.notify_all();
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::mutex mtx;
|
|
std::condition_variable cv;
|
|
int readers = 0;
|
|
bool writer_active = false;
|
|
};
|
|
|
|
} // namespace Common
|