Minor fixes

This commit is contained in:
Nekotekina 2016-08-20 00:14:10 +03:00
parent e32c49c12c
commit df6607e236
52 changed files with 309 additions and 282 deletions

View File

@ -10,6 +10,8 @@
#include <mutex>
namespace vm { using namespace ps3; }
logs::channel cellFs("cellFs", logs::level::notice);
s32 cellFsOpen(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, vm::cptr<void> arg, u64 size)

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
namespace vm { using namespace ps3; }
logs::channel cellOvis("cellOvis", logs::level::notice);
// Return Codes

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
namespace vm { using namespace ps3; }
logs::channel cellSpudll("cellSpudll", logs::level::notice);
s32 cellSpudllGetImageSize(vm::ptr<u32> psize, vm::cptr<void> so_elf, vm::cptr<struct CellSpudllHandleConfig> config)

View File

@ -10,6 +10,7 @@
#include "cellSpurs.h"
#include <thread>
#include <mutex>
//----------------------------------------------------------------------------
// Externs

View File

@ -1,5 +1,7 @@
#pragma once
namespace vm { using namespace ps3; }
// Error Codes
enum
{

View File

@ -3,6 +3,8 @@
#include "libsynth2.h"
namespace vm { using namespace ps3; }
logs::channel libsynth2("libsynth2", logs::level::notice);
s32 cellSoundSynth2Config(s16 param, s32 value)

View File

@ -3,6 +3,8 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/PPUOpcodes.h"
namespace vm { using namespace ps3; }
logs::channel sys_libc("sys_libc", logs::level::notice);
namespace sys_libc_func

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
namespace vm { using namespace ps3; }
extern logs::channel sysPrxForUser;
extern fs::file g_tty;

View File

@ -86,13 +86,13 @@ void sys_ppu_thread_exit(ppu_thread& ppu, u64 val)
return _sys_ppu_thread_exit(ppu, val);
}
std::mutex g_once_mutex;
shared_mutex g_once_mutex;
void sys_ppu_thread_once(ppu_thread& ppu, vm::ptr<atomic_be_t<u32>> once_ctrl, vm::ptr<void()> init)
{
sysPrxForUser.warning("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init);
std::lock_guard<std::mutex> lock(g_once_mutex);
writer_lock lock(g_once_mutex);
if (once_ctrl->compare_and_swap_test(SYS_PPU_THREAD_ONCE_INIT, SYS_PPU_THREAD_DONE_INIT))
{

View File

@ -7,6 +7,8 @@
#include "yaml-cpp/yaml.h"
namespace vm { using namespace ps3; }
const ppu_decoder<ppu_itype> s_ppu_itype;
const ppu_decoder<ppu_iname> s_ppu_iname;

View File

@ -15,6 +15,8 @@
#include <unordered_set>
#include <algorithm>
namespace vm { using namespace ps3; }
LOG_CHANNEL(cellAdec);
LOG_CHANNEL(cellAtrac);
LOG_CHANNEL(cellAtracMulti);

View File

@ -4,8 +4,6 @@
#include "PPUCallback.h"
#include "ErrorCodes.h"
namespace vm { using namespace ps3; }
// Generate FNID or VNID for given name
extern u32 ppu_generate_id(const char* name);
@ -28,7 +26,7 @@ struct ppu_static_function
struct ppu_static_variable
{
const char* name;
vm::gvar<void>* var; // Pointer to variable address storage
vm::ps3::gvar<void>* var; // Pointer to variable address storage
void(*init)(); // Variable initialization function
u32 size;
u32 align;
@ -95,7 +93,7 @@ public:
auto& info = access_static_variable(module, vnid);
info.name = name;
info.var = reinterpret_cast<vm::gvar<void>*>(Var);
info.var = reinterpret_cast<vm::ps3::gvar<void>*>(Var);
info.init = init ? init : [] {};
info.size = SIZE_32(typename T::type);
info.align = ALIGN_32(typename T::type);

View File

@ -41,6 +41,8 @@
#include "Modules/cellMsgDialog.h"
#endif
namespace vm { using namespace ps3; }
enum class ppu_decoder_type
{
precise,

View File

@ -21,6 +21,7 @@
#include <cmath>
#include <cfenv>
#include <thread>
#include <mutex>
extern u64 get_timebased_time();
@ -210,7 +211,7 @@ void SPUThread::cpu_task()
(fmt::throw_exception<std::logic_error>("Invalid SPU decoder"), nullptr));
// LS base address
const auto base = vm::_ptr<const u32>(offset);
const auto base = vm::ps3::_ptr<const u32>(offset);
while (true)
{
@ -348,7 +349,7 @@ void SPUThread::do_dma_list_cmd(u32 cmd, spu_mfc_arg_t args)
for (u32 i = 0; i < list_size; i++)
{
auto rec = vm::ptr<list_element>::make(offset + list_addr + i * 8);
auto rec = vm::ps3::ptr<list_element>::make(offset + list_addr + i * 8);
const u32 size = rec->ts;
const u32 addr = rec->ea;

View File

@ -10,6 +10,8 @@
#include <algorithm>
namespace vm { using namespace ps3; }
logs::channel sys_cond("sys_cond", logs::level::notice);
extern u64 get_system_time();

View File

@ -40,7 +40,7 @@ struct lv2_cond_t
class ppu_thread;
// SysCalls
s32 sys_cond_create(vm::ptr<u32> cond_id, u32 mutex_id, vm::ptr<sys_cond_attribute_t> attr);
s32 sys_cond_create(vm::ps3::ptr<u32> cond_id, u32 mutex_id, vm::ps3::ptr<sys_cond_attribute_t> attr);
s32 sys_cond_destroy(u32 cond_id);
s32 sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout);
s32 sys_cond_signal(u32 cond_id);

View File

@ -6,4 +6,6 @@
#include "Emu/Cell/ErrorCodes.h"
#include "sys_dbg.h"
namespace vm { using namespace ps3; }
logs::channel sys_dbg("sys_dbg", logs::level::notice);

View File

@ -1,3 +1 @@
#pragma once
namespace vm { using namespace ps3; }

View File

@ -10,6 +10,8 @@
#include "sys_process.h"
#include "sys_event.h"
namespace vm { using namespace ps3; }
logs::channel sys_event("sys_event", logs::level::notice);
template<> DECLARE(ipc_manager<lv2_event_queue_t, u64>::g_ipc) {};

View File

@ -2,6 +2,8 @@
#include "sys_sync.h"
class cpu_thread;
// Event Queue Type
enum : u32
{
@ -135,13 +137,13 @@ struct lv2_event_port_t
class ppu_thread;
// SysCalls
s32 sys_event_queue_create(vm::ptr<u32> equeue_id, vm::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size);
s32 sys_event_queue_create(vm::ps3::ptr<u32> equeue_id, vm::ps3::ptr<sys_event_queue_attribute_t> attr, u64 event_queue_key, s32 size);
s32 sys_event_queue_destroy(u32 equeue_id, s32 mode);
s32 sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ptr<sys_event_t> dummy_event, u64 timeout);
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ptr<sys_event_t> event_array, s32 size, vm::ptr<u32> number);
s32 sys_event_queue_receive(ppu_thread& ppu, u32 equeue_id, vm::ps3::ptr<sys_event_t> dummy_event, u64 timeout);
s32 sys_event_queue_tryreceive(u32 equeue_id, vm::ps3::ptr<sys_event_t> event_array, s32 size, vm::ps3::ptr<u32> number);
s32 sys_event_queue_drain(u32 event_queue_id);
s32 sys_event_port_create(vm::ptr<u32> eport_id, s32 port_type, u64 name);
s32 sys_event_port_create(vm::ps3::ptr<u32> eport_id, s32 port_type, u64 name);
s32 sys_event_port_destroy(u32 eport_id);
s32 sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
s32 sys_event_port_disconnect(u32 eport_id);

View File

@ -9,6 +9,8 @@
#include <algorithm>
namespace vm { using namespace ps3; }
logs::channel sys_event_flag("sys_event_flag", logs::level::notice);
extern u64 get_system_time();

View File

@ -114,11 +114,11 @@ struct lv2_event_flag_t
class ppu_thread;
// SysCalls
s32 sys_event_flag_create(vm::ptr<u32> id, vm::ptr<sys_event_flag_attribute_t> attr, u64 init);
s32 sys_event_flag_create(vm::ps3::ptr<u32> id, vm::ps3::ptr<sys_event_flag_attribute_t> attr, u64 init);
s32 sys_event_flag_destroy(u32 id);
s32 sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result, u64 timeout);
s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ptr<u64> result);
s32 sys_event_flag_wait(ppu_thread& ppu, u32 id, u64 bitptn, u32 mode, vm::ps3::ptr<u64> result, u64 timeout);
s32 sys_event_flag_trywait(u32 id, u64 bitptn, u32 mode, vm::ps3::ptr<u64> result);
s32 sys_event_flag_set(u32 id, u64 bitptn);
s32 sys_event_flag_clear(u32 id, u64 bitptn);
s32 sys_event_flag_cancel(u32 id, vm::ptr<u32> num);
s32 sys_event_flag_get(u32 id, vm::ptr<u64> flags);
s32 sys_event_flag_cancel(u32 id, vm::ps3::ptr<u32> num);
s32 sys_event_flag_get(u32 id, vm::ps3::ptr<u64> flags);

View File

@ -8,6 +8,8 @@
#include "Emu/Cell/PPUOpcodes.h"
#include "sys_interrupt.h"
namespace vm { using namespace ps3; }
logs::channel sys_interrupt("sys_interrupt", logs::level::notice);
lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)

View File

@ -38,6 +38,6 @@ struct lv2_int_serv_t
// SysCalls
s32 sys_interrupt_tag_destroy(u32 intrtag);
s32 _sys_interrupt_thread_establish(vm::ptr<u32> ih, u32 intrtag, u32 intrthread, u64 arg1, u64 arg2);
s32 _sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih, vm::ptr<u64> r13);
s32 _sys_interrupt_thread_establish(vm::ps3::ptr<u32> ih, u32 intrtag, u32 intrthread, u64 arg1, u64 arg2);
s32 _sys_interrupt_thread_disestablish(ppu_thread& ppu, u32 ih, vm::ps3::ptr<u64> r13);
void sys_interrupt_thread_eoi(ppu_thread& ppu);

View File

@ -7,6 +7,8 @@
#include "Emu/Cell/PPUThread.h"
#include "sys_lwmutex.h"
namespace vm { using namespace ps3; }
logs::channel sys_lwmutex("sys_lwmutex", logs::level::notice);
extern u64 get_system_time();

View File

@ -71,7 +71,7 @@ struct lv2_lwmutex_t
class ppu_thread;
// SysCalls
s32 _sys_lwmutex_create(vm::ptr<u32> lwmutex_id, u32 protocol, vm::ptr<sys_lwmutex_t> control, u32 arg4, u64 name, u32 arg6);
s32 _sys_lwmutex_create(vm::ps3::ptr<u32> lwmutex_id, u32 protocol, vm::ps3::ptr<sys_lwmutex_t> control, u32 arg4, u64 name, u32 arg6);
s32 _sys_lwmutex_destroy(u32 lwmutex_id);
s32 _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout);
s32 _sys_lwmutex_trylock(u32 lwmutex_id);

View File

@ -86,28 +86,25 @@ error_code sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::
}
}
error_code result{};
const auto ct = idm::get<lv2_memory_container>(cid, [&](lv2_memory_container& ct)
const auto ct = idm::get<lv2_memory_container>(cid, [&](lv2_memory_container& ct) -> CellError
{
// Try to get "physical memory"
if (!ct.take(size))
{
result = CELL_ENOMEM;
return false;
return CELL_ENOMEM;
}
return true;
return {};
});
if (!ct && !result)
if (!ct)
{
return CELL_ESRCH;
}
if (!ct)
if (ct.value)
{
return result;
return ct.value;
}
// Allocate memory, write back the start address of the allocated area, use cid as the supplementary info
@ -206,28 +203,25 @@ error_code sys_memory_container_destroy(u32 cid)
{
sys_memory.warning("sys_memory_container_destroy(cid=0x%x)", cid);
error_code result{};
const auto ct = idm::withdraw<lv2_memory_container>(cid, [&](lv2_memory_container& ct)
const auto ct = idm::withdraw<lv2_memory_container>(cid, [](lv2_memory_container& ct) -> CellError
{
// Check if some memory is not deallocated (the container cannot be destroyed in this case)
if (!ct.used.compare_and_swap_test(0, ct.size))
{
result = CELL_EBUSY;
return false;
return CELL_EBUSY;
}
return true;
return {};
});
if (!ct && !result)
if (!ct)
{
return CELL_ESRCH;
}
if (!ct)
if (ct.value)
{
return result;
return ct.value;
}
// Return "physical memory" to the default container

View File

@ -141,28 +141,25 @@ error_code sys_mmapper_allocate_shared_memory_from_container(u64 unk, u32 size,
}
}
error_code result{};
const auto ct = idm::get<lv2_memory_container>(cid, [&](lv2_memory_container& ct)
const auto ct = idm::get<lv2_memory_container>(cid, [&](lv2_memory_container& ct) -> CellError
{
// Try to get "physical memory"
if (!ct.take(size))
{
result = CELL_ENOMEM;
return false;
return CELL_ENOMEM;
}
return true;
return {};
});
if (!ct && !result)
if (!ct)
{
return CELL_ESRCH;
}
if (!ct)
if (ct.value)
{
return result;
return ct.value;
}
// Generate a new mem ID
@ -202,28 +199,25 @@ error_code sys_mmapper_free_shared_memory(u32 mem_id)
{
sys_mmapper.warning("sys_mmapper_free_shared_memory(mem_id=0x%x)", mem_id);
error_code result{};
// Conditionally remove memory ID
const auto mem = idm::withdraw<lv2_memory>(mem_id, [&](lv2_memory& mem)
const auto mem = idm::withdraw<lv2_memory>(mem_id, [&](lv2_memory& mem) -> CellError
{
if (mem.addr.compare_and_swap_test(0, -1))
{
result = CELL_EBUSY;
return false;
return CELL_EBUSY;
}
return true;
return {};
});
if (!mem && !result)
if (!mem)
{
return CELL_ESRCH;
}
if (!mem)
if (mem.value)
{
return result;
return mem.value;
}
// Return "physical memory" to the memory container

View File

@ -7,6 +7,8 @@
#include "Emu/Cell/PPUThread.h"
#include "sys_mutex.h"
namespace vm { using namespace ps3; }
logs::channel sys_mutex("sys_mutex", logs::level::notice);
extern u64 get_system_time();

View File

@ -48,7 +48,7 @@ struct lv2_mutex_t
class ppu_thread;
// SysCalls
s32 sys_mutex_create(vm::ptr<u32> mutex_id, vm::ptr<sys_mutex_attribute_t> attr);
s32 sys_mutex_create(vm::ps3::ptr<u32> mutex_id, vm::ps3::ptr<sys_mutex_attribute_t> attr);
s32 sys_mutex_destroy(u32 mutex_id);
s32 sys_mutex_lock(ppu_thread& ppu, u32 mutex_id, u64 timeout);
s32 sys_mutex_trylock(ppu_thread& ppu, u32 mutex_id);

View File

@ -9,6 +9,8 @@
#include <thread>
namespace vm { using namespace ps3; }
logs::channel sys_ppu_thread("sys_ppu_thread", logs::level::notice);
void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)

View File

@ -44,14 +44,14 @@ enum : u32
// SysCalls
void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode);
void sys_ppu_thread_yield();
s32 sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr);
s32 sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ps3::ptr<u64> vptr);
s32 sys_ppu_thread_detach(u32 thread_id);
void sys_ppu_thread_get_join_state(ppu_thread& ppu, vm::ptr<s32> isjoinable);
void sys_ppu_thread_get_join_state(ppu_thread& ppu, vm::ps3::ptr<s32> isjoinable);
s32 sys_ppu_thread_set_priority(u32 thread_id, s32 prio);
s32 sys_ppu_thread_get_priority(u32 thread_id, vm::ptr<s32> priop);
s32 sys_ppu_thread_get_stack_information(ppu_thread& ppu, vm::ptr<sys_ppu_thread_stack_t> sp);
s32 sys_ppu_thread_get_priority(u32 thread_id, vm::ps3::ptr<s32> priop);
s32 sys_ppu_thread_get_stack_information(ppu_thread& ppu, vm::ps3::ptr<sys_ppu_thread_stack_t> sp);
s32 sys_ppu_thread_stop(u32 thread_id);
s32 sys_ppu_thread_restart(u32 thread_id);
s32 _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 arg4, s32 prio, u32 stacksize, u64 flags, vm::cptr<char> threadname);
s32 _sys_ppu_thread_create(vm::ps3::ptr<u64> thread_id, vm::ps3::ptr<ppu_thread_param_t> param, u64 arg, u64 arg4, s32 prio, u32 stacksize, u64 flags, vm::ps3::cptr<char> threadname);
s32 sys_ppu_thread_start(u32 thread_id);
s32 sys_ppu_thread_rename(u32 thread_id, vm::cptr<char> name);
s32 sys_ppu_thread_rename(u32 thread_id, vm::ps3::cptr<char> name);

