Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory locking refactoring #9276

Merged
merged 4 commits into from Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions Utilities/Thread.cpp
Expand Up @@ -2702,3 +2702,27 @@ u64 thread_ctrl::get_thread_affinity_mask()
return -1;
#endif
}

std::pair<void*, std::size_t> thread_ctrl::get_thread_stack()
{
#ifdef _WIN32
ULONG_PTR _min = 0;
ULONG_PTR _max = 0;
GetCurrentThreadStackLimits(&_min, &_max);
const std::size_t ssize = _max - _min;
const auto saddr = reinterpret_cast<void*>(_min);
#else
void* saddr = 0;
std::size_t ssize = 0;
pthread_attr_t attr;
#ifdef __linux__
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &saddr, &ssize);
#else
pthread_attr_get_np(pthread_self(), &attr);
pthread_attr_getstackaddr(&attr, &saddr);
pthread_attr_getstacksize(&attr, &ssize);
#endif
#endif
return {saddr, ssize};
}
3 changes: 3 additions & 0 deletions Utilities/Thread.h
Expand Up @@ -262,6 +262,9 @@ class thread_ctrl final
// Miscellaneous
static u64 get_thread_affinity_mask();

// Get current thread stack addr and size
static std::pair<void*, std::size_t> get_thread_stack();

private:
// Miscellaneous
static const u64 process_affinity_mask;
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/Modules/cellCamera.cpp
Expand Up @@ -434,7 +434,7 @@ error_code cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)

if (info->read_mode != CELL_CAMERA_READ_DIRECT && !info->buffer)
{
info->buffer = vm::cast(vm::alloc(vbuf_size, vm::memory_location_t::main));
info->buffer = vm::cast(vm::alloc(vbuf_size, vm::main));
info->bytesize = vbuf_size;
}

Expand Down Expand Up @@ -480,7 +480,7 @@ error_code cellCameraClose(s32 dev_num)
return CELL_CAMERA_ERROR_NOT_OPEN;
}

vm::dealloc(g_camera->info.buffer.addr(), vm::memory_location_t::main);
vm::dealloc(g_camera->info.buffer.addr(), vm::main);
g_camera->is_open = false;

return CELL_OK;
Expand Down
8 changes: 4 additions & 4 deletions rpcs3/Emu/Cell/RawSPUThread.cpp
Expand Up @@ -28,7 +28,7 @@ inline void try_start(spu_thread& spu)

bool spu_thread::read_reg(const u32 addr, u32& value)
{
const u32 offset = addr - this->offset - RAW_SPU_PROB_OFFSET;
const u32 offset = addr - (RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index) - RAW_SPU_PROB_OFFSET;

spu_log.trace("RawSPU[%u]: Read32(0x%x, offset=0x%x)", index, addr, offset);

Expand Down Expand Up @@ -165,7 +165,7 @@ bool spu_thread::read_reg(const u32 addr, u32& value)

bool spu_thread::write_reg(const u32 addr, const u32 value)
{
const u32 offset = addr - this->offset - RAW_SPU_PROB_OFFSET;
const u32 offset = addr - (RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index) - RAW_SPU_PROB_OFFSET;

spu_log.trace("RawSPU[%u]: Write32(0x%x, offset=0x%x, value=0x%x)", index, addr, offset, value);

Expand Down Expand Up @@ -321,7 +321,7 @@ bool spu_thread::write_reg(const u32 addr, const u32 value)

void spu_load_exec(const spu_exec_object& elf)
{
auto ls0 = vm::cast(vm::falloc(RAW_SPU_BASE_ADDR, SPU_LS_SIZE, vm::spu));
auto ls0 = vm::addr_t{RAW_SPU_BASE_ADDR};

spu_thread::g_raw_spu_ctr++;

Expand All @@ -333,7 +333,7 @@ void spu_load_exec(const spu_exec_object& elf)
}
}

auto spu = idm::make_ptr<named_thread<spu_thread>>("TEST_SPU", ls0, nullptr, 0, "", 0);
auto spu = idm::make_ptr<named_thread<spu_thread>>("TEST_SPU", nullptr, 0, "", 0);

spu_thread::g_raw_spu_id[0] = spu->id;

Expand Down
29 changes: 22 additions & 7 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -1384,6 +1384,8 @@ std::string spu_thread::dump_misc() const
fmt::append(ret, "...chunk-0x%05x", (name & 0xffff) * 4);
}

const u32 offset = group ? SPU_FAKE_BASE_ADDR + (id & 0xffffff) * SPU_LS_SIZE : RAW_SPU_BASE_ADDR + index * RAW_SPU_OFFSET;

fmt::append(ret, "\n[%s]", ch_mfc_cmd);
fmt::append(ret, "\nLocal Storage: 0x%08x..0x%08x", offset, offset + 0x3ffff);

