From 168cd9bb7a3909f9d9ce880766db91586dce4c1e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 18 Aug 2015 15:31:48 +0300 Subject: [PATCH] TLS for sys_net implemented Method ptr for vm::ptr (renamed "of") Method ref for vm::ptr (returns vm::ref) Operator & for vm::ref (returns vm::ptr) --- rpcs3/Emu/Memory/vm_ptr.h | 30 +++++++++-- rpcs3/Emu/Memory/vm_ref.h | 10 +++- rpcs3/Emu/Memory/vm_var.h | 6 +-- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 14 +++--- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 16 +++--- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 48 +++++++++--------- rpcs3/Emu/SysCalls/Modules/sys_net.cpp | 56 ++++++++++++++------- rpcs3/rpcs3.cpp | 2 - 8 files changed, 116 insertions(+), 66 deletions(-) diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index e29ef2994c..f75d85b2eb 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -5,6 +5,8 @@ class ARMv7Thread; namespace vm { + template struct _ref_base; + // helper SFINAE type for vm::_ptr_base comparison operators (enables comparison between equal types and between any type and void*) template using if_comparable_t = std::enable_if_t< std::is_void::value || @@ -33,19 +35,39 @@ namespace vm return m_addr; } - // get vm pointer to member - template> _ptr_base of(MT T2::*const member) const + // get vm pointer to a struct member + template> _ptr_base ptr(MT T2::*const member) const { const u32 offset = static_cast(reinterpret_cast(&(reinterpret_cast(0ull)->*member))); return{ VM_CAST(m_addr + offset) }; } - // get vm pointer to array member with array subscribtion - template> _ptr_base> of(MT T2::*const member, u32 index) const + // get vm pointer to a struct member with array subscription + template> _ptr_base> ptr(MT T2::*const member, u32 index) const { const u32 offset = static_cast(reinterpret_cast(&(reinterpret_cast(0ull)->*member))); return{ VM_CAST(m_addr + offset + sizeof32(T) * index) }; } + + // get vm reference to a struct member + template> _ref_base ref(MT T2::*const member) const + { + const u32 offset = static_cast(reinterpret_cast(&(reinterpret_cast(0ull)->*member))); + return{ VM_CAST(m_addr + offset) }; + } + + // get vm reference to a struct member with array subscription + template> _ref_base> ref(MT T2::*const member, u32 index) const + { + const u32 offset = static_cast(reinterpret_cast(&(reinterpret_cast(0ull)->*member))); + return{ VM_CAST(m_addr + offset + sizeof32(T) * index) }; + } + + // get vm reference + _ref_base ref() const + { + return{ VM_CAST(m_addr) }; + } template std::enable_if_t::value> set(const CT& value) { diff --git a/rpcs3/Emu/Memory/vm_ref.h b/rpcs3/Emu/Memory/vm_ref.h index 5189a13ed2..13e4b7189d 100644 --- a/rpcs3/Emu/Memory/vm_ref.h +++ b/rpcs3/Emu/Memory/vm_ref.h @@ -2,6 +2,8 @@ namespace vm { + template struct _ptr_base; + template struct _ref_base { @@ -33,7 +35,7 @@ namespace vm } // TODO: conversion operator (seems hard to define it correctly) - //template::value || std::is_convertible, CT>::value>> operator CT() const + //template::value || std::is_convertible, CT>::value>> operator CT() const //{ // return get_ref(); //} @@ -48,6 +50,12 @@ namespace vm return get_ref(); } + // convert to vm pointer + vm::_ptr_base operator &() const + { + return{ VM_CAST(m_addr) }; + } + // copy assignment operator: // returns T& by default, this may be wrong if called assignment operator has different return type T& operator =(const _ref_base& right) diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 4fb6670f05..1906d1a3fb 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -100,13 +100,13 @@ namespace vm { using _ptr_base::m_addr; - using allocator = A; + using allocation = A; public: template, Args...>::value>> _var_base(Args&&... args) - : allocator(std::forward(args)...) + : allocation(std::forward(args)...) { - m_addr = allocator::get_addr(); + m_addr = allocation::get_addr(); } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 4b58ffb575..692a2d7055 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -74,10 +74,10 @@ s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr dirName, u32 er const vm::var<_stack_t> stack(ppu); - const auto param = stack.of(&_stack_t::param); - const auto result = stack.of(&_stack_t::result); - const auto get = stack.of(&_stack_t::get); - const auto set = stack.of(&_stack_t::set); + const auto param = stack.ptr(&_stack_t::param); + const auto result = stack.ptr(&_stack_t::result); + const auto get = stack.ptr(&_stack_t::get); + const auto set = stack.ptr(&_stack_t::set); get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run. get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST; @@ -414,9 +414,9 @@ s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr dirName const vm::var<_stack_t> stack(ppu); - const auto cbResult = stack.of(&_stack_t::result); - const auto cbGet = stack.of(&_stack_t::get); - const auto cbSet = stack.of(&_stack_t::set); + const auto cbResult = stack.ptr(&_stack_t::result); + const auto cbGet = stack.ptr(&_stack_t::get); + const auto cbSet = stack.ptr(&_stack_t::set); *cbGet = {}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index eaf20423a9..8276422d20 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -67,14 +67,14 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt const vm::var<_stack_t> stack(ppu); - const auto result = stack.of(&_stack_t::result); - const auto listGet = stack.of(&_stack_t::listGet); - const auto listSet = stack.of(&_stack_t::listSet); - const auto fixedSet = stack.of(&_stack_t::fixedSet); - const auto statGet = stack.of(&_stack_t::statGet); - const auto statSet = stack.of(&_stack_t::statSet); - const auto fileGet = stack.of(&_stack_t::fileGet); - const auto fileSet = stack.of(&_stack_t::fileSet); + const auto result = stack.ptr(&_stack_t::result); + const auto listGet = stack.ptr(&_stack_t::listGet); + const auto listSet = stack.ptr(&_stack_t::listSet); + const auto fixedSet = stack.ptr(&_stack_t::fixedSet); + const auto statGet = stack.ptr(&_stack_t::statGet); + const auto statSet = stack.ptr(&_stack_t::statSet); + const auto fileGet = stack.ptr(&_stack_t::fileGet); + const auto fileSet = stack.ptr(&_stack_t::fileSet); // path of the specified user (00000001 by default) const std::string base_dir = fmt::format("/dev_hdd0/home/%08u/savedata/", userId ? userId : 1u); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 3644970887..31788d1514 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -411,7 +411,7 @@ s32 spursDetachLv2EventQueue(vm::ptr spurs, u8 spuPort, bool spursCre /// Wait until a workload in the SPURS instance becomes ready void spursHandlerWaitReady(PPUThread& ppu, vm::ptr spurs) { - if (s32 rc = sys_lwmutex_lock(ppu, spurs.of(&CellSpurs::mutex), 0)) + if (s32 rc = sys_lwmutex_lock(ppu, spurs.ptr(&CellSpurs::mutex), 0)) { throw EXCEPTION("sys_lwmutex_lock() failed (0x%x)", rc); } @@ -424,7 +424,7 @@ void spursHandlerWaitReady(PPUThread& ppu, vm::ptr spurs) { extern u32 g_ppu_func_index__sys_lwmutex_unlock; // test - if (s32 rc = CALL_FUNC(ppu, sys_lwmutex_unlock, ppu, spurs.of(&CellSpurs::mutex))) + if (s32 rc = CALL_FUNC(ppu, sys_lwmutex_unlock, ppu, spurs.ptr(&CellSpurs::mutex))) { throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc); } @@ -484,7 +484,7 @@ void spursHandlerWaitReady(PPUThread& ppu, vm::ptr spurs) spurs->handlerWaiting.store(1); if (spurs->handlerDirty.load() == 0) { - if (s32 rc = sys_lwcond_wait(ppu, spurs.of(&CellSpurs::cond), 0)) + if (s32 rc = sys_lwcond_wait(ppu, spurs.ptr(&CellSpurs::cond), 0)) { throw EXCEPTION("sys_lwcond_wait() failed (0x%x)", rc); } @@ -494,7 +494,7 @@ void spursHandlerWaitReady(PPUThread& ppu, vm::ptr spurs) } // If we reach here then a runnable workload was found - if (s32 rc = sys_lwmutex_unlock(ppu, spurs.of(&CellSpurs::mutex))) + if (s32 rc = sys_lwmutex_unlock(ppu, spurs.ptr(&CellSpurs::mutex))) { throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc); } @@ -710,7 +710,7 @@ void spursEventHelperEntry(PPUThread& ppu) } else if (data0 == 3) { - if (s32 rc = spursInvokeEventHandlers(ppu, spurs.of(&CellSpurs::eventPortMux))) + if (s32 rc = spursInvokeEventHandlers(ppu, spurs.ptr(&CellSpurs::eventPortMux))) { throw EXCEPTION("spursInvokeEventHandlers() failed (0x%x)", rc); } @@ -729,12 +729,12 @@ s32 spursCreateSpursEventHelper(PPUThread& ppu, vm::ptr spurs, u32 pp const vm::var evqName(ppu, 8); memcpy(evqName.get_ptr(), "_spuPrv", 8); - if (s32 rc = spursCreateLv2EventQueue(ppu, spurs, spurs.of(&CellSpurs::eventQueue), spurs.of(&CellSpurs::spuPort), 0x2A /*size*/, evqName)) + if (s32 rc = spursCreateLv2EventQueue(ppu, spurs, spurs.ptr(&CellSpurs::eventQueue), spurs.ptr(&CellSpurs::spuPort), 0x2A /*size*/, evqName)) { return rc; } - if (s32 rc = sys_event_port_create(spurs.of(&CellSpurs::eventPort), SYS_EVENT_PORT_LOCAL, SYS_EVENT_PORT_NO_NAME)) + if (s32 rc = sys_event_port_create(spurs.ptr(&CellSpurs::eventPort), SYS_EVENT_PORT_LOCAL, SYS_EVENT_PORT_NO_NAME)) { if (s32 rc2 = spursDetachLv2EventQueue(spurs, spurs->spuPort, true /*spursCreated*/)) { @@ -829,7 +829,7 @@ s32 spursFinalizeSpu(vm::ptr spurs) } } - if (s32 rc = sys_spu_image_close(spurs.of(&CellSpurs::spuImg))) + if (s32 rc = sys_spu_image_close(spurs.ptr(&CellSpurs::spuImg))) { throw EXCEPTION("sys_spu_image_close() failed (0x%x)", rc); } @@ -883,17 +883,17 @@ s32 spursStopEventHelper(PPUThread& ppu, vm::ptr spurs) /// Signal to the SPURS handler thread s32 spursSignalToHandlerThread(PPUThread& ppu, vm::ptr spurs) { - if (s32 rc = sys_lwmutex_lock(ppu, spurs.of(&CellSpurs::mutex), 0 /* forever */)) + if (s32 rc = sys_lwmutex_lock(ppu, spurs.ptr(&CellSpurs::mutex), 0 /* forever */)) { throw EXCEPTION("sys_lwmutex_lock() failed (0x%x)", rc); } - if (s32 rc = sys_lwcond_signal(ppu, spurs.of(&CellSpurs::cond))) + if (s32 rc = sys_lwcond_signal(ppu, spurs.ptr(&CellSpurs::cond))) { throw EXCEPTION("sys_lwcond_signal() failed (0x%x)", rc); } - if (s32 rc = sys_lwmutex_unlock(ppu, spurs.of(&CellSpurs::mutex))) + if (s32 rc = sys_lwmutex_unlock(ppu, spurs.ptr(&CellSpurs::mutex))) { throw EXCEPTION("sys_lwmutex_unlock() failed (0x%x)", rc); } @@ -1119,7 +1119,7 @@ s32 spursInit( if (s32 rc = sys_spu_thread_group_create(spuTgId, nSpus, spuPriority, spuTgAttr)) { - sys_spu_image_close(spurs.of(&CellSpurs::spuImg)); + sys_spu_image_close(spurs.ptr(&CellSpurs::spuImg)); return rollback(), rc; } @@ -1141,10 +1141,10 @@ s32 spursInit( spuThArgs->arg1 = (u64)num << 32; spuThArgs->arg2 = (u64)spurs.addr(); - if (s32 rc = sys_spu_thread_initialize(spuThreadId, spurs->spuTG, num, spurs.of(&CellSpurs::spuImg), spuThAttr, spuThArgs)) + if (s32 rc = sys_spu_thread_initialize(spuThreadId, spurs->spuTG, num, spurs.ptr(&CellSpurs::spuImg), spuThAttr, spuThArgs)) { sys_spu_thread_group_destroy(spurs->spuTG); - sys_spu_image_close(spurs.of(&CellSpurs::spuImg)); + sys_spu_image_close(spurs.ptr(&CellSpurs::spuImg)); return rollback(), rc; } @@ -1169,8 +1169,8 @@ s32 spursInit( } } - const auto lwMutex = spurs.of(&CellSpurs::mutex); - const auto lwCond = spurs.of(&CellSpurs::cond); + const auto lwMutex = spurs.ptr(&CellSpurs::mutex); + const auto lwCond = spurs.ptr(&CellSpurs::cond); auto sys_lwmutex_attribute_initialize = [](vm::ptr attr) { @@ -1240,7 +1240,7 @@ s32 spursInit( // TODO: Register libprof for user trace // Initialise the event port multiplexor - spursInitialiseEventPortMux(spurs.of(&CellSpurs::eventPortMux), spurs->spuPort, spurs->eventPort, 3); + spursInitialiseEventPortMux(spurs.ptr(&CellSpurs::eventPortMux), spurs->spuPort, spurs->eventPort, 3); // Enable the default system workload if required if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) @@ -1297,10 +1297,10 @@ s32 cellSpursInitializeWithAttribute(PPUThread& ppu, vm::ptr spurs, v attr->spuPriority, attr->ppuPriority, attr->flags | (attr->exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0), - attr.of(&CellSpursAttribute::prefix, 0), + attr.ptr(&CellSpursAttribute::prefix, 0), attr->prefixSize, attr->container, - attr.of(&CellSpursAttribute::swlPriority, 0), + attr.ptr(&CellSpursAttribute::swlPriority, 0), attr->swlMaxSpu, attr->swlIsPreem); } @@ -1334,10 +1334,10 @@ s32 cellSpursInitializeWithAttribute2(PPUThread& ppu, vm::ptr spurs, attr->spuPriority, attr->ppuPriority, attr->flags | (attr->exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | SAF_SECOND_VERSION, - attr.of(&CellSpursAttribute::prefix, 0), + attr.ptr(&CellSpursAttribute::prefix, 0), attr->prefixSize, attr->container, - attr.of(&CellSpursAttribute::swlPriority, 0), + attr.ptr(&CellSpursAttribute::swlPriority, 0), attr->swlMaxSpu, attr->swlIsPreem); } @@ -2477,7 +2477,7 @@ s32 cellSpursGetWorkloadFlag(vm::ptr spurs, vm::pptr spurs return CELL_SPURS_TASK_ERROR_INVAL; } - auto rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, attr.of(&CellSpursTasksetAttribute::priority), attr->max_contention, attr->name, attr->taskset_size, attr->enable_clear_ls); + auto rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, attr.ptr(&CellSpursTasksetAttribute::priority), attr->max_contention, attr->name, attr->taskset_size, attr->enable_clear_ls); if (attr->taskset_size >= sizeof32(CellSpursTaskset2)) { @@ -3860,7 +3860,7 @@ s32 cellSpursCreateTaskset2(PPUThread& ppu, vm::ptr spurs, vm::ptrargs, attr.of(&CellSpursTasksetAttribute2::priority), attr->max_contention, attr->name, sizeof32(CellSpursTaskset2), attr->enable_clear_ls)) + if (s32 rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, attr.ptr(&CellSpursTasksetAttribute2::priority), attr->max_contention, attr->name, sizeof32(CellSpursTaskset2), attr->enable_clear_ls)) { return rc; } diff --git a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp index 5a7c758320..bad9b5a4ac 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp @@ -112,13 +112,35 @@ void copy_fdset(fd_set* set, vm::ptr src) namespace sys_net { - struct tls_data_t + struct _tls_data_t { be_t _errno; be_t _h_errno; }; - thread_local vm::var g_tls_data; // TODO + thread_local vm::var<_tls_data_t, vm::page_alloc_t> g_tls_net_data; + + inline void initialize_tls() + { + if (!g_tls_net_data) + { + g_tls_net_data = { vm::main }; // allocate if not initialized + } + } + + vm::ref get_errno() + { + initialize_tls(); + + return g_tls_net_data.ref(&_tls_data_t::_errno); + } + + vm::ref get_h_errno() + { + initialize_tls(); + + return g_tls_net_data.ref(&_tls_data_t::_h_errno); + } // Functions s32 accept(s32 s, vm::ptr addr, vm::ptr paddrlen) @@ -128,7 +150,7 @@ namespace sys_net if (!addr) { int ret = ::accept(s, nullptr, nullptr); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } else { @@ -138,7 +160,7 @@ namespace sys_net ::socklen_t _paddrlen; s32 ret = ::accept(s, &_addr, &_paddrlen); *paddrlen = _paddrlen; - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } } @@ -154,7 +176,7 @@ namespace sys_net const char *ipaddr = ::inet_ntoa(saddr.sin_addr); libnet.Warning("binding on %s to port %d", ipaddr, ntohs(saddr.sin_port)); s32 ret = ::bind(s, (const ::sockaddr*)&saddr, addrlen); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -170,7 +192,7 @@ namespace sys_net const char *ipaddr = ::inet_ntoa(saddr.sin_addr); libnet.Warning("connecting on %s to port %d", ipaddr, ntohs(saddr.sin_port)); s32 ret = ::connect(s, (const ::sockaddr*)&saddr, addrlen); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -265,7 +287,7 @@ namespace sys_net libnet.Warning("listen(s=%d, backlog=%d)", s, backlog); s = g_socketMap[s]; s32 ret = ::listen(s, backlog); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -276,7 +298,7 @@ namespace sys_net s = g_socketMap[s]; s32 ret = ::recv(s, buf.get_ptr(), len, flags); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -292,7 +314,7 @@ namespace sys_net ::socklen_t _paddrlen; s32 ret = ::recvfrom(s, buf.get_ptr(), len, flags, &_addr, &_paddrlen); *paddrlen = _paddrlen; - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -309,7 +331,7 @@ namespace sys_net s = g_socketMap[s]; s32 ret = ::send(s, buf.get_ptr(), len, flags); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -329,7 +351,7 @@ namespace sys_net memcpy(&_addr, addr.get_ptr(), sizeof(::sockaddr)); _addr.sa_family = addr->sa_family; s32 ret = ::sendto(s, buf.get_ptr(), len, flags, &_addr, addrlen); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -340,7 +362,7 @@ namespace sys_net s = g_socketMap[s]; s32 ret = ::setsockopt(s, level, optname, optval.get_ptr(), optlen); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -351,7 +373,7 @@ namespace sys_net s = g_socketMap[s]; s32 ret = ::shutdown(s, how); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -361,7 +383,7 @@ namespace sys_net libnet.Warning("socket(family=%d, type=%d, protocol=%d)", family, type, protocol); s32 sock = ::socket(family, type, protocol); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); g_socketMap.push_back(sock); return g_socketMap.size() - 1; @@ -377,7 +399,7 @@ namespace sys_net #else int ret = ::close(s); #endif - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); return ret; } @@ -411,7 +433,7 @@ namespace sys_net copy_fdset(&_exceptfds, exceptfds); s32 ret = ::select(nfds, &_readfds, &_writefds, &_exceptfds, timeout ? &_timeout : NULL); - g_tls_data->_errno = getLastError(); + get_errno() = getLastError(); if (getLastError() >= 0) { @@ -492,7 +514,7 @@ namespace sys_net { libnet.Warning("_sys_net_errno_loc()"); - return g_tls_data.of(&tls_data_t::_errno); + return &get_errno(); } s32 sys_net_set_resolver_configurations() diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index 819e2aa7f4..49ec369aa1 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -42,8 +42,6 @@ wxDEFINE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent); IMPLEMENT_APP(Rpcs3App) Rpcs3App* TheApp; -extern std::string simplify_path(const std::string& path, bool is_dir); - extern std::unique_ptr g_msg_dialog; extern std::unique_ptr g_savedata_dialog;