View File

@ -23,6 +23,8 @@
#include <thread>
namespace vm { using namespace ps3; }
logs::channel sys_process("sys_process", logs::level::notice);
u32 g_ps3_sdk_version;
@ -49,14 +51,11 @@ s32 sys_process_exit(s32 status)
{
sys_process.warning("sys_process_exit(status=0x%x)", status);
LV2_LOCK;
CHECK_EMU_STATUS;
sys_process.success("Process finished");
Emu.CallAfter([]()
{
sys_process.success("Process finished");
Emu.Stop();
});

View File

@ -1,7 +1,5 @@
#pragma once
namespace vm { using namespace ps3; }
// Process Local Object Type
enum : u32
{
@ -33,16 +31,16 @@ s32 process_is_spu_lock_line_reservation_address(u32 addr, u64 flags);
// SysCalls
s32 sys_process_getpid();
s32 sys_process_getppid();
s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump);
s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> set_size);
s32 _sys_process_get_paramsfo(vm::ptr<char> buffer);
s32 sys_process_get_sdk_version(u32 pid, vm::ptr<s32> version);
s32 sys_process_get_number_of_object(u32 object, vm::ps3::ptr<u32> nump);
s32 sys_process_get_id(u32 object, vm::ps3::ptr<u32> buffer, u32 size, vm::ps3::ptr<u32> set_size);
s32 _sys_process_get_paramsfo(vm::ps3::ptr<char> buffer);
s32 sys_process_get_sdk_version(u32 pid, vm::ps3::ptr<s32> version);
s32 sys_process_get_status(u64 unk);
s32 sys_process_is_spu_lock_line_reservation_address(u32 addr, u64 flags);
s32 sys_process_exit(s32 errorcode);
s32 sys_process_kill(u32 pid);
s32 sys_process_wait_for_child(u32 pid, vm::ptr<u32> status, u64 unk);
s32 sys_process_wait_for_child(u32 pid, vm::ps3::ptr<u32> status, u64 unk);
s32 sys_process_wait_for_child2(u64 unk1, u64 unk2, u64 unk3, u64 unk4, u64 unk5, u64 unk6);
s32 sys_process_detach_child(u64 unk);
void sys_game_process_exitspawn(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);
void sys_game_process_exitspawn2(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);
void sys_game_process_exitspawn(vm::ps3::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);
void sys_game_process_exitspawn2(vm::ps3::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);

View File

@ -8,6 +8,8 @@
#include "Emu/Cell/ErrorCodes.h"
#include "sys_prx.h"
namespace vm { using namespace ps3; }
extern std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object&);
logs::channel sys_prx("sys_prx", logs::level::notice);

View File

@ -2,8 +2,6 @@
#include "Emu/Cell/PPUAnalyser.h"
namespace vm { using namespace ps3; }
// Return codes
enum
{
@ -35,13 +33,13 @@ enum
struct sys_prx_get_module_id_by_name_option_t
{
be_t<u64> size;
vm::ptr<void> base;
vm::ps3::ptr<void> base;
};
struct sys_prx_load_module_option_t
{
be_t<u64> size;
vm::bptr<void> base_addr;
vm::ps3::bptr<void> base_addr;
};
struct sys_prx_segment_info_t;// TODO
@ -51,14 +49,14 @@ struct sys_prx_start_module_option_t
{
be_t<u64> size;
be_t<u64> put;
vm::bptr<s32(int argc, vm::ptr<void> argv), u64> entry_point;
vm::ps3::bptr<s32(int argc, vm::ps3::ptr<void> argv), u64> entry_point;
};
struct sys_prx_stop_module_option_t
{
be_t<u64> size;
be_t<u64> put;
vm::bptr<s32(int argc, vm::ptr<void> argv), u64> entry_point;
vm::ps3::bptr<s32(int argc, vm::ps3::ptr<void> argv), u64> entry_point;
};
struct sys_prx_unload_module_option_t
@ -71,7 +69,7 @@ struct sys_prx_get_module_list_t
be_t<u64> size;
be_t<u32> max;
be_t<u32> count;
vm::bptr<s32> idlist;
vm::ps3::bptr<s32> idlist;
};
struct lv2_prx_t
@ -87,29 +85,29 @@ struct lv2_prx_t
std::unordered_map<u32, u32> specials;
std::vector<ppu_function> funcs;
vm::ptr<s32(int argc, vm::ptr<void> argv)> start = vm::null;
vm::ptr<s32(int argc, vm::ptr<void> argv)> stop = vm::null;
vm::ptr<s32()> exit = vm::null;
vm::ps3::ptr<s32(int argc, vm::ps3::ptr<void> argv)> start = vm::null;
vm::ps3::ptr<s32(int argc, vm::ps3::ptr<void> argv)> stop = vm::null;
vm::ps3::ptr<s32()> exit = vm::null;
lv2_prx_t();
};
// SysCalls
s32 sys_prx_load_module(vm::cptr<char> path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt);
s32 sys_prx_load_module_list(s32 count, vm::cpptr<char> path_list, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, vm::ptr<u32> id_list);
s32 sys_prx_load_module(vm::ps3::cptr<char> path, u64 flags, vm::ps3::ptr<sys_prx_load_module_option_t> pOpt);
s32 sys_prx_load_module_list(s32 count, vm::ps3::cpptr<char> path_list, u64 flags, vm::ps3::ptr<sys_prx_load_module_option_t> pOpt, vm::ps3::ptr<u32> id_list);
s32 sys_prx_load_module_on_memcontainer();
s32 sys_prx_load_module_by_fd();
s32 sys_prx_load_module_on_memcontainer_by_fd();
s32 sys_prx_start_module(s32 id, u64 flags, vm::ptr<sys_prx_start_module_option_t> pOpt);
s32 sys_prx_stop_module(s32 id, u64 flags, vm::ptr<sys_prx_stop_module_option_t> pOpt);
s32 sys_prx_unload_module(s32 id, u64 flags, vm::ptr<sys_prx_unload_module_option_t> pOpt);
s32 sys_prx_get_module_list(u64 flags, vm::ptr<sys_prx_get_module_list_t> pInfo);
s32 sys_prx_start_module(s32 id, u64 flags, vm::ps3::ptr<sys_prx_start_module_option_t> pOpt);
s32 sys_prx_stop_module(s32 id, u64 flags, vm::ps3::ptr<sys_prx_stop_module_option_t> pOpt);
s32 sys_prx_unload_module(s32 id, u64 flags, vm::ps3::ptr<sys_prx_unload_module_option_t> pOpt);
s32 sys_prx_get_module_list(u64 flags, vm::ps3::ptr<sys_prx_get_module_list_t> pInfo);
s32 sys_prx_get_my_module_id();
s32 sys_prx_get_module_id_by_address();
s32 sys_prx_get_module_id_by_name(vm::cptr<char> name, u64 flags, vm::ptr<sys_prx_get_module_id_by_name_option_t> pOpt);
s32 sys_prx_get_module_info(s32 id, u64 flags, vm::ptr<sys_prx_module_info_t> info);
s32 sys_prx_register_library(vm::ptr<void> library);
s32 sys_prx_unregister_library(vm::ptr<void> library);
s32 sys_prx_get_module_id_by_name(vm::ps3::cptr<char> name, u64 flags, vm::ps3::ptr<sys_prx_get_module_id_by_name_option_t> pOpt);
s32 sys_prx_get_module_info(s32 id, u64 flags, vm::ps3::ptr<sys_prx_module_info_t> info);
s32 sys_prx_register_library(vm::ps3::ptr<void> library);
s32 sys_prx_unregister_library(vm::ps3::ptr<void> library);
s32 sys_prx_get_ppu_guid();
s32 sys_prx_register_module();
s32 sys_prx_query_module();

View File

@ -5,6 +5,8 @@
#include "Emu/Cell/ErrorCodes.h"
#include "sys_rsx.h"
namespace vm { using namespace ps3; }
logs::channel sys_rsx("sys_rsx", logs::level::notice);
s32 sys_rsx_device_open()

View File

@ -1,17 +1,15 @@
#pragma once
namespace vm { using namespace ps3; }
// SysCalls
s32 sys_rsx_device_open();
s32 sys_rsx_device_close();
s32 sys_rsx_memory_allocate(vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
s32 sys_rsx_memory_allocate(vm::ps3::ptr<u32> mem_handle, vm::ps3::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
s32 sys_rsx_memory_free(u32 mem_handle);
s32 sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u32> lpar_dma_control, vm::ptr<u32> lpar_driver_info, vm::ptr<u32> lpar_reports, u64 mem_ctx, u64 system_mode);
s32 sys_rsx_context_allocate(vm::ps3::ptr<u32> context_id, vm::ps3::ptr<u32> lpar_dma_control, vm::ps3::ptr<u32> lpar_driver_info, vm::ps3::ptr<u32> lpar_reports, u64 mem_ctx, u64 system_mode);
s32 sys_rsx_context_free(u32 context_id);
s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
s32 sys_rsx_context_iounmap(u32 context_id, u32 a2, u32 io_addr, u32 size);
s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
s32 sys_rsx_device_map(vm::ptr<u32> addr, vm::ptr<u32> a2, u32 dev_id);
s32 sys_rsx_device_map(vm::ps3::ptr<u32> addr, vm::ps3::ptr<u32> a2, u32 dev_id);
s32 sys_rsx_device_unmap(u32 dev_id);
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);

View File

@ -7,6 +7,8 @@
#include "Emu/Cell/PPUThread.h"
#include "sys_rwlock.h"
namespace vm { using namespace ps3; }
logs::channel sys_rwlock("sys_rwlock", logs::level::notice);
extern u64 get_system_time();

View File

@ -45,7 +45,7 @@ struct lv2_rwlock_t
class ppu_thread;
// SysCalls
s32 sys_rwlock_create(vm::ptr<u32> rw_lock_id, vm::ptr<sys_rwlock_attribute_t> attr);
s32 sys_rwlock_create(vm::ps3::ptr<u32> rw_lock_id, vm::ps3::ptr<sys_rwlock_attribute_t> attr);
s32 sys_rwlock_destroy(u32 rw_lock_id);
s32 sys_rwlock_rlock(ppu_thread& ppu, u32 rw_lock_id, u64 timeout);
s32 sys_rwlock_tryrlock(u32 rw_lock_id);

View File

@ -7,6 +7,8 @@
#include "Emu/Cell/PPUThread.h"
#include "sys_semaphore.h"
namespace vm { using namespace ps3; }
logs::channel sys_semaphore("sys_semaphore", logs::level::notice);
extern u64 get_system_time();

View File

@ -44,9 +44,9 @@ struct lv2_sema_t
class ppu_thread;
// SysCalls
s32 sys_semaphore_create(vm::ptr<u32> sem_id, vm::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_create(vm::ps3::ptr<u32> sem_id, vm::ps3::ptr<sys_semaphore_attribute_t> attr, s32 initial_val, s32 max_val);
s32 sys_semaphore_destroy(u32 sem_id);
s32 sys_semaphore_wait(ppu_thread& ppu, 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_get_value(u32 sem_id, vm::ps3::ptr<s32> count);

View File

@ -11,6 +11,8 @@
#include "sys_event.h"
#include "sys_spu.h"
namespace vm { using namespace ps3; }
logs::channel sys_spu("sys_spu", logs::level::notice);
void LoadSpuImage(const fs::file& stream, u32& spu_ep, u32 addr)

View File

@ -57,7 +57,7 @@ enum : s32
struct sys_spu_thread_group_attribute
{
be_t<u32> nsize; // name length including NULL terminator
vm::bcptr<char> name;
vm::ps3::bcptr<char> name;
be_t<s32> type;
be_t<u32> ct; // memory container id
};
@ -71,7 +71,7 @@ enum : u32
struct sys_spu_thread_attribute
{
vm::bcptr<char> name;
vm::ps3::bcptr<char> name;
be_t<u32> name_len;
be_t<u32> option;
};
@ -109,7 +109,7 @@ struct sys_spu_image_t
{
be_t<u32> type; // user, kernel
be_t<u32> entry_point;
vm::bptr<sys_spu_segment> segs;
vm::ps3::bptr<sys_spu_segment> segs;
be_t<s32> nsegs;
};
@ -149,7 +149,7 @@ struct lv2_spu_group_t
const u32 ct; // Memory Container Id
std::array<std::shared_ptr<SPUThread>, 256> threads; // SPU Threads
std::array<vm::ptr<sys_spu_image_t>, 256> images; // SPU Images
std::array<vm::ps3::ptr<sys_spu_image_t>, 256> images; // SPU Images
std::array<spu_arg_t, 256> args; // SPU Thread Arguments
s32 prio; // SPU Thread Group Priority
@ -208,41 +208,41 @@ u32 LoadSpuImage(const fs::file& stream, u32& spu_ep);
// SysCalls
s32 sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
s32 sys_spu_image_open(vm::ptr<sys_spu_image_t> img, vm::cptr<char> path);
s32 sys_spu_image_close(vm::ptr<sys_spu_image_t> img);
s32 sys_spu_thread_initialize(vm::ptr<u32> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image_t> img, vm::ptr<sys_spu_thread_attribute> attr, vm::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_set_argument(u32 id, vm::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_group_create(vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr);
s32 sys_spu_image_open(vm::ps3::ptr<sys_spu_image_t> img, vm::ps3::cptr<char> path);
s32 sys_spu_image_close(vm::ps3::ptr<sys_spu_image_t> img);
s32 sys_spu_thread_initialize(vm::ps3::ptr<u32> thread, u32 group, u32 spu_num, vm::ps3::ptr<sys_spu_image_t> img, vm::ps3::ptr<sys_spu_thread_attribute> attr, vm::ps3::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_set_argument(u32 id, vm::ps3::ptr<sys_spu_thread_argument> arg);
s32 sys_spu_thread_group_create(vm::ps3::ptr<u32> id, u32 num, s32 prio, vm::ps3::ptr<sys_spu_thread_group_attribute> attr);
s32 sys_spu_thread_group_destroy(u32 id);
s32 sys_spu_thread_group_start(u32 id);
s32 sys_spu_thread_group_suspend(u32 id);
s32 sys_spu_thread_group_resume(u32 id);
s32 sys_spu_thread_group_yield(u32 id);
s32 sys_spu_thread_group_terminate(u32 id, s32 value);
s32 sys_spu_thread_group_join(u32 id, vm::ptr<u32> cause, vm::ptr<u32> status);
s32 sys_spu_thread_group_join(u32 id, vm::ps3::ptr<u32> cause, vm::ps3::ptr<u32> status);
s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et);
s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et);
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, vm::ptr<u8> spup);
s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, vm::ps3::ptr<u8> spup);
s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup);
s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ptr<u64> value, u32 type);
s32 sys_spu_thread_read_ls(u32 id, u32 address, vm::ps3::ptr<u64> value, u32 type);
s32 sys_spu_thread_write_spu_mb(u32 id, u32 value);
s32 sys_spu_thread_set_spu_cfg(u32 id, u64 value);
s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ptr<u64> value);
s32 sys_spu_thread_get_spu_cfg(u32 id, vm::ps3::ptr<u64> value);
s32 sys_spu_thread_write_snr(u32 id, u32 number, u32 value);
s32 sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup);
s32 sys_spu_thread_disconnect_event(u32 id, u32 event_type, u8 spup);
s32 sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num);
s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num);
s32 sys_spu_thread_get_exit_status(u32 id, vm::ptr<u32> status);
s32 sys_spu_thread_get_exit_status(u32 id, vm::ps3::ptr<u32> status);
s32 sys_raw_spu_create(vm::ptr<u32> id, vm::ptr<void> attr);
s32 sys_raw_spu_create(vm::ps3::ptr<u32> id, vm::ps3::ptr<void> attr);
s32 sys_raw_spu_destroy(ppu_thread& ppu, u32 id);
s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr<u32> intrtag);
s32 sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ps3::ptr<u32> intrtag);
s32 sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask);
s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ptr<u64> mask);
s32 sys_raw_spu_get_int_mask(u32 id, u32 class_id, vm::ps3::ptr<u64> mask);
s32 sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat);
s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr<u64> stat);
s32 sys_raw_spu_read_puint_mb(u32 id, vm::ptr<u32> value);
s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ps3::ptr<u64> stat);
s32 sys_raw_spu_read_puint_mb(u32 id, vm::ps3::ptr<u32> value);
s32 sys_raw_spu_set_spu_cfg(u32 id, u32 value);
s32 sys_raw_spu_get_spu_cfg(u32 id, vm::ptr<u32> value);
s32 sys_raw_spu_get_spu_cfg(u32 id, vm::ps3::ptr<u32> value);

View File

@ -4,8 +4,6 @@
#include <mutex>
#include <condition_variable>
namespace vm { using namespace ps3; }
// attr_protocol (waiting scheduling policy)
enum
{

View File

@ -103,6 +103,8 @@ static int clock_gettime(int clk_id, struct timespec* tp)
#endif
namespace vm { using namespace ps3; }
logs::channel sys_time("sys_time", logs::level::notice);
static const u64 g_timebase_freq = /*79800000*/ 80000000; // 80 Mhz

View File

@ -1,8 +1,6 @@
#pragma once
namespace vm { using namespace ps3; }
// SysCalls
s32 sys_time_get_timezone(vm::ptr<s32> timezone, vm::ptr<s32> summertime);
s32 sys_time_get_current_time(vm::ptr<s64> sec, vm::ptr<s64> nsec);
s32 sys_time_get_timezone(vm::ps3::ptr<s32> timezone, vm::ps3::ptr<s32> summertime);
s32 sys_time_get_current_time(vm::ps3::ptr<s64> sec, vm::ps3::ptr<s64> nsec);
u64 sys_time_get_timebase_frequency();

View File

@ -8,6 +8,8 @@
#include "sys_process.h"
#include "sys_timer.h"
namespace vm { using namespace ps3; }
logs::channel sys_timer("sys_timer", logs::level::notice);
extern u64 get_system_time();

View File

@ -2,8 +2,6 @@
#include "Utilities/Thread.h"
namespace vm { using namespace ps3; }
// Timer State
enum : u32
{
@ -45,9 +43,9 @@ public:
u64 period = 0; // Period (oneshot if 0)
};
s32 sys_timer_create(vm::ptr<u32> timer_id);
s32 sys_timer_create(vm::ps3::ptr<u32> timer_id);
s32 sys_timer_destroy(u32 timer_id);
s32 sys_timer_get_information(u32 timer_id, vm::ptr<sys_timer_information_t> info);
s32 sys_timer_get_information(u32 timer_id, vm::ps3::ptr<sys_timer_information_t> info);
s32 _sys_timer_start(u32 timer_id, u64 basetime, u64 period); // basetime type changed from s64
s32 sys_timer_stop(u32 timer_id);
s32 sys_timer_connect_event_queue(u32 timer_id, u32 queue_id, u64 name, u64 data1, u64 data2);

View File

@ -5,6 +5,8 @@
#include "Emu/Cell/ErrorCodes.h"
#include "sys_trace.h"
namespace vm { using namespace ps3; }
logs::channel sys_trace("sys_trace", logs::level::notice);
s32 sys_trace_create()

View File

@ -1,7 +1,5 @@
#pragma once
namespace vm { using namespace ps3; }
// SysCalls
s32 sys_trace_create();
s32 sys_trace_start();

View File

@ -812,15 +812,6 @@ struct psp2_event_flag final
static const u32 id_step = 1;
static const u32 id_count = 32767;
struct alignas(8) ctrl_t
{
u32 waiters;
u32 pattern;
};
atomic_t<ctrl_t> ctrl; // Sync variable
atomic_t<u64> wait_ctr{}; // FIFO ordering helper
using ipc = ipc_manager<psp2_event_flag, std::string>;
const std::string name; // IPC/Debug Name
@ -829,11 +820,15 @@ struct psp2_event_flag final
const u32 attr;
const u32 init;
atomic_t<u32> pattern{0}; // Sync variable
atomic_t<u32> waiters{0}; // Waiter number or waiter id
atomic_t<u64> wait_ctr; // FIFO ordering helper
psp2_event_flag(std::string&& name, u32 attr, u32 pattern)
: ctrl({0, pattern})
, name(std::move(name))
: name(std::move(name))
, attr(attr)
, init(pattern)
, pattern(pattern)
{
}
@ -856,14 +851,15 @@ struct psp2_event_flag final
// Commands
enum class task : u32
{
null = 0,
wait,
poll,
set,
clear,
cancel,
destroy,
signal,
null,
wait, // Check condition, enqueue waiting thread
poll, // Check condition only
set, // Set pattern bits and wake up threads
clear, // Clear pattern bits (bitwise AND)
cancel, // Wake up all threads with SCE_KERNEL_ERROR_WAIT_CANCEL
destroy, // Wake up all threads with SCE_KERNEL_ERROR_WAIT_DELETE
timeout, // Dequeue waiting thread (cleanup)
signal, // Signal selected thread (aux)
};
struct alignas(8) cmd_t
@ -907,13 +903,29 @@ struct psp2_event_flag final
case task::wait: op_wait(cmd.arg); break;
case task::poll: op_poll(cmd.arg); break;
case task::set: op_set(cmd.arg); break;
case task::clear: op_clear(cmd.arg); break;
case task::clear: pattern &= cmd.arg; break;
case task::cancel: op_stop(vm::cast(cmd.arg), SCE_KERNEL_ERROR_WAIT_CANCEL); break;
case task::destroy: op_stop(vm::cast(cmd.arg), SCE_KERNEL_ERROR_WAIT_DELETE); break;
case task::timeout:
{
// Timeout cleanup
idm::check<ARMv7Thread>(cmd.arg, [&](ARMv7Thread& cpu)
{
if (cpu.owner.compare_and_swap_test(this, nullptr))
{
cpu.GPR[0] = SCE_KERNEL_ERROR_WAIT_TIMEOUT;
cpu.GPR[1] = pattern;
waiters -= attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
}
});
break;
}
case task::signal:
{
idm::get<ARMv7Thread>(cmd.arg, [&](ARMv7Thread& cpu)
idm::check<ARMv7Thread>(cmd.arg, [](auto& cpu)
{
cpu.state += cpu_flag::signal;
cpu.lock_notify();
@ -955,28 +967,40 @@ struct psp2_event_flag final
private:
lf_fifo<atomic_t<cmd_t>, 16> m_workload;
// Check condition
void op_wait(u32 thread_id)
{
idm::get<ARMv7Thread>(thread_id, [&](ARMv7Thread& cpu)
idm::check<ARMv7Thread>(thread_id, [=](ARMv7Thread& cpu)
{
const u32 pattern = ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state) -> u32
if (attr & SCE_KERNEL_ATTR_MULTI)
{
const u32 pat = state.pattern;
waiters++;
}
else if (!waiters.compare_and_swap_test(0, thread_id))
{
cpu.GPR[0] = SCE_KERNEL_ERROR_EVF_MULTI;
cpu.GPR[1] = pattern;
cpu.state += cpu_flag::signal;
cpu->lock_notify();
return;
}
const u32 old_pattern = pattern.atomic_op([&](u32& value) -> u32
{
const u32 pat = value;
if (pat_test(pat, cpu.GPR[1], cpu.GPR[0]))
{
state.pattern &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
state.waiters -= attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
value &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
return pat;
}
return 0;
});
if (pattern)
if (old_pattern)
{
waiters -= attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
cpu.GPR[0] = SCE_OK;
cpu.GPR[1] = pattern;
cpu.GPR[1] = old_pattern;
cpu.state += cpu_flag::signal;
cpu->lock_notify();
}
@ -988,17 +1012,16 @@ private:
});
}
// Check condition
void op_poll(u32 thread_id)
{
idm::get<ARMv7Thread>(thread_id, [&](ARMv7Thread& cpu)
idm::check<ARMv7Thread>(thread_id, [&](ARMv7Thread& cpu)
{
cpu.GPR[1] = ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state) -> u32
cpu.GPR[1] = pattern.atomic_op([&](u32& value) -> u32
{
const u32 pat = state.pattern;
const u32 pat = value;
if (pat_test(pat, cpu.GPR[1], cpu.GPR[0]))
{
state.pattern &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
value &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
return pat;
}
@ -1007,26 +1030,24 @@ private:
});
}
// Set pattern bits and wake up threads
void op_set(u32 pattern)
void op_set(u32 _pattern)
{
const auto new_state = ctrl.op_fetch([&](psp2_event_flag::ctrl_t& state)
{
state.pattern |= pattern;
});
pattern |= _pattern;
if (new_state.waiters)
if (const u32 _waiters = waiters)
{
const u32 new_pattern = pattern;
std::vector<std::reference_wrapper<ARMv7Thread>> threads;
// Check and lock appropriate threads
// Enumerate appropriate threads
if (attr & SCE_KERNEL_ATTR_MULTI)
{
threads.reserve(new_state.waiters);
threads.reserve(_waiters);
idm::select<ARMv7Thread>([&](u32 id, ARMv7Thread& cpu)
idm::select<ARMv7Thread>([&](u32, ARMv7Thread& cpu)
{
if (cpu->lock_if([&] { return cpu.owner == this && pat_test(new_state.pattern, cpu.GPR[1], cpu.GPR[0]); }))
if (cpu.owner == this && pat_test(new_pattern, cpu.GPR[1], cpu.GPR[0]))
{
threads.emplace_back(cpu);
}
@ -1047,9 +1068,9 @@ private:
}
else
{
idm::get<ARMv7Thread>(new_state.waiters, [&](ARMv7Thread& cpu)
idm::check<ARMv7Thread>(_waiters, [&](ARMv7Thread& cpu)
{
if (cpu->lock_if([&] { return cpu.owner == this && pat_test(new_state.pattern, cpu.GPR[1], cpu.GPR[0]); }))
if (cpu.owner == this && pat_test(new_pattern, cpu.GPR[1], cpu.GPR[0]))
{
threads.emplace_back(cpu);
}
@ -1059,14 +1080,13 @@ private:
// Wake up threads
for (ARMv7Thread& cpu : threads)
{
const u32 old_pattern = ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state) -> u32
const u32 old_pattern = pattern.atomic_op([&](u32& value) -> u32
{
const u32 pat = state.pattern;
const u32 pat = value;
if (pat_test(pat, cpu.GPR[1], cpu.GPR[0]))
{
state.pattern &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
state.waiters -= attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
value &= pat_clear(cpu.GPR[1], cpu.GPR[0]);
return pat;
}
@ -1079,56 +1099,43 @@ private:
cpu.GPR[1] = old_pattern;
cpu.state += cpu_flag::signal;
cpu.owner = nullptr;
cpu->unlock();
cpu->notify();
}
else
{
cpu->unlock();
waiters -= attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
cpu->lock_notify();
}
}
}
}
// Clear pattern bits (bitwise AND)
void op_clear(u32 pattern)
{
ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state)
{
state.pattern &= pattern;
});
}
// Wake up all threads
void op_stop(vm::ptr<u32> ptr, s32 error)
{
s32 result = 0;
const u32 pattern = ptr ? ptr->value() : ctrl.load().pattern;
const u32 _pattern = ptr ? ptr->value() : pattern.load();
std::vector<std::reference_wrapper<ARMv7Thread>> threads;
idm::select<ARMv7Thread>([&](u32, ARMv7Thread& cpu)
{
if (cpu->lock_if([&] { return cpu.owner == this; }))
if (cpu.owner == this)
{
cpu.GPR[0] = error;
cpu.GPR[1] = pattern;
cpu.state += cpu_flag::signal;
cpu.owner = nullptr;
cpu->unlock();
cpu->notify();
result++;
threads.emplace_back(cpu);
}
});
if (ptr)
{
*ptr = result;
*ptr = static_cast<u32>(threads.size());
}
ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state)
for (ARMv7Thread& cpu : threads)
{
state.pattern = pattern;
state.waiters = attr & SCE_KERNEL_ATTR_MULTI ? state.waiters - result : 0;
});
cpu.GPR[0] = error;
cpu.GPR[1] = _pattern;
cpu.state += cpu_flag::signal;
cpu.owner = nullptr;
cpu.lock_notify();
}
pattern = _pattern;
waiters = 0;
}
};
@ -1226,62 +1233,66 @@ error_code sceKernelWaitEventFlag(ARMv7Thread& cpu, s32 evfId, u32 bitPattern, u
return SCE_KERNEL_ERROR_INVALID_UID;
}
// First chance
const auto state = evf->ctrl.fetch_op([&](psp2_event_flag::ctrl_t& state)
{
if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
{
state.pattern &= psp2_event_flag::pat_clear(bitPattern, waitMode);
}
else if (evf->attr & SCE_KERNEL_ATTR_MULTI)
{
state.waiters++;
}
else if (!state.waiters)
{
state.waiters = cpu.id;
}
});
// First chance (TODO)
//const auto state = evf->ctrl.fetch_op([&](psp2_event_flag::ctrl_t& state)
//{
// if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
// {
// state.pattern &= psp2_event_flag::pat_clear(bitPattern, waitMode);
// }
// else if (evf->attr & SCE_KERNEL_ATTR_MULTI)
// {
// state.waiters++;
// }
// else if (!state.waiters)
// {
// state.waiters = cpu.id;
// }
//});
if (state.waiters && !(evf->attr & SCE_KERNEL_ATTR_MULTI))
{
return SCE_KERNEL_ERROR_EVF_MULTI;
}
//if (evf->waiters && !(evf->attr & SCE_KERNEL_ATTR_MULTI))
//{
// return SCE_KERNEL_ERROR_EVF_MULTI;
//}
if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
{
if (pResultPat) *pResultPat = state.pattern;
return SCE_OK;
}
//if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
//{
// if (pResultPat) *pResultPat = state.pattern;
// return SCE_OK;
//}
// Set register values for external use
cpu.GPR[0] = waitMode;
cpu.GPR[1] = bitPattern;
// Second chance
if (evf->exec(psp2_event_flag::task::wait, cpu.id) && cpu.state.test_and_reset(cpu_flag::signal))
if (!evf->exec(psp2_event_flag::task::wait, cpu.id) || !cpu.state.test_and_reset(cpu_flag::signal))
{
if (pResultPat) *pResultPat = cpu.GPR[1];
return SCE_OK;
thread_lock lock(cpu);
if (!thread_ctrl::wait_for(timeout, [&] { return cpu.state.test_and_reset(cpu_flag::signal); }))
{
if (!evf->exec(psp2_event_flag::task::timeout, cpu.id))
{
if (!evf->exec(psp2_event_flag::task::signal, cpu.id))
{
thread_ctrl::wait([&] { return cpu.state.test_and_reset(cpu_flag::signal); });
}
else
{
cpu.state -= cpu_flag::signal;
}
}
}
}
thread_lock entry(cpu);
if (!thread_ctrl::wait_for(timeout, [&] { return cpu.state.test_and_reset(cpu_flag::signal); }))
if (cpu.GPR[0] == SCE_KERNEL_ERROR_EVF_MULTI)
{
// Timeout cleanup
cpu.owner = nullptr;
cpu.GPR[0] = SCE_KERNEL_ERROR_WAIT_TIMEOUT;
cpu.GPR[1] = evf->ctrl.atomic_op([&](psp2_event_flag::ctrl_t& state)
{
state.waiters -= evf->attr & SCE_KERNEL_ATTR_MULTI ? 1 : cpu.id;
return state.pattern;
});
return SCE_KERNEL_ERROR_EVF_MULTI;
}
if (pResultPat) *pResultPat = cpu.GPR[1];
if (pTimeout) *pTimeout = static_cast<u32>(std::max<s64>(0, timeout - (get_system_time() - start_time)));
return not_an_error(cpu.GPR[0]);
}
@ -1303,23 +1314,17 @@ error_code sceKernelPollEventFlag(ARMv7Thread& cpu, s32 evfId, u32 bitPattern, u
return SCE_KERNEL_ERROR_INVALID_UID;
}
// First chance
const auto state = evf->ctrl.fetch_op([&](psp2_event_flag::ctrl_t& state)
{
if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
{
state.pattern &= psp2_event_flag::pat_clear(bitPattern, waitMode);
}
});
// First chance (TODO)
//const auto state = evf->ctrl.fetch_op([&](psp2_event_flag::ctrl_t& state)
//{
// if (!state.waiters && psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
// {
// state.pattern &= psp2_event_flag::pat_clear(bitPattern, waitMode);
// }
//});
if (psp2_event_flag::pat_test(state.pattern, bitPattern, waitMode))
if (psp2_event_flag::pat_test(evf->pattern, bitPattern, waitMode))
{
if (!state.waiters)
{
*pResultPat = state.pattern;
return SCE_OK;
}
cpu.GPR[0] = waitMode;
cpu.GPR[1] = bitPattern;
@ -1407,11 +1412,8 @@ error_code sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo>
pInfo->attr = evf->attr;
pInfo->initPattern = evf->init;
const auto state = evf->ctrl.load();
pInfo->currentPattern = state.pattern;
pInfo->numWaitThreads = evf->attr & SCE_KERNEL_ATTR_MULTI ? state.waiters : state.waiters != 0;
pInfo->currentPattern = evf->pattern;
pInfo->numWaitThreads = evf->attr & SCE_KERNEL_ATTR_MULTI ? evf->waiters.load() : evf->waiters != 0;
return SCE_OK;
}