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)
This commit is contained in:
Nekotekina 2015-08-18 15:31:48 +03:00
parent 6b6cd11fbe
commit 168cd9bb7a
8 changed files with 116 additions and 66 deletions

View File

@ -5,6 +5,8 @@ class ARMv7Thread;
namespace vm
{
template<typename T, typename AT> struct _ref_base;
// helper SFINAE type for vm::_ptr_base comparison operators (enables comparison between equal types and between any type and void*)
template<typename T1, typename T2, typename RT = void> using if_comparable_t = std::enable_if_t<
std::is_void<T1>::value ||
@ -33,19 +35,39 @@ namespace vm
return m_addr;
}
// get vm pointer to member
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ptr_base<MT> of(MT T2::*const member) const
// get vm pointer to a struct member
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ptr_base<MT> ptr(MT T2::*const member) const
{
const u32 offset = static_cast<u32>(reinterpret_cast<std::ptrdiff_t>(&(reinterpret_cast<T*>(0ull)->*member)));
return{ VM_CAST(m_addr + offset) };
}
// get vm pointer to array member with array subscribtion
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ptr_base<std::remove_extent_t<MT>> of(MT T2::*const member, u32 index) const
// get vm pointer to a struct member with array subscription
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ptr_base<std::remove_extent_t<MT>> ptr(MT T2::*const member, u32 index) const
{
const u32 offset = static_cast<u32>(reinterpret_cast<std::ptrdiff_t>(&(reinterpret_cast<T*>(0ull)->*member)));
return{ VM_CAST(m_addr + offset + sizeof32(T) * index) };
}
// get vm reference to a struct member
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ref_base<MT> ref(MT T2::*const member) const
{
const u32 offset = static_cast<u32>(reinterpret_cast<std::ptrdiff_t>(&(reinterpret_cast<T*>(0ull)->*member)));
return{ VM_CAST(m_addr + offset) };
}
// get vm reference to a struct member with array subscription
template<typename MT, typename T2, typename = if_comparable_t<T, T2>> _ref_base<std::remove_extent_t<MT>> ref(MT T2::*const member, u32 index) const
{
const u32 offset = static_cast<u32>(reinterpret_cast<std::ptrdiff_t>(&(reinterpret_cast<T*>(0ull)->*member)));
return{ VM_CAST(m_addr + offset + sizeof32(T) * index) };
}
// get vm reference
_ref_base<T, u32> ref() const
{
return{ VM_CAST(m_addr) };
}
template<typename CT> std::enable_if_t<std::is_assignable<AT&, CT>::value> set(const CT& value)
{

View File

@ -2,6 +2,8 @@
namespace vm
{
template<typename T, typename AT> struct _ptr_base;
template<typename T, typename AT = u32>
struct _ref_base
{
@ -33,7 +35,7 @@ namespace vm
}
// TODO: conversion operator (seems hard to define it correctly)
//template<typename CT, typename dummy = std::enable_if_t<std::is_convertible<T, CT>::value || std::is_convertible<to_ne_t<T>, CT>::value>> operator CT() const
//template<typename CT, typename = std::enable_if_t<std::is_convertible<T, CT>::value || std::is_convertible<to_ne_t<T>, CT>::value>> operator CT() const
//{
// return get_ref();
//}
@ -48,6 +50,12 @@ namespace vm
return get_ref();
}
// convert to vm pointer
vm::_ptr_base<T, u32> 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)

View File

@ -100,13 +100,13 @@ namespace vm
{
using _ptr_base<T>::m_addr;
using allocator = A<T>;
using allocation = A<T>;
public:
template<typename... Args, typename = std::enable_if_t<std::is_constructible<A<T>, Args...>::value>> _var_base(Args&&... args)
: allocator(std::forward<Args>(args)...)
: allocation(std::forward<Args>(args)...)
{
m_addr = allocator::get_addr();
m_addr = allocation::get_addr();
}
};

View File

@ -74,10 +74,10 @@ s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr<char> 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<char> 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 = {};

View File

@ -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);

View File

@ -411,7 +411,7 @@ s32 spursDetachLv2EventQueue(vm::ptr<CellSpurs> spurs, u8 spuPort, bool spursCre
/// Wait until a workload in the SPURS instance becomes ready
void spursHandlerWaitReady(PPUThread& ppu, vm::ptr<CellSpurs> 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<CellSpurs> 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<CellSpurs> 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<CellSpurs> 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<CellSpurs> spurs, u32 pp
const vm::var<char> 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<CellSpurs> 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<CellSpurs> spurs)
/// Signal to the SPURS handler thread
s32 spursSignalToHandlerThread(PPUThread& ppu, vm::ptr<CellSpurs> 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<sys_lwmutex_attribute_t> 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<CellSpurs> 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<CellSpurs> 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<CellSpurs> spurs, vm::pptr<CellSpursWorkloa
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
*flag = spurs.of(&CellSpurs::wklFlag);
*flag = spurs.ptr(&CellSpurs::wklFlag);
return CELL_OK;
}
@ -3438,7 +3438,7 @@ s32 cellSpursCreateTasksetWithAttribute(PPUThread& ppu, vm::ptr<CellSpurs> 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<CellSpurs> spurs, vm::ptr<Ce
_cellSpursTasksetAttribute2Initialize(attr, 0);
}
if (s32 rc = spursCreateTaskset(ppu, spurs, taskset, attr->args, 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;
}

View File

@ -112,13 +112,35 @@ void copy_fdset(fd_set* set, vm::ptr<sys_net::fd_set> src)
namespace sys_net
{
struct tls_data_t
struct _tls_data_t
{
be_t<s32> _errno;
be_t<s32> _h_errno;
};
thread_local vm::var<tls_data_t, vm::page_alloc_t> 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<s32> get_errno()
{
initialize_tls();
return g_tls_net_data.ref(&_tls_data_t::_errno);
}
vm::ref<s32> get_h_errno()
{
initialize_tls();
return g_tls_net_data.ref(&_tls_data_t::_h_errno);
}
// Functions
s32 accept(s32 s, vm::ptr<sockaddr> addr, vm::ptr<u32> 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()

View File

@ -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<MsgDialogInstance> g_msg_dialog;
extern std::unique_ptr<SaveDataDialogInstance> g_savedata_dialog;