62 lines
3.3 KiB
C++
62 lines
3.3 KiB
C++
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <initializer_list>
|
|
|
|
extern "C" {
|
|
int APS5_VABI sem_init_nid_postfix(void*, int, unsigned int);
|
|
int APS5_VABI sem_destroy_nid_postfix(void*);
|
|
int APS5_VABI sem_post_nid_postfix(void*);
|
|
int APS5_VABI sem_trywait_nid_postfix(void*);
|
|
int APS5_VABI sem_getvalue_nid_postfix(void*, int*);
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
|
|
static void Require(bool condition, const char* message) {
|
|
if (!condition) {
|
|
std::fprintf(stderr, "%s\n", message);
|
|
std::abort();
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
constexpr unsigned int maximum = 0x7fffffffu;
|
|
std::uintptr_t sem = 0;
|
|
int value = -1;
|
|
if (argc > 1 && std::strcmp(argv[1], "init") == 0) {
|
|
for (const unsigned int initial : {maximum + 1, 0xffffffffu}) {
|
|
sem = 0x1234;
|
|
*__error_nid_postfix() = 0;
|
|
const int result = sem_init_nid_postfix(&sem, 0, initial);
|
|
std::fprintf(stderr, "sem_init(%u): result=%d errno=%d\n", initial, result, *__error_nid_postfix());
|
|
Require(result == -1 && *__error_nid_postfix() == 22, "initial count above maximum must fail with EINVAL");
|
|
Require(sem == 0x1234, "failed initialization changed semaphore storage");
|
|
}
|
|
return 0;
|
|
}
|
|
Require(sem_init_nid_postfix(&sem, 0, maximum) == 0, "maximum count must initialize");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == static_cast<int>(maximum), "maximum count must be readable");
|
|
*__error_nid_postfix() = 0;
|
|
const int result = sem_post_nid_postfix(&sem);
|
|
std::fprintf(stderr, "sem_post(maximum): result=%d errno=%d\n", result, *__error_nid_postfix());
|
|
Require(result == -1 && *__error_nid_postfix() == 84, "post at maximum must fail with guest EOVERFLOW");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == static_cast<int>(maximum), "overflow changed count");
|
|
Require(sem_trywait_nid_postfix(&sem) == 0, "wait at maximum must succeed");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == static_cast<int>(maximum - 1), "wait must decrement");
|
|
Require(sem_post_nid_postfix(&sem) == 0, "post below maximum must succeed");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == static_cast<int>(maximum), "post must reach maximum");
|
|
Require(sem_post_nid_postfix(&sem) == -1 && *__error_nid_postfix() == 84, "repeated overflow must fail");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == static_cast<int>(maximum), "repeated overflow changed count");
|
|
Require(sem_destroy_nid_postfix(&sem) == 0, "destroy must succeed");
|
|
Require(sem_init_nid_postfix(&sem, 0, 0) == 0, "zero count must initialize");
|
|
Require(sem_trywait_nid_postfix(&sem) == -1 && *__error_nid_postfix() == 35, "empty semaphore must report EAGAIN");
|
|
Require(sem_post_nid_postfix(&sem) == 0, "normal post must succeed");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == 1, "normal post must increment");
|
|
Require(sem_trywait_nid_postfix(&sem) == 0, "normal wait must succeed");
|
|
Require(sem_getvalue_nid_postfix(&sem, &value) == 0 && value == 0, "normal wait must decrement");
|
|
Require(sem_destroy_nid_postfix(&sem) == 0, "normal destroy must succeed");
|
|
}
|