mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-15 11:25:13 +00:00
c4506da0ae
* libkernel: Cleanup some function places * kernel: Refactor thread functions * kernel: It builds * kernel: Fix a bunch of bugs, kernel thread heap * kernel: File cleanup pt1 * File cleanup pt2 * File cleanup pt3 * File cleanup pt4 * kernel: Add missing funcs * kernel: Add basic exceptions for linux * gnmdriver: Add workload functions * kernel: Fix new pthreads code on macOS. (#1441) * kernel: Downgrade edeadlk to log * gnmdriver: Add sceGnmSubmitCommandBuffersForWorkload * exception: Add context register population for macOS. (#1444) * kernel: Pthread rewrite touchups for Windows * kernel: Multiplatform thread implementation * mutex: Remove spamming log * pthread_spec: Make assert into a log * pthread_spec: Zero initialize array * Attempt to fix non-Windows builds * hotfix: change incorrect NID for scePthreadAttrSetaffinity * scePthreadAttrSetaffinity implementation * Attempt to fix Linux * windows: Address a bunch of address space problems * address_space: Fix unmap of region surrounded by placeholders * libs: Reduce logging * pthread: Implement condvar with waitable atomics and sleepqueue * sleepq: Separate and make faster * time: Remove delay execution * Causes high cpu usage in Tohou Luna Nights * kernel: Cleanup files again * pthread: Add missing include * semaphore: Use binary_semaphore instead of condvar * Seems more reliable * libraries/sysmodule: log module on `sceSysmoduleIsLoaded` * libraries/kernel: implement `scePthreadSetPrio` --------- Co-authored-by: squidbus <175574877+squidbus@users.noreply.github.com> Co-authored-by: Daniel R. <47796739+polybiusproxy@users.noreply.github.com>
164 lines
3.6 KiB
C++
164 lines
3.6 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include "common/assert.h"
|
|
#include "common/spin_lock.h"
|
|
|
|
namespace Common {
|
|
|
|
class SlabHeapImpl {
|
|
public:
|
|
struct Node {
|
|
Node* next{};
|
|
};
|
|
|
|
public:
|
|
constexpr SlabHeapImpl() = default;
|
|
|
|
void Initialize() {
|
|
ASSERT(m_head == nullptr);
|
|
}
|
|
|
|
Node* GetHead() const {
|
|
return m_head;
|
|
}
|
|
|
|
void* Allocate() {
|
|
m_lock.lock();
|
|
|
|
Node* ret = m_head;
|
|
if (ret != nullptr) {
|
|
m_head = ret->next;
|
|
}
|
|
|
|
m_lock.unlock();
|
|
return ret;
|
|
}
|
|
|
|
void Free(void* obj) {
|
|
m_lock.lock();
|
|
|
|
Node* node = static_cast<Node*>(obj);
|
|
node->next = m_head;
|
|
m_head = node;
|
|
|
|
m_lock.unlock();
|
|
}
|
|
|
|
private:
|
|
std::atomic<Node*> m_head{};
|
|
Common::SpinLock m_lock;
|
|
};
|
|
|
|
class SlabHeapBase : protected SlabHeapImpl {
|
|
private:
|
|
size_t m_obj_size{};
|
|
uintptr_t m_peak{};
|
|
uintptr_t m_start{};
|
|
uintptr_t m_end{};
|
|
|
|
public:
|
|
constexpr SlabHeapBase() = default;
|
|
|
|
bool Contains(uintptr_t address) const {
|
|
return m_start <= address && address < m_end;
|
|
}
|
|
|
|
void Initialize(size_t obj_size, void* memory, size_t memory_size) {
|
|
// Ensure we don't initialize a slab using null memory.
|
|
ASSERT(memory != nullptr);
|
|
|
|
// Set our object size.
|
|
m_obj_size = obj_size;
|
|
|
|
// Initialize the base allocator.
|
|
SlabHeapImpl::Initialize();
|
|
|
|
// Set our tracking variables.
|
|
const size_t num_obj = (memory_size / obj_size);
|
|
m_start = reinterpret_cast<uintptr_t>(memory);
|
|
m_end = m_start + num_obj * obj_size;
|
|
m_peak = m_start;
|
|
|
|
// Free the objects.
|
|
u8* cur = reinterpret_cast<u8*>(m_end);
|
|
|
|
for (size_t i = 0; i < num_obj; i++) {
|
|
cur -= obj_size;
|
|
SlabHeapImpl::Free(cur);
|
|
}
|
|
}
|
|
|
|
size_t GetSlabHeapSize() const {
|
|
return (m_end - m_start) / this->GetObjectSize();
|
|
}
|
|
|
|
size_t GetObjectSize() const {
|
|
return m_obj_size;
|
|
}
|
|
|
|
void* Allocate() {
|
|
void* obj = SlabHeapImpl::Allocate();
|
|
return obj;
|
|
}
|
|
|
|
void Free(void* obj) {
|
|
// Don't allow freeing an object that wasn't allocated from this heap.
|
|
const bool contained = this->Contains(reinterpret_cast<uintptr_t>(obj));
|
|
ASSERT(contained);
|
|
SlabHeapImpl::Free(obj);
|
|
}
|
|
|
|
size_t GetObjectIndex(const void* obj) const {
|
|
return (reinterpret_cast<uintptr_t>(obj) - m_start) / this->GetObjectSize();
|
|
}
|
|
|
|
size_t GetPeakIndex() const {
|
|
return this->GetObjectIndex(reinterpret_cast<const void*>(m_peak));
|
|
}
|
|
|
|
uintptr_t GetSlabHeapAddress() const {
|
|
return m_start;
|
|
}
|
|
|
|
size_t GetNumRemaining() const {
|
|
// Only calculate the number of remaining objects under debug configuration.
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
class SlabHeap final : public SlabHeapBase {
|
|
private:
|
|
using BaseHeap = SlabHeapBase;
|
|
|
|
public:
|
|
constexpr SlabHeap() = default;
|
|
|
|
void Initialize(void* memory, size_t memory_size) {
|
|
BaseHeap::Initialize(sizeof(T), memory, memory_size);
|
|
}
|
|
|
|
T* Allocate() {
|
|
T* obj = static_cast<T*>(BaseHeap::Allocate());
|
|
|
|
if (obj != nullptr) [[likely]] {
|
|
std::construct_at(obj);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
void Free(T* obj) {
|
|
BaseHeap::Free(obj);
|
|
}
|
|
|
|
size_t GetObjectIndex(const T* obj) const {
|
|
return BaseHeap::GetObjectIndex(obj);
|
|
}
|
|
};
|
|
|
|
} // namespace Common
|