mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Merge pull request #1032 from Nekotekina/master
lv2 sema/rwlock, bugfox, cleanup
This commit is contained in:
commit
e5de176b16
28 changed files with 526 additions and 1068 deletions
|
@ -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)...));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; };
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -110,4 +110,4 @@ psv_log_base sceDisplay("SceDisplay", []()
|
|||
REG_FUNC(0x3E796EF5, sceDisplayWaitSetFrameBufMultiCB);
|
||||
REG_FUNC(0x6BDF4C4D, sceDisplayRegisterVblankStartCallback);
|
||||
REG_FUNC(0x98436A80, sceDisplayUnregisterVblankStartCallback);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -28,7 +28,6 @@ PPUThread& GetCurrentPPUThread()
|
|||
|
||||
PPUThread::PPUThread() : CPUThread(CPU_THREAD_PPU)
|
||||
{
|
||||
owned_mutexes = 0;
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue