Merge pull request #1032 from Nekotekina/master

lv2 sema/rwlock, bugfox, cleanup
This commit is contained in:
Raul Tambre 2015-03-08 15:00:54 +02:00
commit e5de176b16
28 changed files with 526 additions and 1068 deletions

View file

@ -132,5 +132,5 @@ void log_message(Log::LogType type, Log::LogSeverity sev, std::string text);
template<typename... Targs>
__noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args)
{
log_message(type, sev, fmt::detail::format(fmt, fmt::do_unveil(args)...));
log_message(type, sev, fmt::Format(fmt, fmt::do_unveil(args)...));
}

View file

@ -70,92 +70,6 @@ std::string fmt::to_sdec(s64 svalue)
return std::string(&res[first], sizeof(res) - first);
}
size_t fmt::detail::get_fmt_start(const char* fmt, size_t len)
{
for (size_t i = 0; i < len; i++)
{
if (fmt[i] == '%')
{
return i;
}
}
return len;
}
size_t fmt::detail::get_fmt_len(const char* fmt, size_t len)
{
assert(len >= 2 && fmt[0] == '%');
size_t res = 2;
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
res += 2;
fmt += 2;
len -= 2;
if (fmt[0] == '1')
{
assert(len >= 3 && fmt[1] - '0' < 7);
res++;
fmt++;
len--;
}
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
return res;
}
size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len)
{
assert(len >= 2);
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
if (fmt[2] == '1')
{
assert(len >= 5 && fmt[3] - '0' < 7);
return 10 + fmt[3] - '0';
}
return fmt[2] - '0';
}
return 1;
}
std::string fmt::detail::format(const char* fmt)
{
const size_t len = strlen(fmt);
const size_t fmt_start = get_fmt_start(fmt, len);
if (fmt_start != len)
{
throw "Excessive formatting: " + std::string(fmt, len);
}
return std::string(fmt, len);
}
extern const std::string fmt::placeholder = "???";
std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to)

View file

@ -177,366 +177,6 @@ namespace fmt
std::string to_udec(u64 value);
std::string to_sdec(s64 value);
std::string toupper(std::string source);
namespace detail
{
size_t get_fmt_start(const char* fmt, size_t len);
size_t get_fmt_len(const char* fmt, size_t len);
size_t get_fmt_precision(const char* fmt, size_t len);
template<typename T>
struct get_fmt
{
static_assert(!sizeof(T), "Unsupported fmt::format argument");
};
template<>
struct get_fmt<u8>
{
static std::string text(const char* fmt, size_t len, u8 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return to_udec(arg);
}
else
{
throw "Invalid formatting (u8): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<u16>
{
static std::string text(const char* fmt, size_t len, u16 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return to_udec(arg);
}
else
{
throw "Invalid formatting (u16): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<u32>
{
static std::string text(const char* fmt, size_t len, u32 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return to_udec(arg);
}
else
{
throw "Invalid formatting (u32): " + std::string(fmt, len);
}
}
};
#ifdef __APPLE__
template<>
struct get_fmt<unsigned long>
{
static std::string text(const char* fmt, size_t len, unsigned long arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return to_udec(arg);
}
else
{
throw "Invalid formatting (unsigned long): " + std::string(fmt, len);
}
}
};
#endif
template<>
struct get_fmt<u64>
{
static std::string text(const char* fmt, size_t len, u64 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return to_udec(arg);
}
else
{
throw "Invalid formatting (u64): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<s8>
{
static std::string text(const char* fmt, size_t len, s8 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u8)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u8)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd')
{
return to_sdec(arg);
}
else
{
throw "Invalid formatting (s8): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<s16>
{
static std::string text(const char* fmt, size_t len, s16 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u16)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u16)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd')
{
return to_sdec(arg);
}
else
{
throw "Invalid formatting (s16): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<s32>
{
static std::string text(const char* fmt, size_t len, s32 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u32)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u32)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd')
{
return to_sdec(arg);
}
else
{
throw "Invalid formatting (s32): " + std::string(fmt, len);
}
}
};
#ifdef __APPLE__
template<>
struct get_fmt<long>
{
static std::string text(const char* fmt, size_t len, long arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u64)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd')
{
return to_sdec(arg);
}
else
{
throw "Invalid formatting (long): " + std::string(fmt, len);
}
}
};
#endif
template<>
struct get_fmt<s64>
{
static std::string text(const char* fmt, size_t len, s64 arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u64)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'd')
{
return to_sdec(arg);
}
else
{
throw "Invalid formatting (s64): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<float>
{
static std::string text(const char* fmt, size_t len, float arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u32&)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u32&)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'f')
{
return std::to_string(arg);
}
else
{
throw "Invalid formatting (float): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<double>
{
static std::string text(const char* fmt, size_t len, double arg)
{
if (fmt[len - 1] == 'x')
{
return to_hex((u64&)arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'X')
{
return fmt::toupper(to_hex((u64&)arg, get_fmt_precision(fmt, len)));
}
else if (fmt[len - 1] == 'f')
{
return std::to_string(arg);
}
else
{
throw "Invalid formatting (double): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<bool>
{
static std::string text(const char* fmt, size_t len, bool arg)
{
if (fmt[len - 1] == 'x' || fmt[len - 1] == 'X')
{
return to_hex(arg, get_fmt_precision(fmt, len));
}
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
{
return arg ? "1" : "0";
}
else if (fmt[len - 1] == 's')
{
return arg ? "true" : "false";
}
else
{
throw "Invalid formatting (bool): " + std::string(fmt, len);
}
}
};
template<>
struct get_fmt<const char*>
{
static std::string text(const char* fmt, size_t len, const char* arg)
{
if (fmt[len - 1] == 's')
{
return arg;
}
else
{
throw "Invalid formatting (const char*): " + std::string(fmt, len);
}
}
};
std::string format(const char* fmt); // terminator
template<typename T, typename... Args>
std::string format(const char* fmt, const T& arg, Args... args)
{
const size_t len = strlen(fmt);
const size_t fmt_start = get_fmt_start(fmt, len);
const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start);
const size_t fmt_end = fmt_start + fmt_len;
return std::string(fmt, fmt_start) + get_fmt<T>::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, args...);
}
};
template<typename T, bool is_enum = std::is_enum<T>::value>
struct unveil
{
@ -612,24 +252,12 @@ namespace fmt
/*
fmt::format(const char* fmt, args...)
Formatting function with very limited functionality (compared to printf-like formatting) and be_t<> support
Formatting function with special functionality:
Supported types:
std::string forced to .c_str()
be_t<> forced to .value() (fmt::unveil reverts byte order automatically)
u8, s8 (%x, %d)
u16, s16 (%x, %d)
u32, s32 (%x, %d)
u64, s64 (%x, %d)
float (%x, %f)
double (%x, %f)
bool (%x, %d, %s)
char* (%s)
std::string forced to .c_str() (fmt::unveil)
be_t<> of any appropriate type in this list (fmt::unveil)
enum of any appropriate type in this list (fmt::unveil)
External specializations (can be found in another headers):
External specializations for fmt::unveil (can be found in another headers):
vm::ps3::ptr (fmt::unveil) (vm_ptr.h) (with appropriate address type, using .addr() can be avoided)
vm::ps3::bptr (fmt::unveil) (vm_ptr.h)
vm::psv::ptr (fmt::unveil) (vm_ptr.h)
@ -637,18 +265,11 @@ namespace fmt
vm::ps3::bref (fmt::unveil) (vm_ref.h)
vm::psv::ref (fmt::unveil) (vm_ref.h)
Supported formatting:
%d - decimal; to_sdec() and to_udec()
%x - hexadecimal; to_hex(), %08x - hexadecimal with minimal length (from 02 to 016)
%s - string; generates "true" or "false" for bool
%f - floating point; only basic std::to_string() functionality
Other features are not supported.
*/
template<typename... Args>
__forceinline __safebuffers std::string format(const char* fmt, Args... args)
{
return detail::format(fmt, do_unveil(args)...);
return Format(fmt, do_unveil(args)...);
}
//convert a wxString to a std::string encoded in utf8

View file

@ -1472,63 +1472,12 @@ bool waiter_map_t::is_stopped(u64 signal_id)
{
if (Emu.IsStopped())
{
LOG_WARNING(Log::HLE, "%s: waiter_op() aborted (signal_id=0x%llx)", m_name.c_str(), signal_id);
LOG_WARNING(Log::HLE, "%s: waiter_op() aborted (signal_id=0x%llx)", name.c_str(), signal_id);
return true;
}
return false;
}
void waiter_map_t::waiter_reg_t::init()
{
if (!thread)
{
thread = GetCurrentNamedThread();
std::lock_guard<std::mutex> lock(map.m_mutex);
// add waiter
map.m_waiters.push_back({ signal_id, thread });
}
}
waiter_map_t::waiter_reg_t::~waiter_reg_t()
{
if (thread)
{
std::lock_guard<std::mutex> lock(map.m_mutex);
// remove waiter
for (s64 i = map.m_waiters.size() - 1; i >= 0; i--)
{
if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread)
{
map.m_waiters.erase(map.m_waiters.begin() + i);
return;
}
}
LOG_ERROR(HLE, "%s(): waiter not found (signal_id=0x%llx, map='%s')", __FUNCTION__, signal_id, map.m_name.c_str());
Emu.Pause();
}
}
void waiter_map_t::notify(u64 signal_id)
{
if (m_waiters.size())
{
std::lock_guard<std::mutex> lock(m_mutex);
// find waiter and signal
for (auto& v : m_waiters)
{
if (v.signal_id == signal_id)
{
v.thread->Notify();
}
}
}
}
const std::function<bool()> SQUEUE_ALWAYS_EXIT = [](){ return true; };
const std::function<bool()> SQUEUE_NEVER_EXIT = [](){ return false; };

View file

@ -103,65 +103,54 @@ class slw_shared_mutex_t
};
class waiter_map_t
struct waiter_map_t
{
// TODO: optimize (use custom lightweight readers-writer lock)
std::mutex m_mutex;
static const size_t size = 32;
struct waiter_t
{
u64 signal_id;
NamedThreadBase* thread;
};
std::array<std::mutex, size> mutex;
std::array<std::condition_variable, size> cv;
std::vector<waiter_t> m_waiters;
const std::string name;
std::string m_name;
struct waiter_reg_t
{
NamedThreadBase* thread;
const u64 signal_id;
waiter_map_t& map;
waiter_reg_t(waiter_map_t& map, u64 signal_id)
: thread(nullptr)
, signal_id(signal_id)
, map(map)
{
}
~waiter_reg_t();
void init();
};
bool is_stopped(u64 signal_id);
public:
waiter_map_t(const char* name)
: m_name(name)
: name(name)
{
}
bool is_stopped(u64 signal_id);
// wait until waiter_func() returns true, signal_id is an arbitrary number
template<typename WT> __forceinline void wait_op(u64 signal_id, const WT waiter_func)
template<typename S, typename WT> __forceinline __safebuffers void wait_op(const S& signal_id, const WT waiter_func)
{
// register waiter
waiter_reg_t waiter(*this, signal_id);
// generate hash
const auto hash = std::hash<S>()(signal_id) % size;
// set mutex locker
std::unique_lock<std::mutex> locker(mutex[hash], std::defer_lock);
// check the condition or if the emulator is stopped
while (!waiter_func() && !is_stopped(signal_id))
{
// initialize waiter (only once)
waiter.init();
// wait for 1 ms or until signal arrived
waiter.thread->WaitForAnySignal(1);
// lock the mutex and initialize waiter (only once)
if (!locker.owns_lock())
{
locker.lock();
}
// wait on appropriate condition variable for 1 ms or until signal arrived
cv[hash].wait_for(locker, std::chrono::milliseconds(1));
}
}
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
void notify(u64 signal_id);
template<typename S> __forceinline void notify(const S& signal_id)
{
// generate hash
const auto hash = std::hash<S>()(signal_id) % size;
// signal appropriate condition variable
cv[hash].notify_all();
}
};
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;

View file

@ -110,4 +110,4 @@ psv_log_base sceDisplay("SceDisplay", []()
REG_FUNC(0x3E796EF5, sceDisplayWaitSetFrameBufMultiCB);
REG_FUNC(0x6BDF4C4D, sceDisplayRegisterVblankStartCallback);
REG_FUNC(0x98436A80, sceDisplayUnregisterVblankStartCallback);
});
});

View file

@ -44,7 +44,7 @@ s32 sceKernelCreateThread(
s32 cpuAffinityMask,
vm::psv::ptr<const SceKernelThreadOptParam> pOptParam)
{
sceLibKernel.Warning("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)",
sceLibKernel.Warning("sceKernelCreateThread(pName=*0x%x, entry=*0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=*0x%x)",
pName, entry, initPriority, stackSize, attr, cpuAffinityMask, pOptParam);
auto t = Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
@ -62,7 +62,7 @@ s32 sceKernelCreateThread(
s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr<const void> pArgBlock)
{
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock);
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
@ -185,7 +185,7 @@ s32 sceKernelChangeCurrentThreadAttr(u32 clearAttr, u32 setAttr)
s32 sceKernelGetThreadExitStatus(s32 threadId, vm::psv::ptr<s32> pExitStatus)
{
sceLibKernel.Todo("sceKernelGetThreadExitStatus(threadId=0x%x, pExitStatus=0x%x)", threadId, pExitStatus);
sceLibKernel.Todo("sceKernelGetThreadExitStatus(threadId=0x%x, pExitStatus=*0x%x)", threadId, pExitStatus);
throw __FUNCTION__;
}
@ -206,21 +206,21 @@ s32 sceKernelCheckWaitableStatus()
s32 sceKernelGetThreadInfo(s32 threadId, vm::psv::ptr<SceKernelThreadInfo> pInfo)
{
sceLibKernel.Todo("sceKernelGetThreadInfo(threadId=0x%x, pInfo=0x%x)", threadId, pInfo);
sceLibKernel.Todo("sceKernelGetThreadInfo(threadId=0x%x, pInfo=*0x%x)", threadId, pInfo);
throw __FUNCTION__;
}
s32 sceKernelGetThreadRunStatus(vm::psv::ptr<SceKernelThreadRunStatus> pStatus)
{
sceLibKernel.Todo("sceKernelGetThreadRunStatus(pStatus=0x%x)", pStatus);
sceLibKernel.Todo("sceKernelGetThreadRunStatus(pStatus=*0x%x)", pStatus);
throw __FUNCTION__;
}
s32 sceKernelGetSystemInfo(vm::psv::ptr<SceKernelSystemInfo> pInfo)
{
sceLibKernel.Todo("sceKernelGetSystemInfo(pInfo=0x%x)", pInfo);
sceLibKernel.Todo("sceKernelGetSystemInfo(pInfo=*0x%x)", pInfo);
throw __FUNCTION__;
}
@ -262,7 +262,7 @@ s32 sceKernelDelayThreadCB(u32 usec)
s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv::ptr<u32> pTimeout)
{
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout);
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7);
@ -297,7 +297,7 @@ s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv:
s32 sceKernelWaitThreadEndCB(s32 threadId, vm::psv::ptr<s32> pExitStatus, vm::psv::ptr<u32> pTimeout)
{
sceLibKernel.Todo("sceKernelWaitThreadEndCB(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout);
sceLibKernel.Todo("sceKernelWaitThreadEndCB(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
throw __FUNCTION__;
}
@ -395,7 +395,7 @@ s32 sceKernelWaitMultipleEventsCB(vm::psv::ptr<SceKernelWaitEvent> pWaitEventLis
s32 sceKernelCreateEventFlag(vm::psv::ptr<const char> pName, u32 attr, u32 initPattern, vm::psv::ptr<const SceKernelEventFlagOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateEventFlag(pName=0x%x, attr=0x%x, initPattern=0x%x, pOptParam=0x%x)", pName, attr, initPattern, pOptParam);
sceLibKernel.Error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam);
if (s32 id = g_psv_ef_list.add(new psv_event_flag_t(pName.get_ptr(), attr, initPattern), 0))
{
@ -459,7 +459,7 @@ s32 sceKernelGetEventFlagInfo(s32 evfId, vm::psv::ptr<SceKernelEventFlagInfo> pI
s32 sceKernelCreateSema(vm::psv::ptr<const char> pName, u32 attr, s32 initCount, s32 maxCount, vm::psv::ptr<const SceKernelSemaOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateSema(pName=0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=0x%x)", pName, attr, initCount, maxCount, pOptParam);
sceLibKernel.Error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam);
if (s32 id = g_psv_sema_list.add(new psv_sema_t(pName.get_ptr(), attr, initCount, maxCount), 0))
{
@ -500,7 +500,7 @@ s32 sceKernelCloseSema(s32 semaId)
s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::psv::ptr<u32> pTimeout)
{
sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=0x%x)", semaId, needCount, pTimeout);
sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout);
ref_t<psv_sema_t> sema = g_psv_sema_list.get(semaId);
@ -543,7 +543,7 @@ s32 sceKernelGetSemaInfo(s32 semaId, vm::psv::ptr<SceKernelSemaInfo> pInfo)
s32 sceKernelCreateMutex(vm::psv::ptr<const char> pName, u32 attr, s32 initCount, vm::psv::ptr<const SceKernelMutexOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateMutex(pName=0x%x, attr=0x%x, initCount=%d, pOptParam=0x%x)", pName, attr, initCount, pOptParam);
sceLibKernel.Error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam);
if (s32 id = g_psv_mutex_list.add(new psv_mutex_t(pName.get_ptr(), attr, initCount), 0))
{
@ -644,7 +644,7 @@ s32 sceKernelGetLwMutexInfoById(s32 lwMutexId, vm::psv::ptr<SceKernelLwMutexInfo
s32 sceKernelCreateCond(vm::psv::ptr<const char> pName, u32 attr, s32 mutexId, vm::psv::ptr<const SceKernelCondOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateCond(pName=0x%x, attr=0x%x, mutexId=0x%x, pOptParam=0x%x)", pName, attr, mutexId, pOptParam);
sceLibKernel.Error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam);
if (s32 id = g_psv_cond_list.add(new psv_cond_t(pName.get_ptr(), attr, mutexId), 0))
{

View file

@ -150,7 +150,7 @@ namespace sce_libc_func
{
void __cxa_atexit(vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> arg, vm::psv::ptr<void> dso)
{
sceLibc.Warning("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso);
sceLibc.Warning("__cxa_atexit(func=*0x%x, arg=*0x%x, dso=*0x%x)", func, arg, dso);
LV2_LOCK;
@ -162,7 +162,7 @@ namespace sce_libc_func
void __aeabi_atexit(vm::psv::ptr<void> arg, vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> dso)
{
sceLibc.Warning("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso);
sceLibc.Warning("__aeabi_atexit(arg=*0x%x, func=*0x%x, dso=*0x%x)", arg, func, dso);
LV2_LOCK;
@ -195,7 +195,7 @@ namespace sce_libc_func
void printf(ARMv7Context& context, vm::psv::ptr<const char> fmt) // va_args...
{
sceLibc.Warning("printf(fmt=0x%x)", fmt);
sceLibc.Warning("printf(fmt=*0x%x)", fmt);
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
const std::string& result = armv7_fmt(context, fmt, 1, 0, 0);
@ -206,7 +206,7 @@ namespace sce_libc_func
void sprintf(ARMv7Context& context, vm::psv::ptr<char> str, vm::psv::ptr<const char> fmt) // va_args...
{
sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
sceLibc.Warning("sprintf(str=*0x%x, fmt=*0x%x)", str, fmt);
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
const std::string& result = armv7_fmt(context, fmt, 2, 0, 0);
@ -217,28 +217,28 @@ namespace sce_libc_func
void __cxa_set_dso_handle_main(vm::psv::ptr<void> dso)
{
sceLibc.Warning("__cxa_set_dso_handle_main(dso=0x%x)", dso);
sceLibc.Warning("__cxa_set_dso_handle_main(dso=*0x%x)", dso);
g_dso = dso;
}
void memcpy(vm::psv::ptr<void> dst, vm::psv::ptr<const void> src, u32 size)
{
sceLibc.Warning("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size);
sceLibc.Warning("memcpy(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
::memcpy(dst.get_ptr(), src.get_ptr(), size);
}
void memset(vm::psv::ptr<void> dst, s32 value, u32 size)
{
sceLibc.Warning("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size);
sceLibc.Warning("memset(dst=*0x%x, value=%d, size=0x%x)", dst, value, size);
::memset(dst.get_ptr(), value, size);
}
void _Assert(ARMv7Context& context, vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
{
sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func);
sceLibc.Error("_Assert(text=*0x%x, func=*0x%x)", text, func);
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
LOG_NOTICE(ARMv7, context.thread.RegsToString());

View file

@ -187,7 +187,7 @@ s32 scePerfArmPmonStop(ARMv7Context& context, s32 threadId)
s32 scePerfArmPmonGetCounterValue(ARMv7Context& context, s32 threadId, u32 counter, vm::psv::ptr<u32> pValue)
{
scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=0x%x)", threadId, counter, pValue);
scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=*0x%x)", threadId, counter, pValue);
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{

View file

@ -2004,7 +2004,29 @@ void Compiler::BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) {
}
void Compiler::HACK(u32 index) {
Call<void>("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index));
if (index & EIF_SAVE_RTOC) {
auto addr_i64 = (Value *)m_ir_builder->getInt64(0x28);
auto ra_i64 = GetGpr(1);
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
WriteMemory(addr_i64, GetGpr(2, 64));
}
Call<void>("execute_ppu_func_by_index", &execute_ppu_func_by_index, m_state.args[CompileTaskState::Args::State], m_ir_builder->getInt32(index & ~EIF_FLAGS));
if (index & EIF_PERFORM_BLR) {
auto lr_i64 = GetLr();
lr_i64 = m_ir_builder->CreateAnd(lr_i64, ~0x3ULL);
auto lr_i32 = m_ir_builder->CreateTrunc(lr_i64, m_ir_builder->getInt32Ty());
CreateBranch(nullptr, lr_i32, false, true);
}
// copied from Compiler::SC()
auto ret_i1 = Call<bool>("PollStatus", m_poll_status_function, m_state.args[CompileTaskState::Args::State]);
auto cmp_i1 = m_ir_builder->CreateICmpEQ(ret_i1, m_ir_builder->getInt1(true));
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then_true");
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge_true");
m_ir_builder->CreateCondBr(cmp_i1, then_bb, merge_bb);
m_ir_builder->SetInsertPoint(then_bb);
m_ir_builder->CreateRet(m_ir_builder->getInt32(0xFFFFFFFF));
m_ir_builder->SetInsertPoint(merge_bb);
}
void Compiler::SC(u32 lev) {

View file

@ -28,7 +28,6 @@ PPUThread& GetCurrentPPUThread()
PPUThread::PPUThread() : CPUThread(CPU_THREAD_PPU)
{
owned_mutexes = 0;
Reset();
}

View file

@ -536,7 +536,6 @@ public:
//TBR : Time-Base Registers
u64 TB; //TBR 0x10C - 0x10D
u32 owned_mutexes;
std::function<void(PPUThread& CPU)> custom_task;
public:

View file

@ -20,7 +20,7 @@ class LogBase
template<typename... Targs>
__noinline void LogPrepare(LogType type, const char* fmt, Targs... args) const
{
LogOutput(type, fmt::detail::format(fmt, args...));
LogOutput(type, fmt::Format(fmt, args...));
}
public:

View file

@ -347,12 +347,18 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
if (!stream.peek(code))
{
// demuxing finished
dmux.is_running = false;
// callback
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(dmux.memAddr + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
dmux.cbFunc(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
dmux.is_running = false;
dmux.is_working = false;
stream = {};
continue;
}
@ -634,16 +640,20 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
case dmuxResetStream:
case dmuxResetStreamAndWaitDone:
{
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(dmux.memAddr + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
dmux.cbFunc(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
// demuxing stopped
if (dmux.is_running.exchange(false))
{
// callback
auto dmuxMsg = vm::ptr<CellDmuxMsg>::make(dmux.memAddr + (cb_add ^= 16));
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
dmux.cbFunc(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg);
stream = {};
dmux.is_working = false;
}
stream = {};
dmux.is_running = false;
//if (task.type == dmuxResetStreamAndWaitDone)
//{
//}
break;
}
@ -926,8 +936,16 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
return CELL_DMUX_ERROR_ARG;
}
if (!dmux->is_running)
{
return CELL_OK;
}
dmux->is_working = true;
dmux->job.push(DemuxerTask(dmuxResetStreamAndWaitDone), &dmux->is_closed);
while (dmux->is_running && !dmux->is_closed) // TODO: ensure that it is safe
while (dmux->is_running && dmux->is_working && !dmux->is_closed) // TODO: ensure that it is safe
{
if (Emu.IsStopped())
{
@ -936,6 +954,7 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
return CELL_OK;
}

View file

@ -404,6 +404,7 @@ public:
volatile bool is_finished;
volatile bool is_closed;
std::atomic<bool> is_running;
std::atomic<bool> is_working;
PPUThread* dmuxCb;
@ -411,6 +412,7 @@ public:
: is_finished(false)
, is_closed(false)
, is_running(false)
, is_working(false)
, memAddr(addr)
, memSize(size)
, cbFunc(func)

View file

@ -813,7 +813,7 @@ int cellSailPlayerCancel()
int cellSailPlayerSetPaused(vm::ptr<CellSailPlayer> pSelf, bool paused)
{
cellSail.Todo("cellSailPlayerSetPaused(pSelf_addr=0x%x, paused=)", pSelf.addr(), paused);
cellSail.Todo("cellSailPlayerSetPaused(pSelf_addr=0x%x, paused=%d)", pSelf.addr(), paused);
return CELL_OK;
}

View file

@ -32,19 +32,20 @@ s32 syncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
// prx: set zero and sync
mutex->data.exchange({});
return CELL_OK;
}
s32 cellSyncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
{
cellSync.Log("cellSyncMutexInitialize(mutex_addr=0x%x)", mutex.addr());
cellSync.Log("cellSyncMutexInitialize(mutex=*0x%x)", mutex);
return syncMutexInitialize(mutex);
}
s32 cellSyncMutexLock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.Log("cellSyncMutexLock(mutex_addr=0x%x)", mutex.addr());
cellSync.Log("cellSyncMutexLock(mutex=*0x%x)", mutex);
if (!mutex)
{
@ -70,12 +71,13 @@ s32 cellSyncMutexLock(vm::ptr<CellSyncMutex> mutex)
// prx: sync
mutex->data.read_sync();
return CELL_OK;
}
s32 cellSyncMutexTryLock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.Log("cellSyncMutexTryLock(mutex_addr=0x%x)", mutex.addr());
cellSync.Log("cellSyncMutexTryLock(mutex=*0x%x)", mutex);
if (!mutex)
{
@ -99,7 +101,7 @@ s32 cellSyncMutexTryLock(vm::ptr<CellSyncMutex> mutex)
s32 cellSyncMutexUnlock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.Log("cellSyncMutexUnlock(mutex_addr=0x%x)", mutex.addr());
cellSync.Log("cellSyncMutexUnlock(mutex=*0x%x)", mutex);
if (!mutex)
{
@ -116,6 +118,7 @@ s32 cellSyncMutexUnlock(vm::ptr<CellSyncMutex> mutex)
});
g_sync_mutex_wm.notify(mutex.addr());
return CELL_OK;
}
@ -136,12 +139,13 @@ s32 syncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count)
// prx: zeroize first u16, write total_count in second u16 and sync
barrier->data.exchange({ be_t<s16>::make(0), be_t<s16>::make(total_count) });
return CELL_OK;
}
s32 cellSyncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count)
{
cellSync.Log("cellSyncBarrierInitialize(barrier_addr=0x%x, total_count=%d)", barrier.addr(), total_count);
cellSync.Log("cellSyncBarrierInitialize(barrier=*0x%x, total_count=%d)", barrier, total_count);
return syncBarrierInitialize(barrier, total_count);
}
@ -149,24 +153,26 @@ s32 cellSyncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 total_count)
s32 syncBarrierTryNotifyOp(CellSyncBarrier::data_t& barrier)
{
// prx: extract m_value (repeat if < 0), increase, compare with second s16, set sign bit if equal, insert it back
s16 value = (s16)barrier.m_value;
s16 value = barrier.m_value;
if (value < 0)
{
return CELL_SYNC_ERROR_BUSY;
}
value++;
if (value == (s16)barrier.m_count)
if (++value == barrier.m_count)
{
value |= 0x8000;
}
barrier.m_value = value;
return CELL_OK;
};
s32 cellSyncBarrierNotify(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.Log("cellSyncBarrierNotify(barrier_addr=0x%x)", barrier.addr());
cellSync.Log("cellSyncBarrierNotify(barrier=*0x%x)", barrier);
if (!barrier)
{
@ -183,12 +189,13 @@ s32 cellSyncBarrierNotify(vm::ptr<CellSyncBarrier> barrier)
});
g_sync_barrier_wait_wm.notify(barrier.addr());
return CELL_OK;
}
s32 cellSyncBarrierTryNotify(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.Log("cellSyncBarrierTryNotify(barrier_addr=0x%x)", barrier.addr());
cellSync.Log("cellSyncBarrierTryNotify(barrier=*0x%x)", barrier);
if (!barrier)
{
@ -205,30 +212,33 @@ s32 cellSyncBarrierTryNotify(vm::ptr<CellSyncBarrier> barrier)
}
g_sync_barrier_wait_wm.notify(barrier.addr());
return CELL_OK;
}
s32 syncBarrierTryWaitOp(CellSyncBarrier::data_t& barrier)
{
// prx: extract m_value (repeat if >= 0), decrease it, set 0 if == 0x8000, insert it back
s16 value = (s16)barrier.m_value;
s16 value = barrier.m_value;
if (value >= 0)
{
return CELL_SYNC_ERROR_BUSY;
}
value--;
if (value == (s16)0x8000)
if (--value == -0x8000)
{
value = 0;
}
barrier.m_value = value;
return CELL_OK;
}
s32 cellSyncBarrierWait(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.Log("cellSyncBarrierWait(barrier_addr=0x%x)", barrier.addr());
cellSync.Log("cellSyncBarrierWait(barrier=*0x%x)", barrier);
if (!barrier)
{
@ -245,12 +255,13 @@ s32 cellSyncBarrierWait(vm::ptr<CellSyncBarrier> barrier)
});
g_sync_barrier_notify_wm.notify(barrier.addr());
return CELL_OK;
}
s32 cellSyncBarrierTryWait(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.Log("cellSyncBarrierTryWait(barrier_addr=0x%x)", barrier.addr());
cellSync.Log("cellSyncBarrierTryWait(barrier=*0x%x)", barrier);
if (!barrier)
{
@ -267,6 +278,7 @@ s32 cellSyncBarrierTryWait(vm::ptr<CellSyncBarrier> barrier)
}
g_sync_barrier_notify_wm.notify(barrier.addr());
return CELL_OK;
}
@ -289,12 +301,13 @@ s32 syncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer
rwm->m_size = be_t<u32>::make(buffer_size);
rwm->m_buffer = buffer;
rwm->data.exchange({});
return CELL_OK;
}
s32 cellSyncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer_size)
{
cellSync.Log("cellSyncRwmInitialize(rwm_addr=0x%x, buffer_addr=0x%x, buffer_size=0x%x)", rwm.addr(), buffer.addr(), buffer_size);
cellSync.Log("cellSyncRwmInitialize(rwm=*0x%x, buffer=*0x%x, buffer_size=0x%x)", rwm, buffer, buffer_size);
return syncRwmInitialize(rwm, buffer, buffer_size);
}
@ -307,6 +320,7 @@ s32 syncRwmTryReadBeginOp(CellSyncRwm::data_t& rwm)
}
rwm.m_readers++;
return CELL_OK;
}
@ -318,12 +332,13 @@ s32 syncRwmReadEndOp(CellSyncRwm::data_t& rwm)
}
rwm.m_readers--;
return CELL_OK;
}
s32 cellSyncRwmRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncRwmRead(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.addr(), buffer.addr());
cellSync.Log("cellSyncRwmRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
{
@ -341,7 +356,7 @@ s32 cellSyncRwmRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
});
// copy data to buffer_addr
memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), (u32)rwm->m_size);
memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), rwm->m_size);
// prx: decrease m_readers (return 0x8041010C if already zero)
if (s32 res = rwm->data.atomic_op(CELL_OK, syncRwmReadEndOp))
@ -351,12 +366,13 @@ s32 cellSyncRwmRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
}
g_sync_rwm_write_wm.notify(rwm.addr());
return CELL_OK;
}
s32 cellSyncRwmTryRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncRwmTryRead(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.addr(), buffer.addr());
cellSync.Log("cellSyncRwmTryRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
{
@ -372,7 +388,7 @@ s32 cellSyncRwmTryRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
return res;
}
memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), (u32)rwm->m_size);
memcpy(buffer.get_ptr(), rwm->m_buffer.get_ptr(), rwm->m_size);
if (s32 res = rwm->data.atomic_op(CELL_OK, syncRwmReadEndOp))
{
@ -380,6 +396,7 @@ s32 cellSyncRwmTryRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
}
g_sync_rwm_write_wm.notify(rwm.addr());
return CELL_OK;
}
@ -391,12 +408,13 @@ s32 syncRwmTryWriteBeginOp(CellSyncRwm::data_t& rwm)
}
rwm.m_writers = 1;
return CELL_OK;
}
s32 cellSyncRwmWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
{
cellSync.Log("cellSyncRwmWrite(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.addr(), buffer.addr());
cellSync.Log("cellSyncRwmWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
{
@ -419,17 +437,19 @@ s32 cellSyncRwmWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
});
// prx: copy data from buffer_addr
memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), (u32)rwm->m_size);
memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), rwm->m_size);
// prx: sync and zeroize m_readers and m_writers
rwm->data.exchange({});
g_sync_rwm_read_wm.notify(rwm.addr());
return CELL_OK;
}
s32 cellSyncRwmTryWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
{
cellSync.Log("cellSyncRwmTryWrite(rwm_addr=0x%x, buffer_addr=0x%x)", rwm.addr(), buffer.addr());
cellSync.Log("cellSyncRwmTryWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
{
@ -447,11 +467,13 @@ s32 cellSyncRwmTryWrite(vm::ptr<CellSyncRwm> rwm, vm::ptr<const void> buffer)
}
// prx: copy data from buffer_addr
memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), (u32)rwm->m_size);
memcpy(rwm->m_buffer.get_ptr(), buffer.get_ptr(), rwm->m_size);
// prx: sync and zeroize m_readers and m_writers
rwm->data.exchange({});
g_sync_rwm_read_wm.notify(rwm.addr());
return CELL_OK;
}
@ -479,20 +501,22 @@ s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 si
queue->m_depth = be_t<u32>::make(depth);
queue->m_buffer.set(buffer.addr());
queue->data.exchange({});
return CELL_OK;
}
s32 cellSyncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth)
{
cellSync.Log("cellSyncQueueInitialize(queue_addr=0x%x, buffer_addr=0x%x, size=0x%x, depth=0x%x)", queue.addr(), buffer.addr(), size, depth);
cellSync.Log("cellSyncQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x)", queue, buffer, size, depth);
return syncQueueInitialize(queue, buffer, size, depth);
}
s32 syncQueueTryPushOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
{
const u32 v1 = (u32)queue.m_v1;
const u32 v2 = (u32)queue.m_v2;
const u32 v1 = queue.m_v1;
const u32 v2 = queue.m_v2;
// prx: compare 5th u8 with zero (break if not zero)
// prx: compare (second u32 (u24) + first u8) with depth (break if greater or equal)
if ((v2 >> 24) || ((v2 & 0xffffff) + (v1 >> 24)) >= depth)
@ -506,12 +530,13 @@ s32 syncQueueTryPushOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
position = (v1 & 0xffffff);
queue.m_v1 = (v1 & 0xff000000) | ((position + 1) % depth);
queue.m_v2 = (1 << 24) | ((v2 & 0xffffff) + 1);
return CELL_OK;
}
s32 cellSyncQueuePush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffer)
{
cellSync.Log("cellSyncQueuePush(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueuePush(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -522,10 +547,10 @@ s32 cellSyncQueuePush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffer)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
g_sync_queue_wm.wait_op(queue.addr(), [queue, depth, &position]()
@ -541,13 +566,15 @@ s32 cellSyncQueuePush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffer)
// prx: atomically insert 0 in 5th u8
queue->data &= { be_t<u32>::make(~0), be_t<u32>::make(0xffffff) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffer)
{
cellSync.Log("cellSyncQueueTryPush(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueueTryPush(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -558,10 +585,10 @@ s32 cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffe
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32
@ -574,15 +601,19 @@ s32 cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::ptr<const void> buffe
}
memcpy(&queue->m_buffer[position * size], buffer.get_ptr(), size);
queue->data &= { be_t<u32>::make(~0), be_t<u32>::make(0xffffff) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 syncQueueTryPopOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
{
const u32 v1 = (u32)queue.m_v1;
const u32 v2 = (u32)queue.m_v2;
const u32 v1 = queue.m_v1;
const u32 v2 = queue.m_v2;
// prx: extract first u8, repeat if not zero
// prx: extract second u32 (u24), subtract 5th u8, compare with zero, repeat if less or equal
if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24)))
@ -596,12 +627,13 @@ s32 syncQueueTryPopOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
queue.m_v1 = 0x1000000 | v1;
position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth;
queue.m_v2 = (v2 & 0xff000000) | ((v2 & 0xffffff) - 1);
return CELL_OK;
}
s32 cellSyncQueuePop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncQueuePop(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueuePop(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -612,10 +644,10 @@ s32 cellSyncQueuePop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
g_sync_queue_wm.wait_op(queue.addr(), [queue, depth, &position]()
@ -631,13 +663,15 @@ s32 cellSyncQueuePop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
// prx: atomically insert 0 in first u8
queue->data &= { be_t<u32>::make(0xffffff), be_t<u32>::make(~0) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncQueueTryPop(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueueTryPop(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -648,10 +682,10 @@ s32 cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32
@ -664,15 +698,19 @@ s32 cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
}
memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size);
queue->data &= { be_t<u32>::make(0xffffff), be_t<u32>::make(~0) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 syncQueueTryPeekOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
{
const u32 v1 = (u32)queue.m_v1;
const u32 v2 = (u32)queue.m_v2;
const u32 v1 = queue.m_v1;
const u32 v2 = queue.m_v2;
if ((v1 >> 24) || ((v2 & 0xffffff) <= (v2 >> 24)))
{
return CELL_SYNC_ERROR_BUSY;
@ -680,12 +718,13 @@ s32 syncQueueTryPeekOp(CellSyncQueue::data_t& queue, u32 depth, u32& position)
queue.m_v1 = 0x1000000 | v1;
position = ((v1 & 0xffffff) + depth - (v2 & 0xffffff)) % depth;
return CELL_OK;
}
s32 cellSyncQueuePeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncQueuePeek(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueuePeek(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -696,10 +735,10 @@ s32 cellSyncQueuePeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
g_sync_queue_wm.wait_op(queue.addr(), [queue, depth, &position]()
@ -711,14 +750,17 @@ s32 cellSyncQueuePeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
});
memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size);
queue->data &= { be_t<u32>::make(0xffffff), be_t<u32>::make(~0) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
{
cellSync.Log("cellSyncQueueTryPeek(queue_addr=0x%x, buffer_addr=0x%x)", queue.addr(), buffer.addr());
cellSync.Log("cellSyncQueueTryPeek(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
{
@ -729,10 +771,10 @@ s32 cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 size = (u32)queue->m_size;
const u32 depth = (u32)queue->m_depth;
const u32 size = queue->m_size;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
u32 position;
s32 res = queue->data.atomic_op(CELL_OK, [depth, &position](CellSyncQueue::data_t& queue) -> s32
@ -745,14 +787,17 @@ s32 cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buffer)
}
memcpy(buffer.get_ptr(), &queue->m_buffer[position * size], size);
queue->data &= { be_t<u32>::make(0xffffff), be_t<u32>::make(~0) };
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
s32 cellSyncQueueSize(vm::ptr<CellSyncQueue> queue)
{
cellSync.Log("cellSyncQueueSize(queue_addr=0x%x)", queue.addr());
cellSync.Log("cellSyncQueueSize(queue=*0x%x)", queue);
if (!queue)
{
@ -764,16 +809,16 @@ s32 cellSyncQueueSize(vm::ptr<CellSyncQueue> queue)
}
const auto data = queue->data.read_relaxed();
const u32 count = (u32)data.m_v2 & 0xffffff;
const u32 depth = (u32)queue->m_depth;
assert(((u32)data.m_v1 & 0xffffff) <= depth && count <= depth);
const u32 count = data.m_v2 & 0xffffff;
const u32 depth = queue->m_depth;
assert((data.m_v1 & 0xffffff) <= depth && count <= depth);
return count;
}
s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
{
cellSync.Log("cellSyncQueueClear(queue_addr=0x%x)", queue.addr());
cellSync.Log("cellSyncQueueClear(queue=*0x%x)", queue);
if (!queue)
{
@ -784,16 +829,17 @@ s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
return CELL_SYNC_ERROR_ALIGN;
}
const u32 depth = (u32)queue->m_depth;
const u32 depth = queue->m_depth;
const auto data = queue->data.read_relaxed();
assert(((u32)data.m_v1 & 0xffffff) <= depth && ((u32)data.m_v2 & 0xffffff) <= depth);
assert((data.m_v1 & 0xffffff) <= depth && (data.m_v2 & 0xffffff) <= depth);
// TODO: optimize if possible
g_sync_queue_wm.wait_op(queue.addr(), [queue, depth]()
{
return CELL_OK == queue->data.atomic_op(CELL_OK, [depth](CellSyncQueue::data_t& queue) -> s32
{
const u32 v1 = (u32)queue.m_v1;
const u32 v1 = queue.m_v1;
// prx: extract first u8, repeat if not zero, insert 1
if (v1 >> 24)
{
@ -801,6 +847,7 @@ s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
}
queue.m_v1 = v1 | 0x1000000;
return CELL_OK;
});
});
@ -809,7 +856,8 @@ s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
{
return CELL_OK == queue->data.atomic_op(CELL_OK, [depth](CellSyncQueue::data_t& queue) -> s32
{
const u32 v2 = (u32)queue.m_v2;
const u32 v2 = queue.m_v2;
// prx: extract 5th u8, repeat if not zero, insert 1
if (v2 >> 24)
{
@ -817,12 +865,15 @@ s32 cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
}
queue.m_v2 = v2 | 0x1000000;
return CELL_OK;
});
});
queue->data.exchange({});
g_sync_queue_wm.notify(queue.addr());
return CELL_OK;
}
@ -943,13 +994,13 @@ s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u3
if (old_value == 2)
{
if ((u32)queue->m_size != size || (u32)queue->m_depth != depth || queue->m_buffer.addr() != buffer.addr())
if (queue->m_size != size || queue->m_depth != depth || queue->m_buffer.addr().value() != buffer.addr())
{
return CELL_SYNC_ERROR_INVAL;
}
if (sdk_ver > 0x17ffff)
{
if (queue->m_eaSignal.addr() != eaSignal.addr() || (u32)queue->m_direction != direction)
if (queue->m_eaSignal.addr() != eaSignal.addr() || queue->m_direction != direction)
{
return CELL_SYNC_ERROR_INVAL;
}
@ -971,8 +1022,7 @@ s32 syncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u3
s32 cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr<void> eaSignal)
{
cellSync.Warning("cellSyncLFQueueInitialize(queue_addr=0x%x, buffer_addr=0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal_addr=0x%x)",
queue.addr(), buffer.addr(), size, depth, direction, eaSignal.addr());
cellSync.Warning("cellSyncLFQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal=*0x%x)", queue, buffer, size, depth, direction, eaSignal);
return syncLFQueueInitialize(queue, buffer, size, depth, direction, eaSignal);
}
@ -985,7 +1035,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
}
u32 var1 = 0;
s32 depth = (u32)queue->m_depth;
s32 depth = queue->m_depth;
while (true)
{
while (true)
@ -1007,7 +1057,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
return CELL_SYNC_ERROR_STAT;
}
s32 var2 = (s32)(s16)push.m_h8;
s32 var2 = (s16)push.m_h8;
s32 res;
if (useEventQueue && ((s32)push.m_h5 != var2 || push.m_h7.data() != 0))
{
@ -1036,14 +1086,7 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
}
else if (!isBlocking)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!push.m_h7.data() || res)
{
// TODO: This condition is always true - wrong implementation?
return res;
}
break;
return CELL_SYNC_ERROR_AGAIN;
}
else if (!useEventQueue)
{
@ -1080,12 +1123,13 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
s32 _cellSyncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 useEventQueue)
{
cellSync.Warning("_cellSyncLFQueueGetPushPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, useEventQueue=%d)",
queue.addr(), pointer.addr(), isBlocking, useEventQueue);
cellSync.Warning("_cellSyncLFQueueGetPushPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue);
s32 pointer_value;
s32 result = syncLFQueueGetPushPointer(queue, pointer_value, isBlocking, useEventQueue);
*pointer = pointer_value;
return result;
}
@ -1097,12 +1141,13 @@ s32 syncLFQueueGetPushPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
s32 _cellSyncLFQueueGetPushPointer2(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 useEventQueue)
{
// arguments copied from _cellSyncLFQueueGetPushPointer
cellSync.Todo("_cellSyncLFQueueGetPushPointer2(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, useEventQueue=%d)",
queue.addr(), pointer.addr(), isBlocking, useEventQueue);
cellSync.Todo("_cellSyncLFQueueGetPushPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue);
s32 pointer_value;
s32 result = syncLFQueueGetPushPointer2(queue, pointer_value, isBlocking, useEventQueue);
*pointer = pointer_value;
return result;
}
@ -1242,8 +1287,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
s32 _cellSyncLFQueueCompletePushPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal)
{
cellSync.Warning("_cellSyncLFQueueCompletePushPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)",
queue.addr(), pointer, fpSendSignal.addr());
cellSync.Warning("_cellSyncLFQueueCompletePushPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal);
return syncLFQueueCompletePushPointer(queue, pointer, fpSendSignal);
}
@ -1256,8 +1300,7 @@ s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal)
{
// arguments copied from _cellSyncLFQueueCompletePushPointer
cellSync.Todo("_cellSyncLFQueueCompletePushPointer2(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)",
queue.addr(), pointer, fpSendSignal.addr());
cellSync.Todo("_cellSyncLFQueueCompletePushPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal);
return syncLFQueueCompletePushPointer2(queue, pointer, fpSendSignal);
}
@ -1265,7 +1308,7 @@ s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 poi
s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::ptr<const void> buffer, u32 isBlocking)
{
// cellSyncLFQueuePush has 1 in isBlocking param, cellSyncLFQueueTryPush has 0
cellSync.Warning("_cellSyncLFQueuePushBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking);
cellSync.Warning("_cellSyncLFQueuePushBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking);
if (!queue || !buffer)
{
@ -1304,7 +1347,7 @@ s32 _cellSyncLFQueuePushBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm:
if (Emu.IsStopped())
{
cellSync.Warning("_cellSyncLFQueuePushBody(queue_addr=0x%x) aborted", queue.addr());
cellSync.Warning("_cellSyncLFQueuePushBody(queue=*0x%x) aborted", queue);
return CELL_OK;
}
}
@ -1387,14 +1430,7 @@ s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 i
}
else if (!isBlocking)
{
res = CELL_SYNC_ERROR_AGAIN;
if (!pop.m_h3.data() || res)
{
// TODO: This condition is always true - wrong implementation?
return res;
}
break;
return CELL_SYNC_ERROR_AGAIN;
}
else if (!useEventQueue)
{
@ -1431,12 +1467,13 @@ s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 i
s32 _cellSyncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 arg4, u32 useEventQueue)
{
cellSync.Warning("_cellSyncLFQueueGetPopPointer(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)",
queue.addr(), pointer.addr(), isBlocking, arg4, useEventQueue);
cellSync.Warning("_cellSyncLFQueueGetPopPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)", queue, pointer, isBlocking, arg4, useEventQueue);
s32 pointer_value;
s32 result = syncLFQueueGetPopPointer(queue, pointer_value, isBlocking, arg4, useEventQueue);
*pointer = pointer_value;
return result;
}
@ -1448,12 +1485,13 @@ s32 syncLFQueueGetPopPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
s32 _cellSyncLFQueueGetPopPointer2(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> pointer, u32 isBlocking, u32 useEventQueue)
{
// arguments copied from _cellSyncLFQueueGetPopPointer
cellSync.Todo("_cellSyncLFQueueGetPopPointer2(queue_addr=0x%x, pointer_addr=0x%x, isBlocking=%d, useEventQueue=%d)",
queue.addr(), pointer.addr(), isBlocking, useEventQueue);
cellSync.Todo("_cellSyncLFQueueGetPopPointer2(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue);
s32 pointer_value;
s32 result = syncLFQueueGetPopPointer2(queue, pointer_value, isBlocking, useEventQueue);
*pointer = pointer_value;
return result;
}
@ -1593,8 +1631,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, c
s32 _cellSyncLFQueueCompletePopPointer(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
{
// arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer)
cellSync.Warning("_cellSyncLFQueueCompletePopPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)",
queue.addr(), pointer, fpSendSignal.addr(), noQueueFull);
cellSync.Warning("_cellSyncLFQueueCompletePopPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull);
return syncLFQueueCompletePopPointer(queue, pointer, fpSendSignal, noQueueFull);
}
@ -1607,8 +1644,7 @@ s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer, vm::ptr<s32(u32 addr, u32 arg)> fpSendSignal, u32 noQueueFull)
{
// arguments copied from _cellSyncLFQueueCompletePopPointer
cellSync.Todo("_cellSyncLFQueueCompletePopPointer2(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)",
queue.addr(), pointer, fpSendSignal.addr(), noQueueFull);
cellSync.Todo("_cellSyncLFQueueCompletePopPointer2(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull);
return syncLFQueueCompletePopPointer2(queue, pointer, fpSendSignal, noQueueFull);
}
@ -1616,7 +1652,7 @@ s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 poin
s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::ptr<void> buffer, u32 isBlocking)
{
// cellSyncLFQueuePop has 1 in isBlocking param, cellSyncLFQueueTryPop has 0
cellSync.Warning("_cellSyncLFQueuePopBody(queue_addr=0x%x, buffer_addr=0x%x, isBlocking=%d)", queue.addr(), buffer.addr(), isBlocking);
cellSync.Warning("_cellSyncLFQueuePopBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking);
if (!queue || !buffer)
{
@ -1654,7 +1690,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::
if (Emu.IsStopped())
{
cellSync.Warning("_cellSyncLFQueuePopBody(queue_addr=0x%x) aborted", queue.addr());
cellSync.Warning("_cellSyncLFQueuePopBody(queue=*0x%x) aborted", queue);
return CELL_OK;
}
}
@ -1680,7 +1716,7 @@ s32 _cellSyncLFQueuePopBody(PPUThread& CPU, vm::ptr<CellSyncLFQueue> queue, vm::
s32 cellSyncLFQueueClear(vm::ptr<CellSyncLFQueue> queue)
{
cellSync.Warning("cellSyncLFQueueClear(queue_addr=0x%x)", queue.addr());
cellSync.Warning("cellSyncLFQueueClear(queue=*0x%x)", queue);
if (!queue)
{
@ -1730,7 +1766,7 @@ s32 cellSyncLFQueueClear(vm::ptr<CellSyncLFQueue> queue)
s32 cellSyncLFQueueSize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> size)
{
cellSync.Warning("cellSyncLFQueueSize(queue_addr=0x%x, size_addr=0x%x)", queue.addr(), size.addr());
cellSync.Warning("cellSyncLFQueueSize(queue=*0x%x, size=*0x%x)", queue, size);
if (!queue || !size)
{
@ -1765,7 +1801,7 @@ s32 cellSyncLFQueueSize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> size)
s32 cellSyncLFQueueDepth(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> depth)
{
cellSync.Log("cellSyncLFQueueDepth(queue_addr=0x%x, depth_addr=0x%x)", queue.addr(), depth.addr());
cellSync.Log("cellSyncLFQueueDepth(queue=*0x%x, depth=*0x%x)", queue, depth);
if (!queue || !depth)
{
@ -1782,7 +1818,7 @@ s32 cellSyncLFQueueDepth(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32> depth)
s32 _cellSyncLFQueueGetSignalAddress(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<u32> ppSignal)
{
cellSync.Log("_cellSyncLFQueueGetSignalAddress(queue_addr=0x%x, ppSignal_addr=0x%x)", queue.addr(), ppSignal.addr());
cellSync.Log("_cellSyncLFQueueGetSignalAddress(queue=*0x%x, ppSignal=*0x%x)", queue, ppSignal);
if (!queue || !ppSignal)
{
@ -1799,7 +1835,7 @@ s32 _cellSyncLFQueueGetSignalAddress(vm::ptr<const CellSyncLFQueue> queue, vm::p
s32 cellSyncLFQueueGetDirection(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<CellSyncQueueDirection> direction)
{
cellSync.Log("cellSyncLFQueueGetDirection(queue_addr=0x%x, direction_addr=0x%x)", queue.addr(), direction.addr());
cellSync.Log("cellSyncLFQueueGetDirection(queue=*0x%x, direction=*0x%x)", queue, direction);
if (!queue || !direction)
{
@ -1816,7 +1852,7 @@ s32 cellSyncLFQueueGetDirection(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<Ce
s32 cellSyncLFQueueGetEntrySize(vm::ptr<const CellSyncLFQueue> queue, vm::ptr<u32> entry_size)
{
cellSync.Log("cellSyncLFQueueGetEntrySize(queue_addr=0x%x, entry_size_addr=0x%x)", queue.addr(), entry_size.addr());
cellSync.Log("cellSyncLFQueueGetEntrySize(queue=*0x%x, entry_size=*0x%x)", queue, entry_size);
if (!queue || !entry_size)
{
@ -1838,7 +1874,7 @@ s32 syncLFQueueAttachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncL
s32 _cellSyncLFQueueAttachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue)
{
cellSync.Todo("_cellSyncLFQueueAttachLv2EventQueue(spus_addr=0x%x, num=%d, queue_addr=0x%x)", spus.addr(), num, queue.addr());
cellSync.Todo("_cellSyncLFQueueAttachLv2EventQueue(spus=*0x%x, num=%d, queue=*0x%x)", spus, num, queue);
return syncLFQueueAttachLv2EventQueue(spus, num, queue);
}
@ -1850,7 +1886,7 @@ s32 syncLFQueueDetachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncL
s32 _cellSyncLFQueueDetachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncLFQueue> queue)
{
cellSync.Todo("_cellSyncLFQueueDetachLv2EventQueue(spus_addr=0x%x, num=%d, queue_addr=0x%x)", spus.addr(), num, queue.addr());
cellSync.Todo("_cellSyncLFQueueDetachLv2EventQueue(spus=*0x%x, num=%d, queue=*0x%x)", spus, num, queue);
return syncLFQueueDetachLv2EventQueue(spus, num, queue);
}

View file

@ -14,13 +14,13 @@
SemaphoreAttributes SyncPrimManager::GetSemaphoreData(u32 id)
{
std::shared_ptr<Semaphore> sem;
std::shared_ptr<semaphore_t> sem;
if (!Emu.GetIdManager().GetIDData(id, sem))
{
return{};
}
return{ std::string((const char*)&sem->name, 8), sem->value.read_sync(), sem->max };
return{ std::string((const char*)&sem->name, 8), sem->value, sem->max };
}
LwMutexAttributes SyncPrimManager::GetLwMutexData(u32 id)

View file

@ -42,8 +42,8 @@ struct FsRingBufferConfig
s32 cellFsOpen(vm::ptr<const char> path, s32 flags, vm::ptr<be_t<u32>> fd, vm::ptr<const void> arg, u64 size)
{
sys_fs.Log("cellFsOpen(path_addr=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx)", path.addr(), flags, fd, arg, size);
sys_fs.Log("cellFsOpen(path='%s')", path.get_ptr());
sys_fs.Log("cellFsOpen(path=*0x%x, flags=0x%x, fd=*0x%x, arg=*0x%x, size=0x%llx)", path, flags, fd, arg, size);
sys_fs.Log("*** path = '%s'", path.get_ptr());
const std::string _path = path.get_ptr();
@ -145,7 +145,7 @@ s32 cellFsRead(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<be_t<u64>> nread)
s32 cellFsWrite(u32 fd, vm::ptr<const void> buf, u64 nbytes, vm::ptr<u64> nwrite)
{
sys_fs.Log("cellFsWrite(fd=0x%x, buf=0x%x, nbytes=0x%llx, nwrite=0x%x)", fd, buf, nbytes, nwrite);
sys_fs.Log("cellFsWrite(fd=0x%x, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file)) return CELL_ESRCH;
@ -173,8 +173,8 @@ s32 cellFsClose(u32 fd)
s32 cellFsOpendir(vm::ptr<const char> path, vm::ptr<u32> fd)
{
sys_fs.Warning("cellFsOpendir(path_addr=0x%x, fd=0x%x)", path.addr(), fd);
sys_fs.Warning("cellFsOpendir(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsOpendir(path=*0x%x, fd=*0x%x)", path, fd);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
std::shared_ptr<vfsDirBase> dir(Emu.GetVFS().OpenDir(path.get_ptr()));
if (!dir || !dir->IsOpened())
@ -188,7 +188,7 @@ s32 cellFsOpendir(vm::ptr<const char> path, vm::ptr<u32> fd)
s32 cellFsReaddir(u32 fd, vm::ptr<CellFsDirent> dir, vm::ptr<u64> nread)
{
sys_fs.Warning("cellFsReaddir(fd=0x%x, dir=0x%x, nread=0x%x)", fd, dir, nread);
sys_fs.Warning("cellFsReaddir(fd=0x%x, dir=*0x%x, nread=*0x%x)", fd, dir, nread);
std::shared_ptr<vfsDirBase> directory;
if (!Emu.GetIdManager().GetIDData(fd, directory))
@ -222,8 +222,8 @@ s32 cellFsClosedir(u32 fd)
s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
{
sys_fs.Warning("cellFsStat(path_addr=0x%x, sb=0x%x)", path.addr(), sb);
sys_fs.Warning("cellFsStat(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsStat(path=*0x%x, sb=*0x%x)", path, sb);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
const std::string _path = path.get_ptr();
@ -305,7 +305,7 @@ s32 cellFsStat(vm::ptr<const char> path, vm::ptr<CellFsStat> sb)
s32 cellFsFstat(u32 fd, vm::ptr<CellFsStat> sb)
{
sys_fs.Warning("cellFsFstat(fd=0x%x, sb=0x%x)", fd, sb);
sys_fs.Warning("cellFsFstat(fd=0x%x, sb=*0x%x)", fd, sb);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -330,8 +330,8 @@ s32 cellFsFstat(u32 fd, vm::ptr<CellFsStat> sb)
s32 cellFsMkdir(vm::ptr<const char> path, u32 mode)
{
sys_fs.Warning("cellFsMkdir(path_addr=0x%x, mode=0x%x)", path.addr(), mode);
sys_fs.Warning("cellFsMkdir(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsMkdir(path=*0x%x, mode=0x%x)", path, mode);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
const std::string _path = path.get_ptr();
@ -347,8 +347,9 @@ s32 cellFsMkdir(vm::ptr<const char> path, u32 mode)
s32 cellFsRename(vm::ptr<const char> from, vm::ptr<const char> to)
{
sys_fs.Warning("cellFsRename(from_addr=0x%x, to_addr=0x%x)", from.addr(), to.addr());
sys_fs.Warning("cellFsRename(from='%s', to='%s')", from.get_ptr(), to.get_ptr());
sys_fs.Warning("cellFsRename(from=*0x%x, to=*0x%x)", from, to);
sys_fs.Warning("*** from = '%s'", from.get_ptr());
sys_fs.Warning("*** to = '%s'", to.get_ptr());
std::string _from = from.get_ptr();
std::string _to = to.get_ptr();
@ -382,8 +383,8 @@ s32 cellFsRename(vm::ptr<const char> from, vm::ptr<const char> to)
}
s32 cellFsChmod(vm::ptr<const char> path, u32 mode)
{
sys_fs.Todo("cellFsChmod(path_addr=0x%x, mode=0x%x)", path.addr(), mode);
sys_fs.Todo("cellFsChmod(path='%s')", path.get_ptr());
sys_fs.Todo("cellFsChmod(path=*0x%x, mode=0x%x)", path, mode);
sys_fs.Todo("*** path = '%s'", path.get_ptr());
// TODO:
@ -401,8 +402,8 @@ s32 cellFsFsync(u32 fd)
s32 cellFsRmdir(vm::ptr<const char> path)
{
sys_fs.Warning("cellFsRmdir(path_addr=0x%x)", path.addr());
sys_fs.Warning("cellFsRmdir(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsRmdir(path=*0x%x)", path);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
std::string _path = path.get_ptr();
@ -419,8 +420,8 @@ s32 cellFsRmdir(vm::ptr<const char> path)
s32 cellFsUnlink(vm::ptr<const char> path)
{
sys_fs.Warning("cellFsUnlink(path_addr=0x%x)", path.addr());
sys_fs.Warning("cellFsUnlink(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsUnlink(path=*0x%x)", path);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
std::string _path = path.get_ptr();
@ -439,7 +440,7 @@ s32 cellFsUnlink(vm::ptr<const char> path)
s32 cellFsLseek(u32 fd, s64 offset, u32 whence, vm::ptr<be_t<u64>> pos)
{
sys_fs.Log("cellFsLseek(fd=0x%x, offset=0x%llx, whence=0x%x, pos=0x%x)", fd, offset, whence, pos);
sys_fs.Log("cellFsLseek(fd=0x%x, offset=0x%llx, whence=0x%x, pos=*0x%x)", fd, offset, whence, pos);
vfsSeekMode seek_mode;
switch(whence)
@ -490,8 +491,8 @@ s32 cellFsFtruncate(u32 fd, u64 size)
s32 cellFsTruncate(vm::ptr<const char> path, u64 size)
{
sys_fs.Warning("cellFsTruncate(path_addr=0x%x, size=0x%llx)", path.addr(), size);
sys_fs.Warning("cellFsTruncate(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsTruncate(path=*0x%x, size=0x%llx)", path, size);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
vfsFile f(path.get_ptr(), vfsReadWrite);
if (!f.IsOpened())
@ -521,7 +522,7 @@ s32 cellFsTruncate(vm::ptr<const char> path, u64 size)
s32 cellFsFGetBlockSize(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_size)
{
sys_fs.Warning("cellFsFGetBlockSize(fd=0x%x, sector_size=0x%x, block_size=0x%x)", fd, sector_size, block_size);
sys_fs.Warning("cellFsFGetBlockSize(fd=0x%x, sector_size=*0x%x, block_size=*0x%x)", fd, sector_size, block_size);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -535,8 +536,8 @@ s32 cellFsFGetBlockSize(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_siz
s32 cellFsGetBlockSize(vm::ptr<const char> path, vm::ptr<u64> sector_size, vm::ptr<u64> block_size)
{
sys_fs.Warning("cellFsGetBlockSize(path_addr=0x%x, sector_size=0x%x, block_size=0x%x)", path.addr(), sector_size, block_size);
sys_fs.Warning("cellFsGetBlockSize(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsGetBlockSize(path=*0x%x, sector_size=*0x%x, block_size=*0x%x)", path, sector_size, block_size);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
*sector_size = 4096; // ?
*block_size = 4096; // ?
@ -546,8 +547,8 @@ s32 cellFsGetBlockSize(vm::ptr<const char> path, vm::ptr<u64> sector_size, vm::p
s32 cellFsGetFreeSize(vm::ptr<const char> path, vm::ptr<u32> block_size, vm::ptr<u64> block_count)
{
sys_fs.Warning("cellFsGetFreeSize(path_addr=0x%x, block_size=0x%x, block_count=0x%x)", path.addr(), block_size, block_count);
sys_fs.Warning("cellFsGetFreeSize(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsGetFreeSize(path=*0x%x, block_size=*0x%x, block_count=*0x%x)", path, block_size, block_count);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
// TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks
*block_size = 4096; // ?
@ -558,7 +559,7 @@ s32 cellFsGetFreeSize(vm::ptr<const char> path, vm::ptr<u32> block_size, vm::ptr
s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32 entries_size, vm::ptr<u32> data_count)
{
sys_fs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=0x%x, entries_size=0x%x, data_count=0x%x)", fd, entries, entries_size, data_count);
sys_fs.Warning("cellFsGetDirectoryEntries(fd=0x%x, entries=*0x%x, entries_size=0x%x, data_count=*0x%x)", fd, entries, entries_size, data_count);
std::shared_ptr<vfsDirBase> directory;
if (!Emu.GetIdManager().GetIDData(fd, directory))
@ -594,7 +595,7 @@ s32 cellFsGetDirectoryEntries(u32 fd, vm::ptr<CellFsDirectoryEntry> entries, u32
s32 cellFsStReadInit(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
{
sys_fs.Warning("cellFsStReadInit(fd=0x%x, ringbuf=0x%x)", fd, ringbuf);
sys_fs.Warning("cellFsStReadInit(fd=0x%x, ringbuf=*0x%x)", fd, ringbuf);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -633,7 +634,7 @@ s32 cellFsStReadFinish(u32 fd)
s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=0x%x)", fd, ringbuf);
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, ringbuf=*0x%x)", fd, ringbuf);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -648,7 +649,7 @@ s32 cellFsStReadGetRingBuf(u32 fd, vm::ptr<CellFsRingBuffer> ringbuf)
s32 cellFsStReadGetStatus(u32 fd, vm::ptr<u64> status)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=0x%x)", fd, status);
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, status=*0x%x)", fd, status);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -661,7 +662,7 @@ s32 cellFsStReadGetStatus(u32 fd, vm::ptr<u64> status)
s32 cellFsStReadGetRegid(u32 fd, vm::ptr<u64> regid)
{
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=0x%x)", fd, regid);
sys_fs.Warning("cellFsStReadGetRingBuf(fd=0x%x, regid=*0x%x)", fd, regid);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -701,7 +702,7 @@ s32 cellFsStReadStop(u32 fd)
s32 cellFsStRead(u32 fd, vm::ptr<u8> buf, u64 size, vm::ptr<u64> rsize)
{
sys_fs.Warning("cellFsStRead(fd=0x%x, buf=0x%x, size=0x%llx, rsize=0x%x)", fd, buf, size, rsize);
sys_fs.Warning("cellFsStRead(fd=0x%x, buf=*0x%x, size=0x%llx, rsize=*0x%x)", fd, buf, size, rsize);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -720,7 +721,7 @@ s32 cellFsStRead(u32 fd, vm::ptr<u8> buf, u64 size, vm::ptr<u64> rsize)
s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<vm::ptr<u8>> addr, vm::ptr<u64> size)
{
sys_fs.Todo("cellFsStReadGetCurrentAddr(fd=0x%x, addr=0x%x, size=0x%x)", fd, addr, size);
sys_fs.Todo("cellFsStReadGetCurrentAddr(fd=0x%x, addr=*0x%x, size=*0x%x)", fd, addr, size);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -731,7 +732,7 @@ s32 cellFsStReadGetCurrentAddr(u32 fd, vm::ptr<vm::ptr<u8>> addr, vm::ptr<u64> s
s32 cellFsStReadPutCurrentAddr(u32 fd, vm::ptr<u8> addr, u64 size)
{
sys_fs.Todo("cellFsStReadPutCurrentAddr(fd=0x%x, addr=0x%x, size=0x%llx)", fd, addr, size);
sys_fs.Todo("cellFsStReadPutCurrentAddr(fd=0x%x, addr=*0x%x, size=0x%llx)", fd, addr, size);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -753,7 +754,7 @@ s32 cellFsStReadWait(u32 fd, u64 size)
s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr<void(int xfd, u64 xsize)> func)
{
sys_fs.Todo("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=0x%x)", fd, size, func);
sys_fs.Todo("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=*0x%x)", fd, size, func);
std::shared_ptr<vfsStream> file;
if (!Emu.GetIdManager().GetIDData(fd, file))
@ -864,8 +865,8 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil
s32 cellFsSdataOpen(vm::ptr<const char> path, s32 flags, vm::ptr<be_t<u32>> fd, vm::ptr<const void> arg, u64 size)
{
sys_fs.Warning("cellFsSdataOpen(path_addr=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx) -> cellFsOpen()", path.addr(), flags, fd, arg, size);
sys_fs.Warning("cellFsSdataOpen(path='%s')", path.get_ptr());
sys_fs.Warning("cellFsSdataOpen(path=*0x%x, flags=0x%x, fd=*0x%x, arg=*0x%x, size=0x%llx) -> cellFsOpen()", path, flags, fd, arg, size);
sys_fs.Warning("*** path = '%s'", path.get_ptr());
/*if (flags != CELL_O_RDONLY)
return CELL_EINVAL;
@ -889,7 +890,7 @@ s32 cellFsSdataOpen(vm::ptr<const char> path, s32 flags, vm::ptr<be_t<u32>> fd,
s32 cellFsSdataOpenByFd(u32 mself_fd, s32 flags, vm::ptr<u32> sdata_fd, u64 offset, vm::ptr<const void> arg, u64 size)
{
sys_fs.Todo("cellFsSdataOpenByFd(mself_fd=0x%x, flags=0x%x, sdata_fd=0x%x, offset=0x%llx, arg=0x%x, size=0x%llx)", mself_fd, flags, sdata_fd, offset, arg, size);
sys_fs.Todo("cellFsSdataOpenByFd(mself_fd=0x%x, flags=0x%x, sdata_fd=*0x%x, offset=0x%llx, arg=*0x%x, size=0x%llx)", mself_fd, flags, sdata_fd, offset, arg, size);
// TODO:
@ -957,7 +958,7 @@ void fsAioRead(u32 fd, vm::ptr<CellFsAio> aio, int xid, vm::ptr<void(vm::ptr<Cel
s32 cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)> func)
{
sys_fs.Warning("cellFsAioRead(aio=0x%x, id=0x%x, func=0x%x)", aio, id, func);
sys_fs.Warning("cellFsAioRead(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func);
if (!aio_init)
{
@ -982,7 +983,7 @@ s32 cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr<
s32 cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)> func)
{
sys_fs.Todo("cellFsAioWrite(aio=0x%x, id=0x%x, func=0x%x)", aio, id, func);
sys_fs.Todo("cellFsAioWrite(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func);
// TODO:
@ -991,8 +992,8 @@ s32 cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr
s32 cellFsAioInit(vm::ptr<const char> mount_point)
{
sys_fs.Warning("cellFsAioInit(mount_point_addr=0x%x)", mount_point.addr());
sys_fs.Warning("cellFsAioInit(mount_point='%s')", mount_point.get_ptr());
sys_fs.Warning("cellFsAioInit(mount_point=*0x%x)", mount_point);
sys_fs.Warning("*** mount_point = '%s'", mount_point.get_ptr());
aio_init = true;
return CELL_OK;
@ -1000,8 +1001,8 @@ s32 cellFsAioInit(vm::ptr<const char> mount_point)
s32 cellFsAioFinish(vm::ptr<const char> mount_point)
{
sys_fs.Warning("cellFsAioFinish(mount_point_addr=0x%x)", mount_point.addr());
sys_fs.Warning("cellFsAioFinish(mount_point='%s')", mount_point.get_ptr());
sys_fs.Warning("cellFsAioFinish(mount_point=*0x%x)", mount_point);
sys_fs.Warning("*** mount_point = '%s'", mount_point.get_ptr());
//aio_init = false;
return CELL_OK;
@ -1009,7 +1010,7 @@ s32 cellFsAioFinish(vm::ptr<const char> mount_point)
s32 cellFsReadWithOffset(PPUThread& CPU, u32 fd, u64 offset, vm::ptr<void> buf, u64 buffer_size, vm::ptr<be_t<u64>> nread)
{
sys_fs.Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf=0x%x, buffer_size=%lld, nread=0x%llx)", fd, offset, buf, buffer_size, nread);
sys_fs.Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf=*0x%x, buffer_size=%lld, nread=*0x%llx)", fd, offset, buf, buffer_size, nread);
int ret;
vm::stackvar<be_t<u64>> oldPos(CPU), newPos(CPU);

View file

@ -35,10 +35,8 @@ s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attr>
switch (protocol)
{
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_RETRY: sys_event.Error("sys_event_queue_create(): invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL;
case SYS_SYNC_PRIORITY_INHERIT: sys_event.Error("sys_event_queue_create(): invalid protocol (SYS_SYNC_PRIORITY_INHERIT)"); return CELL_EINVAL;
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
default: sys_event.Error("sys_event_queue_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL;
}

View file

@ -27,10 +27,10 @@ s32 sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attr> attr, u6
switch (protocol)
{
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_RETRY: sys_event_flag.Todo("sys_event_flag_create(): SYS_SYNC_RETRY"); break;
case SYS_SYNC_PRIORITY_INHERIT: sys_event_flag.Todo("sys_event_flag_create(): SYS_SYNC_PRIORITY_INHERIT"); break;
case SYS_SYNC_FIFO: break;
case SYS_SYNC_RETRY: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT: break;
default: sys_event_flag.Error("sys_event_flag_create(): unknown protocol (0x%x)", attr->protocol); return CELL_EINVAL;
}

View file

@ -29,8 +29,7 @@ s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr)
{
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT: sys_mutex.Todo("sys_mutex_create(): SYS_SYNC_PRIORITY_INHERIT"); break;
case SYS_SYNC_RETRY: sys_mutex.Error("sys_mutex_create(): invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL;
case SYS_SYNC_PRIORITY_INHERIT: break;
default: sys_mutex.Error("sys_mutex_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL;
}

View file

@ -10,16 +10,8 @@
SysCallBase sys_ppu_thread("sys_ppu_thread");
static const u32 PPU_THREAD_ID_INVALID = 0xFFFFFFFFU/*UUUUUUUUUUuuuuuuuuuu~~~~~~~~*/;
void ppu_thread_exit(PPUThread& CPU, u64 errorcode)
{
if (CPU.owned_mutexes)
{
sys_ppu_thread.Error("Owned mutexes found (%d)", CPU.owned_mutexes);
CPU.owned_mutexes = 0;
}
CPU.SetExitStatus(errorcode);
CPU.Stop();

View file

@ -13,35 +13,33 @@ SysCallBase sys_rwlock("sys_rwlock");
s32 sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr)
{
sys_rwlock.Warning("sys_rwlock_create(rw_lock_id_addr=0x%x, attr_addr=0x%x)", rw_lock_id.addr(), attr.addr());
sys_rwlock.Warning("sys_rwlock_create(rw_lock_id=*0x%x, attr=*0x%x)", rw_lock_id, attr);
if (!attr)
if (!rw_lock_id || !attr)
{
sys_rwlock.Error("sys_rwlock_create(): null attr address");
return CELL_EFAULT;
}
switch (attr->protocol.data())
const u32 protocol = attr->protocol;
switch (protocol)
{
case se32(SYS_SYNC_PRIORITY): break;
case se32(SYS_SYNC_RETRY): sys_rwlock.Error("Invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_rwlock.Todo("SYS_SYNC_PRIORITY_INHERIT"); break;
case se32(SYS_SYNC_FIFO): break;
default: sys_rwlock.Error("Unknown protocol (0x%x)", attr->protocol); return CELL_EINVAL;
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT: break;
default: sys_rwlock.Error("sys_rwlock_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL;
}
if (attr->pshared.data() != se32(0x200))
if (attr->pshared.data() != se32(0x200) || attr->ipc_key.data() || attr->flags.data())
{
sys_rwlock.Error("Unknown pshared attribute (0x%x)", attr->pshared);
sys_rwlock.Error("sys_rwlock_create(): unknown attributes (pshared=0x%x, ipc_key=0x%llx, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
std::shared_ptr<RWLock> rw(new RWLock(attr->protocol, attr->name_u64));
const u32 id = Emu.GetIdManager().GetNewID(rw, TYPE_RWLOCK);
*rw_lock_id = id;
rw->wqueue.set_full_name(fmt::Format("Rwlock(%d)", id));
std::shared_ptr<rwlock_t> rwlock(new rwlock_t(attr->protocol, attr->name_u64));
*rw_lock_id = Emu.GetIdManager().GetNewID(rwlock, TYPE_RWLOCK);
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id = %d", std::string(attr->name, 8).c_str(), rw->protocol, id);
return CELL_OK;
}
@ -49,52 +47,40 @@ s32 sys_rwlock_destroy(u32 rw_lock_id)
{
sys_rwlock.Warning("sys_rwlock_destroy(rw_lock_id=%d)", rw_lock_id);
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
if (!rw->sync.compare_and_swap_test({ 0, 0 }, { ~0u, ~0u })) // check if locked and make unusable
if (rwlock.use_count() > 2 || rwlock->readers || rwlock->writer || rwlock->waiters)
{
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(rw_lock_id);
return CELL_OK;
}
s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
{
sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout);
sys_rwlock.Log("sys_rwlock_rlock(rw_lock_id=%d, timeout=0x%llx)", rw_lock_id, timeout);
const u64 start_time = get_system_time();
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
while (true)
while (rwlock->writer || rwlock->waiters)
{
bool succeeded;
rw->sync.atomic_op_sync([&succeeded](RWLock::sync_var_t& sync)
{
assert(~sync.readers);
if ((succeeded = !sync.writer))
{
sync.readers++;
}
});
if (succeeded)
{
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (timeout && get_system_time() - start_time > timeout)
{
return CELL_ETIMEDOUT;
@ -105,8 +91,12 @@ s32 sys_rwlock_rlock(u32 rw_lock_id, u64 timeout)
sys_rwlock.Warning("sys_rwlock_rlock(id=%d) aborted", rw_lock_id);
return CELL_OK;
}
rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
}
rwlock->readers++;
return CELL_OK;
}
@ -114,100 +104,76 @@ s32 sys_rwlock_tryrlock(u32 rw_lock_id)
{
sys_rwlock.Log("sys_rwlock_tryrlock(rw_lock_id=%d)", rw_lock_id);
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
bool succeeded;
rw->sync.atomic_op_sync([&succeeded](RWLock::sync_var_t& sync)
if (rwlock->writer || rwlock->waiters)
{
assert(~sync.readers);
if ((succeeded = !sync.writer))
{
sync.readers++;
}
});
if (succeeded)
{
return CELL_OK;
return CELL_EBUSY;
}
return CELL_EBUSY;
rwlock->readers++;
return CELL_OK;
}
s32 sys_rwlock_runlock(u32 rw_lock_id)
{
sys_rwlock.Log("sys_rwlock_runlock(rw_lock_id=%d)", rw_lock_id);
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
bool succeeded;
rw->sync.atomic_op_sync([&succeeded](RWLock::sync_var_t& sync)
if (!rwlock->readers)
{
if ((succeeded = sync.readers != 0))
{
assert(!sync.writer);
sync.readers--;
}
});
if (succeeded)
{
return CELL_OK;
return CELL_EPERM;
}
return CELL_EPERM;
if (!--rwlock->readers)
{
rwlock->cv.notify_one();
}
return CELL_OK;
}
s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
{
sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=%lld)", rw_lock_id, timeout);
sys_rwlock.Log("sys_rwlock_wlock(rw_lock_id=%d, timeout=0x%llx)", rw_lock_id, timeout);
const u64 start_time = get_system_time();
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
const u32 tid = CPU.GetId();
if (rw->sync.compare_and_swap_test({ 0, 0 }, { 0, tid }))
{
return CELL_OK;
}
if (rw->sync.read_relaxed().writer == tid)
if (rwlock->writer == CPU.GetId())
{
return CELL_EDEADLK;
}
rw->wqueue.push(tid, rw->protocol);
// protocol is ignored in current implementation
rwlock->waiters++; assert(rwlock->waiters > 0);
while (true)
while (rwlock->readers || rwlock->writer)
{
auto old_sync = rw->sync.compare_and_swap({ 0, 0 }, { 0, tid });
if (!old_sync.readers && (!old_sync.writer || old_sync.writer == tid))
{
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (timeout && get_system_time() - start_time > timeout)
{
if (!rw->wqueue.invalidate(tid, rw->protocol))
{
assert(!"sys_rwlock_wlock() failed (timeout)");
}
rwlock->waiters--; assert(rwlock->waiters >= 0);
return CELL_ETIMEDOUT;
}
@ -216,12 +182,13 @@ s32 sys_rwlock_wlock(PPUThread& CPU, u32 rw_lock_id, u64 timeout)
sys_rwlock.Warning("sys_rwlock_wlock(id=%d) aborted", rw_lock_id);
return CELL_OK;
}
rwlock->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
}
if (!rw->wqueue.invalidate(tid, rw->protocol) && !rw->wqueue.pop(tid, rw->protocol))
{
assert(!"sys_rwlock_wlock() failed (locking)");
}
rwlock->writer = CPU.GetId();
rwlock->waiters--; assert(rwlock->waiters >= 0);
return CELL_OK;
}
@ -229,48 +196,48 @@ s32 sys_rwlock_trywlock(PPUThread& CPU, u32 rw_lock_id)
{
sys_rwlock.Log("sys_rwlock_trywlock(rw_lock_id=%d)", rw_lock_id);
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
const u32 tid = CPU.GetId();
if (rw->sync.compare_and_swap_test({ 0, 0 }, { 0, tid }))
{
return CELL_OK;
}
if (rw->sync.read_relaxed().writer == tid)
if (rwlock->writer == CPU.GetId())
{
return CELL_EDEADLK;
}
return CELL_EBUSY;
if (rwlock->readers || rwlock->writer || rwlock->waiters)
{
return CELL_EBUSY;
}
rwlock->writer = CPU.GetId();
return CELL_OK;
}
s32 sys_rwlock_wunlock(PPUThread& CPU, u32 rw_lock_id)
{
sys_rwlock.Log("sys_rwlock_wunlock(rw_lock_id=%d)", rw_lock_id);
std::shared_ptr<RWLock> rw;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rw))
LV2_LOCK;
std::shared_ptr<rwlock_t> rwlock;
if (!Emu.GetIdManager().GetIDData(rw_lock_id, rwlock))
{
return CELL_ESRCH;
}
const u32 tid = CPU.GetId();
const u32 target = rw->wqueue.signal(rw->protocol);
if (rw->sync.compare_and_swap_test({ 0, tid }, { 0, target }))
if (rwlock->writer != CPU.GetId())
{
if (!target)
{
// TODO: signal readers
}
return CELL_OK;
return CELL_EPERM;
}
return CELL_EPERM;
rwlock->writer = 0;
rwlock->cv.notify_all();
return CELL_OK;
}

View file

@ -7,6 +7,7 @@ struct sys_rwlock_attribute_t
be_t<u64> ipc_key;
be_t<s32> flags;
be_t<u32> pad;
union
{
char name[8];
@ -14,24 +15,25 @@ struct sys_rwlock_attribute_t
};
};
struct RWLock
struct rwlock_t
{
struct sync_var_t
{
u32 readers; // reader count
u32 writer; // writer thread id
};
sleep_queue_t wqueue;
atomic_le_t<sync_var_t> sync;
const u32 protocol;
const u64 name;
RWLock(u32 protocol, u64 name)
std::atomic<u32> readers; // reader count
std::atomic<u32> writer; // writer id
// TODO: use sleep queue, possibly remove condition variable
std::condition_variable cv;
std::atomic<s32> waiters;
rwlock_t(u32 protocol, u64 name)
: protocol(protocol)
, wqueue(name)
, name(name)
, readers(0)
, writer(0)
, waiters(0)
{
sync.write_relaxed({ 0, 0 });
}
};

View file

@ -12,182 +12,141 @@
SysCallBase sys_semaphore("sys_semaphore");
u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64)
u32 semaphore_create(s32 initial_val, s32 max_val, u32 protocol, u64 name_u64)
{
std::shared_ptr<Semaphore> sem(new Semaphore(initial_count, max_count, protocol, name_u64));
std::shared_ptr<semaphore_t> sem(new semaphore_t(protocol, max_val, name_u64, initial_val));
const u32 id = Emu.GetIdManager().GetNewID(sem, TYPE_SEMAPHORE);
sem->queue.set_full_name(fmt::Format("Semaphore(%d)", id));
sys_semaphore.Notice("*** semaphore created [%s] (protocol=0x%x): id = %d", std::string((const char*)&name_u64, 8).c_str(), protocol, id);
return id;
return Emu.GetIdManager().GetNewID(sem, TYPE_SEMAPHORE);
}
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute> attr, s32 initial_count, s32 max_count)
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val)
{
sys_semaphore.Warning("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)",
sem.addr(), attr.addr(), initial_count, max_count);
sys_semaphore.Warning("sys_semaphore_create(sem=*0x%x, attr=*0x%x, initial_val=%d, max_val=%d)", sem, attr, initial_val, max_val);
if (!sem)
if (!sem || !attr)
{
sys_semaphore.Error("sys_semaphore_create(): invalid memory access (sem_addr=0x%x)", sem.addr());
return CELL_EFAULT;
}
if (!attr)
if (max_val <= 0 || initial_val > max_val || initial_val < 0)
{
sys_semaphore.Error("sys_semaphore_create(): An invalid argument value is specified (attr_addr=0x%x)", attr.addr());
return CELL_EFAULT;
}
if (max_count <= 0 || initial_count > max_count || initial_count < 0)
{
sys_semaphore.Error("sys_semaphore_create(): invalid parameters (initial_count=%d, max_count=%d)", initial_count, max_count);
sys_semaphore.Error("sys_semaphore_create(): invalid parameters (initial_val=%d, max_val=%d)", initial_val, max_val);
return CELL_EINVAL;
}
switch (attr->protocol.data())
const u32 protocol = attr->protocol;
switch (protocol)
{
case se32(SYS_SYNC_FIFO): break;
case se32(SYS_SYNC_PRIORITY): break;
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_semaphore.Todo("SYS_SYNC_PRIORITY_INHERIT"); break;
case se32(SYS_SYNC_RETRY): sys_semaphore.Error("Invalid protocol (SYS_SYNC_RETRY)"); return CELL_EINVAL;
default: sys_semaphore.Error("Unknown protocol attribute (0x%x)", attr->protocol); return CELL_EINVAL;
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
case SYS_SYNC_PRIORITY_INHERIT: break;
default: sys_semaphore.Error("sys_semaphore_create(): unknown protocol (0x%x)", protocol); return CELL_EINVAL;
}
if (attr->pshared.data() != se32(0x200))
if (attr->pshared.data() != se32(0x200) || attr->ipc_key.data() || attr->flags.data())
{
sys_semaphore.Error("Unknown pshared attribute (0x%x)", attr->pshared);
sys_semaphore.Error("sys_semaphore_create(): unknown attributes (pshared=0x%x, ipc_key=0x%x, flags=0x%x)", attr->pshared, attr->ipc_key, attr->flags);
return CELL_EINVAL;
}
*sem = semaphore_create(initial_count, max_count, attr->protocol, attr->name_u64);
*sem = semaphore_create(initial_val, max_val, protocol, attr->name_u64);
return CELL_OK;
}
s32 sys_semaphore_destroy(u32 sem_id)
s32 sys_semaphore_destroy(u32 sem)
{
sys_semaphore.Warning("sys_semaphore_destroy(sem_id=%d)", sem_id);
sys_semaphore.Warning("sys_semaphore_destroy(sem=%d)", sem);
std::shared_ptr<Semaphore> sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
LV2_LOCK;
std::shared_ptr<semaphore_t> semaphore;
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
{
return CELL_ESRCH;
}
if (sem->queue.count()) // TODO: safely make object unusable
if (semaphore->waiters)
{
return CELL_EBUSY;
}
Emu.GetIdManager().RemoveID(sem_id);
Emu.GetIdManager().RemoveID(sem);
return CELL_OK;
}
s32 sys_semaphore_wait(u32 sem_id, u64 timeout)
s32 sys_semaphore_wait(u32 sem, u64 timeout)
{
sys_semaphore.Log("sys_semaphore_wait(sem_id=%d, timeout=%lld)", sem_id, timeout);
sys_semaphore.Log("sys_semaphore_wait(sem=%d, timeout=0x%llx)", sem, timeout);
const u64 start_time = get_system_time();
std::shared_ptr<Semaphore> sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
LV2_LOCK;
std::shared_ptr<semaphore_t> semaphore;
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
{
return CELL_ESRCH;
}
const u32 tid = GetCurrentPPUThread().GetId();
s32 old_value;
// protocol is ignored in current implementation
semaphore->waiters++; assert(semaphore->waiters > 0);
while (semaphore->value <= 0)
{
sem->value.atomic_op_sync([&old_value](s32& value)
{
old_value = value;
if (value > 0)
{
value--;
}
});
if (old_value > 0)
{
return CELL_OK;
}
sem->queue.push(tid, sem->protocol);
}
while (true)
{
if (sem->queue.pop(tid, sem->protocol))
{
break;
}
assert(!sem->value.read_sync());
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
if (timeout && get_system_time() - start_time > timeout)
{
if (!sem->queue.invalidate(tid, sem->protocol))
{
if (sem->queue.pop(tid, sem->protocol))
{
return CELL_OK;
}
assert(!"sys_semaphore_wait() failed (timeout)");
}
semaphore->waiters--; assert(semaphore->waiters >= 0);
return CELL_ETIMEDOUT;
}
if (Emu.IsStopped())
{
sys_semaphore.Warning("sys_semaphore_wait(%d) aborted", sem_id);
sys_semaphore.Warning("sys_semaphore_wait(%d) aborted", sem);
return CELL_OK;
}
semaphore->cv.wait_for(lv2_lock, std::chrono::milliseconds(1));
}
semaphore->value--;
semaphore->waiters--; assert(semaphore->waiters >= 0);
return CELL_OK;
}
s32 sys_semaphore_trywait(u32 sem_id)
s32 sys_semaphore_trywait(u32 sem)
{
sys_semaphore.Log("sys_semaphore_trywait(sem_id=%d)", sem_id);
sys_semaphore.Log("sys_semaphore_trywait(sem=%d)", sem);
std::shared_ptr<Semaphore> sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
LV2_LOCK;
std::shared_ptr<semaphore_t> semaphore;
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
{
return CELL_ESRCH;
}
s32 old_value;
sem->value.atomic_op_sync([&old_value](s32& value)
{
old_value = value;
if (value > 0)
{
value--;
}
});
if (old_value > 0)
{
return CELL_OK;
}
else
if (semaphore->value <= 0 || semaphore->waiters)
{
return CELL_EBUSY;
}
semaphore->value--;
return CELL_OK;
}
s32 sys_semaphore_post(u32 sem_id, s32 count)
s32 sys_semaphore_post(u32 sem, s32 count)
{
sys_semaphore.Log("sys_semaphore_post(sem_id=%d, count=%d)", sem_id, count);
sys_semaphore.Log("sys_semaphore_post(sem=%d, count=%d)", sem, count);
std::shared_ptr<Semaphore> sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
LV2_LOCK;
std::shared_ptr<semaphore_t> semaphore;
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
{
return CELL_ESRCH;
}
@ -197,52 +156,35 @@ s32 sys_semaphore_post(u32 sem_id, s32 count)
return CELL_EINVAL;
}
if (count + sem->value.read_sync() - (s32)sem->queue.count() > sem->max)
if (semaphore->value + count > semaphore->max + semaphore->waiters)
{
return CELL_EBUSY;
}
while (count > 0)
{
if (Emu.IsStopped())
{
sys_semaphore.Warning("sys_semaphore_post(%d) aborted", sem_id);
return CELL_OK;
}
if (u32 target = sem->queue.signal(sem->protocol))
{
count--;
}
else
{
sem->value.atomic_op([count](s32& value)
{
value += count;
});
count = 0;
}
}
semaphore->value += count; assert(semaphore->value >= 0);
semaphore->cv.notify_all();
return CELL_OK;
}
s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count)
s32 sys_semaphore_get_value(u32 sem, vm::ptr<s32> count)
{
sys_semaphore.Log("sys_semaphore_get_value(sem_id=%d, count_addr=0x%x)", sem_id, count.addr());
sys_semaphore.Log("sys_semaphore_get_value(sem=%d, count=*0x%x)", sem, count);
if (!count)
{
sys_semaphore.Error("sys_semaphore_get_value(): invalid memory access (addr=0x%x)", count.addr());
return CELL_EFAULT;
}
std::shared_ptr<Semaphore> sem;
if (!Emu.GetIdManager().GetIDData(sem_id, sem))
LV2_LOCK;
std::shared_ptr<semaphore_t> semaphore;
if (!Emu.GetIdManager().GetIDData(sem, semaphore))
{
return CELL_ESRCH;
}
*count = sem->value.read_sync();
*count = std::max<s32>(0, semaphore->value - semaphore->waiters);
return CELL_OK;
}

View file

@ -1,12 +1,13 @@
#pragma once
struct sys_semaphore_attribute
struct sys_semaphore_attribute_t
{
be_t<u32> protocol;
be_t<u32> pshared; // undefined
be_t<u64> ipc_key; // undefined
be_t<s32> flags; // undefined
be_t<u32> pad; // not used
be_t<u32> pshared;
be_t<u64> ipc_key;
be_t<s32> flags;
be_t<u32> pad;
union
{
char name[8];
@ -14,31 +15,35 @@ struct sys_semaphore_attribute
};
};
struct Semaphore
struct semaphore_t
{
sleep_queue_t queue;
atomic_le_t<s32> value;
const s32 max;
const u32 protocol;
const s32 max;
const u64 name;
Semaphore(s32 initial_count, s32 max_count, u32 protocol, u64 name)
: max(max_count)
, protocol(protocol)
std::atomic<s32> value;
// TODO: use sleep queue, possibly remove condition variable
std::condition_variable cv;
std::atomic<s32> waiters;
semaphore_t(u32 protocol, s32 max, u64 name, s32 value)
: protocol(protocol)
, max(max)
, name(name)
, value(value)
, waiters(0)
{
value.write_relaxed(initial_count);
}
};
// Aux
u32 semaphore_create(s32 initial_count, s32 max_count, u32 protocol, u64 name_u64);
u32 semaphore_create(s32 initial_val, s32 max_val, u32 protocol, u64 name_u64);
// SysCalls
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute> attr, s32 initial_count, s32 max_count);
s32 sys_semaphore_destroy(u32 sem_id);
s32 sys_semaphore_wait(u32 sem_id, u64 timeout);
s32 sys_semaphore_trywait(u32 sem_id);
s32 sys_semaphore_post(u32 sem_id, s32 count);
s32 sys_semaphore_get_value(u32 sem_id, vm::ptr<s32> count);
s32 sys_semaphore_create(vm::ptr<u32> sem, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_destroy(u32 sem);
s32 sys_semaphore_wait(u32 sem, u64 timeout);
s32 sys_semaphore_trywait(u32 sem);
s32 sys_semaphore_post(u32 sem, s32 count);
s32 sys_semaphore_get_value(u32 sem, vm::ptr<s32> count);

View file

@ -266,12 +266,14 @@ s32 sys_spu_thread_group_destroy(u32 id)
Memory.MainMem.Free(spu.offset);
Emu.GetCPU().RemoveThread(spu.GetId());
t.reset();
}
}
group->threads = {};
group->state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; // hack
Emu.GetIdManager().RemoveID(id);
return CELL_OK;
}