LV2: allocation-free synchronization syscalls

* Show waiters' ID in kernel explorer.
* Remove deque dependency from sys_sync.h
This commit is contained in:
Eladash 2022-07-25 18:57:47 +03:00 committed by Ivan
parent c7fbc16357
commit 73aaff1b29
26 changed files with 547 additions and 275 deletions

View file

@ -120,7 +120,7 @@ CellError lv2_event_queue::send(lv2_event event, bool notify_later)
return CELL_ENOTCONN;
}
if (sq.empty())
if (!pq && !sq)
{
if (events.size() < this->size + 0u)
{
@ -135,7 +135,7 @@ CellError lv2_event_queue::send(lv2_event event, bool notify_later)
if (type == SYS_PPU_QUEUE)
{
// Store event in registers
auto& ppu = static_cast<ppu_thread&>(*schedule<ppu_thread>(sq, protocol));
auto& ppu = static_cast<ppu_thread&>(*schedule<ppu_thread>(pq, protocol));
if (ppu.state & cpu_flag::again)
{
@ -241,11 +241,15 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
std::unique_lock<shared_mutex> qlock;
cpu_thread* head{};
const auto queue = idm::withdraw<lv2_obj, lv2_event_queue>(equeue_id, [&](lv2_event_queue& queue) -> CellError
{
qlock = std::unique_lock{queue.mutex};
if (!mode && !queue.sq.empty())
head = queue.type == SYS_PPU_QUEUE ? static_cast<cpu_thread*>(+queue.pq) : +queue.sq;
if (!mode && head)
{
return CELL_EBUSY;
}
@ -258,13 +262,13 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
lv2_obj::on_id_destroy(queue, queue.key);
if (queue.sq.empty())
if (!head)
{
qlock.unlock();
}
else
{
for (auto cpu : queue.sq)
for (auto cpu = head; cpu; cpu = cpu->get_next_cpu())
{
if (cpu->state & cpu_flag::again)
{
@ -296,15 +300,18 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
if (qlock.owns_lock())
{
std::deque<cpu_thread*> sq;
sq = std::move(queue->sq);
if (sys_event.warning)
{
fmt::append(lost_data, "Forcefully awaken waiters (%u):\n", sq.size());
u32 size = 0;
for (auto cpu : sq)
for (auto cpu = head; cpu; cpu = cpu->get_next_cpu())
{
size++;
}
fmt::append(lost_data, "Forcefully awaken waiters (%u):\n", size);
for (auto cpu = head; cpu; cpu = cpu->get_next_cpu())
{
lost_data += cpu->get_name();
lost_data += '\n';
@ -313,21 +320,24 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode)
if (queue->type == SYS_PPU_QUEUE)
{
for (auto cpu : sq)
for (auto cpu = +queue->pq; cpu; cpu = cpu->next_cpu)
{
static_cast<ppu_thread&>(*cpu).gpr[3] = CELL_ECANCELED;
cpu->gpr[3] = CELL_ECANCELED;
queue->append(cpu);
}
atomic_storage<ppu_thread*>::release(queue->pq, nullptr);
lv2_obj::awake_all();
}
else
{
for (auto cpu : sq)
for (auto cpu = +queue->sq; cpu; cpu = cpu->next_cpu)
{
static_cast<spu_thread&>(*cpu).ch_in_mbox.set_values(1, CELL_ECANCELED);
resume_spu_thread_group_from_waiting(static_cast<spu_thread&>(*cpu));
cpu->ch_in_mbox.set_values(1, CELL_ECANCELED);
resume_spu_thread_group_from_waiting(*cpu);
}
atomic_storage<spu_thread*>::release(queue->sq, nullptr);
}
qlock.unlock();
@ -382,7 +392,7 @@ error_code sys_event_queue_tryreceive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sy
s32 count = 0;
while (queue->sq.empty() && count < size && !queue->events.empty())
while (count < size && !queue->events.empty())
{
auto& dest = event_array[count++];
const auto event = queue->events.front();
@ -425,8 +435,8 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
if (queue.events.empty())
{
queue.sq.emplace_back(&ppu);
queue.sleep(ppu, timeout, true);
lv2_obj::emplace(queue.pq, &ppu);
return CELL_EBUSY;
}
@ -464,13 +474,16 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
{
std::lock_guard lock_rsx(queue->mutex);
if (std::find(queue->sq.begin(), queue->sq.end(), &ppu) == queue->sq.end())
for (auto cpu = +queue->pq; cpu; cpu = cpu->next_cpu)
{
break;
if (cpu == &ppu)
{
ppu.state += cpu_flag::again;
return {};
}
}
ppu.state += cpu_flag::again;
return {};
break;
}
for (usz i = 0; cpu_flag::signal - ppu.state && i < 50; i++)
@ -495,7 +508,7 @@ error_code sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_e
std::lock_guard lock(queue->mutex);
if (!queue->unqueue(queue->sq, &ppu))
if (!queue->unqueue(queue->pq, &ppu))
{
break;
}