kernel: Use std::list for semaphore
This commit is contained in:
parent
5c1de381c4
commit
833a366e3b
|
@ -2,9 +2,8 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <utility>
|
|
||||||
#include <boost/intrusive/list.hpp>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -13,9 +12,6 @@
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
using ListBaseHook =
|
|
||||||
boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>;
|
|
||||||
|
|
||||||
class Semaphore {
|
class Semaphore {
|
||||||
public:
|
public:
|
||||||
Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo)
|
Semaphore(s32 init_count, s32 max_count, std::string_view name, bool is_fifo)
|
||||||
|
@ -37,7 +33,7 @@ public:
|
||||||
|
|
||||||
// Create waiting thread object and add it into the list of waiters.
|
// Create waiting thread object and add it into the list of waiters.
|
||||||
WaitingThread waiter{need_count, is_fifo};
|
WaitingThread waiter{need_count, is_fifo};
|
||||||
AddWaiter(waiter);
|
AddWaiter(&waiter);
|
||||||
|
|
||||||
// Perform the wait.
|
// Perform the wait.
|
||||||
return waiter.Wait(lk, timeout);
|
return waiter.Wait(lk, timeout);
|
||||||
|
@ -52,14 +48,14 @@ public:
|
||||||
|
|
||||||
// Wake up threads in order of priority.
|
// Wake up threads in order of priority.
|
||||||
for (auto it = wait_list.begin(); it != wait_list.end();) {
|
for (auto it = wait_list.begin(); it != wait_list.end();) {
|
||||||
auto& waiter = *it;
|
auto* waiter = *it;
|
||||||
if (waiter.need_count > token_count) {
|
if (waiter->need_count > token_count) {
|
||||||
it++;
|
it++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
it = wait_list.erase(it);
|
it = wait_list.erase(it);
|
||||||
token_count -= waiter.need_count;
|
token_count -= waiter->need_count;
|
||||||
waiter.cv.notify_one();
|
waiter->cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -70,9 +66,9 @@ public:
|
||||||
if (num_waiters) {
|
if (num_waiters) {
|
||||||
*num_waiters = wait_list.size();
|
*num_waiters = wait_list.size();
|
||||||
}
|
}
|
||||||
for (auto& waiter : wait_list) {
|
for (auto* waiter : wait_list) {
|
||||||
waiter.was_cancled = true;
|
waiter->was_cancled = true;
|
||||||
waiter.cv.notify_one();
|
waiter->cv.notify_one();
|
||||||
}
|
}
|
||||||
wait_list.clear();
|
wait_list.clear();
|
||||||
token_count = set_count < 0 ? init_count : set_count;
|
token_count = set_count < 0 ? init_count : set_count;
|
||||||
|
@ -80,7 +76,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct WaitingThread : public ListBaseHook {
|
struct WaitingThread {
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
u32 priority;
|
u32 priority;
|
||||||
s32 need_count;
|
s32 need_count;
|
||||||
|
@ -132,7 +128,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddWaiter(WaitingThread& waiter) {
|
void AddWaiter(WaitingThread* waiter) {
|
||||||
// Insert at the end of the list for FIFO order.
|
// Insert at the end of the list for FIFO order.
|
||||||
if (is_fifo) {
|
if (is_fifo) {
|
||||||
wait_list.push_back(waiter);
|
wait_list.push_back(waiter);
|
||||||
|
@ -140,16 +136,13 @@ public:
|
||||||
}
|
}
|
||||||
// Find the first with priority less then us and insert right before it.
|
// Find the first with priority less then us and insert right before it.
|
||||||
auto it = wait_list.begin();
|
auto it = wait_list.begin();
|
||||||
while (it != wait_list.end() && it->priority > waiter.priority) {
|
while (it != wait_list.end() && (*it)->priority > waiter->priority) {
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
wait_list.insert(it, waiter);
|
wait_list.insert(it, waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
using WaitingThreads =
|
std::list<WaitingThread*> wait_list;
|
||||||
boost::intrusive::list<WaitingThread, boost::intrusive::base_hook<ListBaseHook>,
|
|
||||||
boost::intrusive::constant_time_size<false>>;
|
|
||||||
WaitingThreads wait_list;
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::atomic<s32> token_count;
|
std::atomic<s32> token_count;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
|
|
|
@ -167,7 +167,7 @@ struct Liverpool {
|
||||||
static constexpr auto* GetBinaryInfo(const Shader& sh) {
|
static constexpr auto* GetBinaryInfo(const Shader& sh) {
|
||||||
const auto* code = sh.template Address<u32*>();
|
const auto* code = sh.template Address<u32*>();
|
||||||
const auto* bininfo = std::bit_cast<const BinaryInfo*>(code + (code[1] + 1) * 2);
|
const auto* bininfo = std::bit_cast<const BinaryInfo*>(code + (code[1] + 1) * 2);
|
||||||
ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header");
|
// ASSERT_MSG(bininfo->Valid(), "Invalid shader binary header");
|
||||||
return bininfo;
|
return bininfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,7 +250,12 @@ void PipelineCache::RefreshGraphicsKey() {
|
||||||
infos[i] = nullptr;
|
infos[i] = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const auto* bininfo = Liverpool::GetBinaryInfo(*pgm);
|
||||||
|
if (!bininfo->Valid()) {
|
||||||
|
key.stage_hashes[i] = 0;
|
||||||
|
infos[i] = nullptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const auto stage = Shader::Stage{i};
|
const auto stage = Shader::Stage{i};
|
||||||
std::tie(infos[i], modules[i], key.stage_hashes[i]) = GetProgram(pgm, stage, binding);
|
std::tie(infos[i], modules[i], key.stage_hashes[i]) = GetProgram(pgm, stage, binding);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue