Merge pull request #4918 from Feuris/feat/libc-mtx-init-with-name
feat(libc): implement _Mtx_init_with_name
This commit is contained in:
commit
cee54cdade
|
|
@ -627,6 +627,18 @@ if(BUILD_TESTING)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
add_test_executable(guest_libc_mutex_init_with_name_tests EXCLUDE_FROM_ALL ${LIBS_INCLUDE_DIR}/tests/GuestLibcMutexInitWithName.cpp)
|
||||
target_include_directories(guest_libc_mutex_init_with_name_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_libc_mutex_init_with_name_tests PRIVATE libc)
|
||||
configure_windows_unwind(guest_libc_mutex_init_with_name_tests)
|
||||
if(BUILD_TESTING)
|
||||
set_target_properties(guest_libc_mutex_init_with_name_tests PROPERTIES EXCLUDE_FROM_ALL FALSE)
|
||||
add_test(NAME guest_libc_mutex_init_with_name COMMAND guest_libc_mutex_init_with_name_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_libc_mutex_init_with_name PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
if(BUILD_TESTING)
|
||||
enable_language(ASM)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type) {
|
|||
return threadSuccess;
|
||||
}
|
||||
|
||||
int APS5_VABI _Mtx_init_with_name_nid_postfix(void** handle, int type, const char*) {
|
||||
return _Mtx_init_nid_postfix(handle, type);
|
||||
}
|
||||
|
||||
void APS5_VABI _Mtx_destroy_nid_postfix(void** handle) {
|
||||
if (!handle)
|
||||
throw std::invalid_argument("_Mtx_destroy: null mutex handle pointer");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI _Mtx_init_with_name_nid_postfix(void** handle, int type, const char* name);
|
||||
void APS5_VABI _Mtx_destroy_nid_postfix(void** handle);
|
||||
int APS5_VABI _Mtx_lock_nid_postfix(void** handle);
|
||||
int APS5_VABI _Mtx_unlock_nid_postfix(void** handle);
|
||||
}
|
||||
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
|
||||
template<typename TException, typename TCall>
|
||||
static void RequireThrows(TCall call) {
|
||||
try {
|
||||
call();
|
||||
} catch (const TException&) {
|
||||
return;
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
|
||||
constexpr int success = 0;
|
||||
constexpr int busy = 3;
|
||||
constexpr int plain = 0x01;
|
||||
|
||||
int main() {
|
||||
void* mutex = nullptr;
|
||||
Require(_Mtx_init_with_name_nid_postfix(&mutex, plain, "GameMutex") == success);
|
||||
Require(mutex != nullptr);
|
||||
Require(_Mtx_lock_nid_postfix(&mutex) == success);
|
||||
Require(_Mtx_lock_nid_postfix(&mutex) == busy);
|
||||
Require(_Mtx_unlock_nid_postfix(&mutex) == success);
|
||||
_Mtx_destroy_nid_postfix(&mutex);
|
||||
Require(mutex == nullptr);
|
||||
|
||||
RequireThrows<std::invalid_argument>([] {
|
||||
_Mtx_init_with_name_nid_postfix(nullptr, plain, "NullHandle");
|
||||
});
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
- [_Mtx_trylock](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `k6pGNMwJB08`) - returns busy for a non-recursive mutex already owned by the caller, assumed to match `_Mtx_lock`'s ownership handling; exact console behavior is unverified.
|
||||
- [nearbyintf](../../../core/libs/prx/libc/src/Math.cpp) (libc, NID `c+4r-T-tEIc`) uses the host rounding mode, not the console's; console rounding mode state remains unverified.
|
||||
- [_Thrd_sleep](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `jfRI3snge3o`) follows the Dinkumware threads library shipped with [Visual C++ 2013](https://github.com/adityaramesh/concurrency_runtime/tree/master/VS2013_SP2/crt/src/thr) (`xtime.c`) and C11 Annex K, without console verification. It reads a 16-byte xtime (64-bit seconds and nanoseconds) on the guest `CLOCK_REALTIME`, normalizes the nanoseconds and sleeps through `nanosleep`, retrying on `EINTR`, so it is a cancellation point; a null xtime or one whose normalization overflows throws. The console's `_Thrd_sleep` (disassembled from a title's `libc.prx`) also takes an optional `xtime*` of remaining time and returns `int`; here the sleep is never cut short, so it returns 0 and leaves the remaining time untouched.
|
||||
- [_Mtx_init_with_name](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `tgioGpKtmbE`) forwards to `_Mtx_init` and ignores the mutex name parameter.
|
||||
- [Guest arena](../../../core/libs/prx/libc/src/GuestArena.cpp) (libc) - the application map area is assumed to end at 0xFC_0000_0000, as `SCE_KERNEL_APP_MAP_AREA_END_ADDR` does on the PS4. On Windows, host allocations made in the arena before libc loads stay, and a fixed guest mapping over one throws
|
||||
- [sceLibcInternalBacktraceForGame](../../../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - `(const char* heapName)` and its return follow the `libc.prx` ASTRO BOT (PPSA21564 01.007.000) bundles: its four calls (0x6801, 0x7F46, 0xE75E, 0xEE02) are in the `malloc_stats` and `sceLibcMspaceMallocStats` paths, each after a `[%s] ...` line printed with the same heap name buffer, and the caller ignores the result and continues. The console's backtrace output is not reproduced: the heap name and the guest return address are written to the host standard error
|
||||
- [sceLibcInternalHeapErrorReportForGame](../../../core/libs/prx/libc/src/HeapDiagnostics.cpp) (libSceLibcInternal, implemented in libc) - `(void* heap, void* block, uint32 error)` follows the same `libc.prx` (call at 0xF634): it passes the heap, the block and the nonzero result of its block check, and then calls a function that never returns, so the report only has to return. The meaning of the error values is unknown; the three values and the guest return address are written to the host standard error
|
||||
|
|
|
|||
Loading…
Reference in New Issue