Expand Down Expand Up @@ -1624,16 +1626,19 @@ void spu_thread::cpu_task()
spu_thread::~spu_thread()
{
{
const auto [_, shm] = vm::get(vm::any, offset)->get(offset);
vm::writer_lock(0);

for (s32 i = -1; i < 2; i++)
{
// Unmap LS mirrors
shm->unmap_critical(ls + (i * SPU_LS_SIZE));
}
}

// Deallocate Local Storage
vm::dealloc_verbose_nothrow(offset);
if (!group)
{
// Deallocate local storage (thread groups are handled in sys_spu.cpp)
vm::dealloc_verbose_nothrow(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, vm::spu);
}

// Release LS mirrors area
Expand All @@ -1653,14 +1658,25 @@ spu_thread::~spu_thread()
perf_log.notice("Perf stats for PUTLLC reload: successs %u, failure %u", last_succ, last_fail);
}

spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option)
spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated, u32 option)
: cpu_thread(idm::last_id())
, index(index)
, shm(std::make_shared<utils::shm>(SPU_LS_SIZE))
, ls([&]()
{
const auto [_, shm] = vm::get(vm::any, _ls)->get(_ls);
const auto addr = static_cast<u8*>(utils::memory_reserve(SPU_LS_SIZE * 5));

if (!group)
{
vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm);
}
else
{
vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm);
}

vm::writer_lock(0);

for (u32 i = 1; i < 4; i++)
{
// Map LS mirrors
Expand All @@ -1672,7 +1688,6 @@ spu_thread::spu_thread(vm::addr_t _ls, lv2_spu_group* group, u32 index, std::str
return addr + (SPU_LS_SIZE * 2);
}())
, thread_type(group ? spu_type::threaded : is_isolated ? spu_type::isolated : spu_type::raw)
, offset(_ls)
, group(group)
, option(option)
, lv2_id(lv2_id)
Expand Down Expand Up @@ -1837,7 +1852,7 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*

if (offset + args.size - 1 < SPU_LS_SIZE) // LS access
{
eal = spu.offset + offset; // redirect access
eal = SPU_FAKE_BASE_ADDR * (spu.id & 0xffffff) + offset; // redirect access
}
else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2))
{
Expand Down
13 changes: 10 additions & 3 deletions rpcs3/Emu/Cell/SPUThread.h
Expand Up @@ -14,6 +14,11 @@ struct lv2_event_queue;
struct lv2_spu_group;
struct lv2_int_tag;

namespace utils
{
class shm;
}

// JIT Block
using spu_function_t = void(*)(spu_thread&, void*, u8*);

Expand Down Expand Up @@ -157,6 +162,8 @@ enum : u32
RAW_SPU_OFFSET = 0x00100000,
RAW_SPU_LS_OFFSET = 0x00000000,
RAW_SPU_PROB_OFFSET = 0x00040000,

SPU_FAKE_BASE_ADDR = 0xE8000000,
};

struct spu_channel
Expand Down Expand Up @@ -629,9 +636,9 @@ class spu_thread : public cpu_thread

static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
static const u32 id_step = 1;
static const u32 id_count = 2048;
static const u32 id_count = (0xF0000000 - SPU_FAKE_BASE_ADDR) / SPU_LS_SIZE;

spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false, u32 option = 0);
spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false, u32 option = 0);

u32 pc = 0;

Expand Down Expand Up @@ -730,10 +737,10 @@ class spu_thread : public cpu_thread
atomic_t<u32> last_exit_status; // Value to be written in exit_status after checking group termination

const u32 index; // SPU index
std::shared_ptr<utils::shm> shm; // SPU memory
const std::add_pointer_t<u8> ls; // SPU LS pointer
const spu_type thread_type;
private:
const u32 offset; // SPU LS offset
lv2_spu_group* const group; // SPU Thread Group (only safe to access in the spu thread itself)
public:
const u32 option; // sys_spu_thread_initialize option
Expand Down
4 changes: 3 additions & 1 deletion rpcs3/Emu/Cell/lv2/sys_memory.cpp
Expand Up @@ -58,12 +58,13 @@ error_code sys_memory_allocate(cpu_thread& cpu, u32 size, u64 flags, vm::ptr<u32

if (const auto area = vm::reserve_map(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000), 0x401))
{
if (u32 addr = area->alloc(size, align))
if (u32 addr = area->alloc(size, nullptr, align))
{
verify(HERE), !g_fxo->get<sys_memory_address_table>()->addrs[addr >> 16].exchange(dct);

if (alloc_addr)
{
vm::lock_sudo(addr, size);
*alloc_addr = addr;
return CELL_OK;
}
Expand Down Expand Up @@ -134,6 +135,7 @@ error_code sys_memory_allocate_from_container(cpu_thread& cpu, u32 size, u32 cid

if (alloc_addr)
{
vm::lock_sudo(addr, size);
*alloc_addr = addr;
return CELL_OK;
}
Expand Down
10 changes: 8 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_mmapper.cpp
Expand Up @@ -20,6 +20,10 @@ lv2_memory::lv2_memory(u32 size, u32 align, u64 flags, lv2_memory_container* ct)
, ct(ct)
, shm(std::make_shared<utils::shm>(size, 1 /* shareable flag */))
{
#ifndef _WIN32
// Optimization that's useless on Windows :puke:
utils::memory_lock(shm->map_self(), size);
#endif
}

template<> DECLARE(ipc_manager<lv2_memory, u64>::g_ipc) {};
Expand Down Expand Up @@ -588,6 +592,7 @@ error_code sys_mmapper_map_shared_memory(ppu_thread& ppu, u32 addr, u32 mem_id,
return CELL_EBUSY;
}

vm::lock_sudo(addr, mem->size);
return CELL_OK;
}

Expand Down Expand Up @@ -627,14 +632,15 @@ error_code sys_mmapper_search_and_map(ppu_thread& ppu, u32 start_addr, u32 mem_i
return mem.ret;
}

const u32 addr = area->alloc(mem->size, mem->align, &mem->shm, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M);
const u32 addr = area->alloc(mem->size, &mem->shm, mem->align, mem->align == 0x10000 ? SYS_MEMORY_PAGE_SIZE_64K : SYS_MEMORY_PAGE_SIZE_1M);

if (!addr)
{
mem->counter--;
return CELL_ENOMEM;
}

vm::lock_sudo(addr, mem->size);
*alloc_addr = addr;
return CELL_OK;
}
Expand All @@ -652,7 +658,7 @@ error_code sys_mmapper_unmap_shared_memory(ppu_thread& ppu, u32 addr, vm::ptr<u3
return {CELL_EINVAL, addr};
}

const auto shm = area->get(addr);
const auto shm = area->peek(addr);

if (!shm.second)
{
Expand Down
15 changes: 7 additions & 8 deletions rpcs3/Emu/Cell/lv2/sys_spu.cpp
Expand Up @@ -399,8 +399,6 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
sys_spu.warning("Unimplemented SPU Thread options (0x%x)", option);
}

const vm::addr_t ls_addr{verify("SPU LS" HERE, vm::alloc(SPU_LS_SIZE, vm::main))};

const u32 inited = group->init;

const u32 tid = (inited << 24) | (group_id & 0xffffff);
Expand All @@ -414,7 +412,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
fmt::append(full_name, "%s ", thread_name);
}

const auto spu = std::make_shared<named_thread<spu_thread>>(full_name, ls_addr, group.get(), spu_num, thread_name, tid, false, option);
const auto spu = std::make_shared<named_thread<spu_thread>>(full_name, group.get(), spu_num, thread_name, tid, false, option);
group->threads[inited] = spu;
group->threads_map[spu_num] = static_cast<s8>(inited);
return spu;
Expand Down Expand Up @@ -683,6 +681,9 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
{
if (auto thread = t.get())
{
// Deallocate LS
vm::get(vm::spu)->dealloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (thread->id & 0xffffff), &thread->shm);

// Remove ID from IDM (destruction will occur in group destructor)
idm::remove<named_thread<spu_thread>>(thread->id);
}
Expand Down Expand Up @@ -1845,9 +1846,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<void> at
index = 0;
}

const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, vm::spu))};

const u32 tid = idm::make<named_thread<spu_thread>>(fmt::format("RawSPU[0x%x] ", index), ls_addr, nullptr, index, "", index);
const u32 tid = idm::make<named_thread<spu_thread>>(fmt::format("RawSPU[0x%x] ", index), nullptr, index, "", index);

spu_thread::g_raw_spu_id[index] = verify("RawSPU ID" HERE, tid);

Expand Down Expand Up @@ -1893,9 +1892,9 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<voi
index = 0;
}

const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, vm::spu))};
const vm::addr_t ls_addr{RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index};

const auto thread = idm::make_ptr<named_thread<spu_thread>>(fmt::format("IsoSPU[0x%x] ", index), ls_addr, nullptr, index, "", index, true);
const auto thread = idm::make_ptr<named_thread<spu_thread>>(fmt::format("IsoSPU[0x%x] ", index), nullptr, index, "", index, true);

thread->gpr[3] = v128::from64(0, arg1);
thread->gpr[4] = v128::from64(0, arg2);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_vm.cpp
Expand Up @@ -77,6 +77,7 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u32 vsize, u32 psize, u32 cid, u64
{
// Alloc all memory (shall not fail)
verify(HERE), area->alloc(vsize);
vm::lock_sudo(area->addr, vsize);

idm::make<sys_vm_t>(area->addr, vsize, ct, psize);

Expand Down