Vita3K/vita3k/modules/SceKernelThreadMgr/SceThreadmgr.cpp

1367 lines
43 KiB
C++

// Vita3K emulator project
// Copyright (C) 2021 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#include "SceThreadmgr.h"
#include <modules/module_parent.h>
#include <host/functions.h>
#include <kernel/callback.h>
#include <kernel/sync_primitives.h>
#include <util/lock_and_find.h>
#include <SDL_timer.h>
#include <chrono>
#include <thread>
inline uint64_t get_current_time() {
return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count();
}
EXPORT(int, __sceKernelCreateLwMutex, Ptr<SceKernelLwMutexWork> workarea, const char *name, unsigned int attr, Ptr<SceKernelCreateLwMutex_opt> opt) {
assert(name != nullptr);
assert(opt.get(host.mem)->init_count >= 0);
auto uid_out = &workarea.get(host.mem)->uid;
return mutex_create(uid_out, host.kernel, host.mem, export_name, name, thread_id, attr, opt.get(host.mem)->init_count, workarea, SyncWeight::Light);
}
EXPORT(int, _sceKernelCancelEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelEventFlag) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelEventWithSetPattern) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelMsgPipe) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelMutex) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelRWLock) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelSema) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCancelTimer) {
return UNIMPLEMENTED();
}
EXPORT(SceUID, _sceKernelCreateCond, const char *pName, SceUInt32 attr, SceUID mutexId, const SceKernelCondOptParam *pOptParam) {
SceUID uid;
if (auto error = condvar_create(&uid, host.kernel, export_name, pName, thread_id, attr, mutexId, SyncWeight::Heavy)) {
return error;
}
return uid;
}
EXPORT(SceUID, _sceKernelCreateEventFlag, const char *pName, SceUInt32 attr, SceUInt32 initPattern, const SceKernelEventFlagOptParam *pOptParam) {
return eventflag_create(host.kernel, export_name, thread_id, pName, attr, initPattern);
}
EXPORT(int, _sceKernelCreateLwCond, Ptr<SceKernelLwCondWork> workarea, const char *name, SceUInt attr, Ptr<SceKernelCreateLwCond_opt> opt) {
const auto uid_out = &workarea.get(host.mem)->uid;
const auto assoc_mutex_uid = opt.get(host.mem)->workarea_mutex.get(host.mem)->uid;
return condvar_create(uid_out, host.kernel, export_name, name, thread_id, attr, assoc_mutex_uid, SyncWeight::Light);
}
EXPORT(int, _sceKernelCreateMsgPipeWithLR) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelCreateMutex, const char *name, SceUInt attr, int init_count, SceKernelMutexOptParam *opt_param) {
SceUID uid;
if (auto error = mutex_create(&uid, host.kernel, host.mem, export_name, name, thread_id, attr, init_count, Ptr<SceKernelLwMutexWork>(0), SyncWeight::Heavy)) {
return error;
}
return uid;
}
EXPORT(SceUID, _sceKernelCreateRWLock, const char *name, SceUInt32 attr, SceKernelMutexOptParam *opt_param) {
return rwlock_create(host.kernel, host.mem, export_name, name, thread_id, attr);
}
EXPORT(int, _sceKernelCreateSema, const char *name, SceUInt attr, int initVal, Ptr<SceKernelCreateSema_opt> opt) {
return semaphore_create(host.kernel, export_name, name, thread_id, attr, initVal, opt.get(host.mem)->maxVal);
}
EXPORT(int, _sceKernelCreateSema_16XX, const char *name, SceUInt attr, int initVal, Ptr<SceKernelCreateSema_opt> opt) {
return semaphore_create(host.kernel, export_name, name, thread_id, attr, initVal, opt.get(host.mem)->maxVal);
}
EXPORT(SceUID, _sceKernelCreateSimpleEvent, const char *pName, SceUInt32 attr, SceUInt32 initPattern, const SceKernelSimpleEventOptParam *pOptParam) {
return eventflag_create(host.kernel, export_name, thread_id, pName, attr, initPattern);
}
EXPORT(int, _sceKernelCreateTimer) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelDeleteLwCond, Ptr<SceKernelLwCondWork> workarea) {
SceUID lightweight_condition_id = workarea.get(host.mem)->uid;
return condvar_delete(host.kernel, export_name, thread_id, lightweight_condition_id, SyncWeight::Light);
}
EXPORT(int, _sceKernelDeleteLwMutex, Ptr<SceKernelLwMutexWork> workarea) {
if (!workarea)
return SCE_KERNEL_ERROR_ILLEGAL_ADDR;
const auto lightweight_mutex_id = workarea.get(host.mem)->uid;
return mutex_delete(host.kernel, export_name, thread_id, lightweight_mutex_id, SyncWeight::Light);
}
EXPORT(int, _sceKernelExitCallback) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelGetCallbackInfo, SceUID callbackId, SceKernelCallbackInfo *pInfo) {
const CallbackPtr cb = lock_and_find(callbackId, host.kernel.callbacks, host.kernel.mutex);
if (!cb)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_CALLBACK_ID);
if (!pInfo)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR); // TODO check result
if (pInfo->size != sizeof(*pInfo))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
pInfo->callbackId = callbackId;
strncpy(pInfo->name, cb->get_name().c_str(), KERNELOBJECT_MAX_NAME_LENGTH);
pInfo->name[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
pInfo->attr = 0;
pInfo->threadId = cb->get_owner_thread_id();
pInfo->callbackFunc = cb->get_callback_function();
pInfo->notifyId = cb->get_notifier_id();
pInfo->notifyArg = cb->get_notify_arg();
pInfo->pCommon = cb->get_user_common_ptr();
return SCE_KERNEL_OK;
}
EXPORT(SceInt32, _sceKernelGetCondInfo, SceUID condId, Ptr<SceKernelCondInfo> pInfo) {
const CondvarPtr condvar = lock_and_find(condId, host.kernel.condvars, host.kernel.mutex);
if (!condvar)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_EVF_ID);
SceKernelCondInfo *info = pInfo.get(host.mem);
if (!info)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR);
if (info->size != sizeof(*info))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
info->condId = condId;
std::copy(condvar->name, condvar->name + KERNELOBJECT_MAX_NAME_LENGTH, info->name);
info->attr = condvar->attr;
info->mutexId = condvar->associated_mutex->uid;
info->numWaitThreads = condvar->waiting_threads->size();
return SCE_KERNEL_OK;
}
EXPORT(SceInt32, _sceKernelGetEventFlagInfo, SceUID evfId, Ptr<SceKernelEventFlagInfo> pInfo) {
const EventFlagPtr eventflag = lock_and_find(evfId, host.kernel.eventflags, host.kernel.mutex);
if (!eventflag)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_EVF_ID);
SceKernelEventFlagInfo *info = pInfo.get(host.mem);
if (!info)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR);
if (info->size != sizeof(*info))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
info->evfId = evfId;
std::copy(eventflag->name, eventflag->name + KERNELOBJECT_MAX_NAME_LENGTH, info->name);
info->attr = eventflag->attr;
info->initPattern = eventflag->flags; // Todo, give only current pattern
info->currentPattern = eventflag->flags;
info->numWaitThreads = eventflag->waiting_threads->size();
return SCE_KERNEL_OK;
}
EXPORT(int, _sceKernelGetEventInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetEventPattern) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetLwCondInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetLwCondInfoById) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetLwMutexInfoById, SceUID lightweight_mutex_id, Ptr<SceKernelLwMutexInfo> info, SceSize size) {
SceKernelLwMutexInfo *info_data = info.get(host.mem);
SceSize info_size = info_data->size;
SceKernelLwMutexInfo info_data_local;
if (info_size < sizeof(SceKernelLwMutexInfo)) {
info_data = &info_data_local;
info_data_local.size = info_size;
}
MutexPtr mutex = mutex_get(host.kernel, export_name, thread_id, lightweight_mutex_id, SyncWeight::Light);
if (mutex) {
info_data->uid = lightweight_mutex_id;
std::copy(mutex->name, mutex->name + KERNELOBJECT_MAX_NAME_LENGTH, info_data->name);
info_data->attr = mutex->attr;
info_data->pWork = mutex->workarea;
info_data->initCount = mutex->init_count;
info_data->currentCount = mutex->lock_count;
if (mutex->owner == 0) {
info_data->currentOwnerId = 0;
} else {
auto workarea_mutex_owner = mutex->workarea.get(host.mem)->owner;
auto threads = host.kernel.threads;
if (threads[workarea_mutex_owner] == mutex->owner) { // something like optimisation
info_data->currentOwnerId = workarea_mutex_owner;
} else {
info_data->currentOwnerId = -1;
for (auto it = threads.begin(); it != threads.end(); ++it) {
if (it->second == mutex->owner) {
info_data->currentOwnerId = it->first;
break;
}
}
}
}
info_data->numWaitThreads = static_cast<SceUInt32>(mutex->waiting_threads->size());
if (info_size < sizeof(SceKernelLwMutexInfo)) {
memcpy(info.get(host.mem), &info_data_local, info_size);
} else {
info_data->size = sizeof(SceKernelLwMutexInfo);
}
return SCE_KERNEL_OK;
} else {
return SCE_KERNEL_ERROR_UNKNOWN_LW_MUTEX_ID;
}
}
EXPORT(int, _sceKernelGetMsgPipeInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetMutexInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetRWLockInfo) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelGetSemaInfo, SceUID semaId, Ptr<SceKernelSemaInfo> pInfo) {
const SemaphorePtr semaphore = lock_and_find(semaId, host.kernel.semaphores, host.kernel.mutex);
if (!semaphore)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_SEMA_ID);
SceKernelSemaInfo *info = pInfo.get(host.mem);
if (!info)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR);
if (info->size != sizeof(*info))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
info->attr = semaphore->attr;
info->currentCount = host.kernel.semaphores.size();
info->initCount = semaphore->val;
info->maxCount = semaphore->max;
std::copy(semaphore->name, semaphore->name + KERNELOBJECT_MAX_NAME_LENGTH, info->name);
info->semaId = semaId;
info->numWaitThreads = semaphore->waiting_threads->size();
return SCE_KERNEL_OK;
}
EXPORT(int, _sceKernelGetSystemInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetSystemTime) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetThreadContextForVM, SceUID threadId, Ptr<SceKernelThreadCpuRegisterInfo> pCpuRegisterInfo, Ptr<SceKernelThreadVfpRegisterInfo> pVfpRegisterInfo) {
STUBBED("Stub");
const ThreadStatePtr thread = lock_and_find(threadId, host.kernel.threads, host.kernel.mutex);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
const auto context = save_context(*thread->cpu);
SceKernelThreadCpuRegisterInfo *infoCpu = pCpuRegisterInfo.get(host.mem);
if (infoCpu) {
if (infoCpu->size != sizeof(*infoCpu))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
infoCpu->cpsr = context.cpsr;
memcpy(infoCpu->reg, context.cpu_registers.data(), 16 * 4);
infoCpu->sb = 100000; // Todo
infoCpu->st = 100000; // Todo
infoCpu->teehbr = 100000; // Todo
infoCpu->tpidrurw = read_tpidruro(*thread->cpu);
}
SceKernelThreadVfpRegisterInfo *infoVfp = pVfpRegisterInfo.get(host.mem);
if (infoVfp) {
if (infoVfp->size != sizeof(*infoVfp))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
infoVfp->fpscr = context.fpscr;
memcpy(infoVfp->reg, context.fpu_registers.data(), 64 * 4);
}
return SCE_KERNEL_OK;
}
EXPORT(SceInt32, _sceKernelGetThreadCpuAffinityMask, SceUID thid) {
const ThreadStatePtr thread = host.kernel.get_thread(thid ? thid : thread_id);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
return thread->affinity_mask;
}
EXPORT(int, _sceKernelGetThreadEventInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetThreadExitStatus) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelGetThreadInfo, SceUID threadId, Ptr<SceKernelThreadInfo> pInfo) {
STUBBED("STUB");
const ThreadStatePtr thread = lock_and_find(threadId ? threadId : thread_id, host.kernel.threads, host.kernel.mutex);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
SceKernelThreadInfo *info = pInfo.get(host.mem);
if (!info)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ADDR);
if (info->size != sizeof(*info))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
// TODO: SCE_KERNEL_ERROR_ILLEGAL_CONTEXT check
std::copy(thread->name.c_str(), thread->name.c_str() + KERNELOBJECT_MAX_NAME_LENGTH, info->name);
info->stack = Ptr<void>(thread->stack.get());
info->stackSize = thread->stack_size;
info->initPriority = thread->priority; // Todo Give only current priority
info->currentPriority = thread->priority;
info->initCpuAffinityMask = thread->affinity_mask; // Todo Give init affinity
info->currentCpuAffinityMask = thread->affinity_mask;
info->entry = SceKernelThreadEntry(thread->entry_point);
return SCE_KERNEL_OK;
}
EXPORT(int, _sceKernelGetThreadRunStatus) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetTimerBase) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetTimerEventRemainingTime) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetTimerInfo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelGetTimerTime) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelLockLwMutex, Ptr<SceKernelLwMutexWork> workarea, int lock_count, unsigned int *ptimeout) {
if (!workarea)
return RET_ERROR(SCE_GXM_ERROR_INVALID_POINTER);
const auto lwmutexid = workarea.get(host.mem)->uid;
return mutex_lock(host.kernel, host.mem, export_name, thread_id, lwmutexid, lock_count, ptimeout, SyncWeight::Light);
}
EXPORT(int, _sceKernelLockMutex, SceUID mutexid, int lock_count, unsigned int *timeout) {
return mutex_lock(host.kernel, host.mem, export_name, thread_id, mutexid, lock_count, timeout, SyncWeight::Heavy);
}
EXPORT(int, _sceKernelLockMutexCB) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelLockReadRWLock, SceUID lock_id, SceUInt32 *timeout) {
return rwlock_lock(host.kernel, host.mem, export_name, thread_id, lock_id, timeout, false);
}
EXPORT(SceInt32, _sceKernelLockReadRWLockCB, SceUID lock_id, SceUInt32 *timeout) {
STUBBED("No CB");
return rwlock_lock(host.kernel, host.mem, export_name, thread_id, lock_id, timeout, false);
}
EXPORT(SceInt32, _sceKernelLockWriteRWLock, SceUID lock_id, SceUInt32 *timeout) {
return rwlock_lock(host.kernel, host.mem, export_name, thread_id, lock_id, timeout, true);
}
EXPORT(SceInt32, _sceKernelLockWriteRWLockCB, SceUID lock_id, SceUInt32 *timeout) {
STUBBED("No CB");
return rwlock_lock(host.kernel, host.mem, export_name, thread_id, lock_id, timeout, true);
}
EXPORT(int, _sceKernelPMonThreadGetCounter) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelPollEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelPollEventFlag, SceUID event_id, unsigned int flags, unsigned int wait, unsigned int *outBits) {
return eventflag_poll(host.kernel, export_name, thread_id, event_id, flags, wait, outBits);
}
EXPORT(int, _sceKernelPulseEventWithNotifyCallback) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelReceiveMsgPipeVector) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelReceiveMsgPipeVectorCB) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelRegisterThreadEventHandler) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSendMsgPipeVector) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSendMsgPipeVectorCB) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSetEventWithNotifyCallback) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSetThreadContextForVM, SceUID threadId, Ptr<SceKernelThreadCpuRegisterInfo> pCpuRegisterInfo, Ptr<SceKernelThreadVfpRegisterInfo> pVfpRegisterInfo) {
const ThreadStatePtr thread = lock_and_find(threadId, host.kernel.threads, host.kernel.mutex);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
SceKernelThreadCpuRegisterInfo *infoCpu = pCpuRegisterInfo.get(host.mem);
if (infoCpu) {
if (infoCpu->size != sizeof(*infoCpu))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
// Todo
}
SceKernelThreadVfpRegisterInfo *infoVfp = pVfpRegisterInfo.get(host.mem);
if (infoVfp) {
if (infoVfp->size != sizeof(*infoVfp))
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE);
// Todo
}
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSetTimerEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSetTimerTime) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelSignalLwCond, Ptr<SceKernelLwCondWork> workarea) {
SceUID condid = workarea.get(host.mem)->uid;
return condvar_signal(host.kernel, export_name, thread_id, condid,
Condvar::SignalTarget(Condvar::SignalTarget::Type::Any), SyncWeight::Light);
}
EXPORT(int, _sceKernelSignalLwCondAll, Ptr<SceKernelLwCondWork> workarea) {
SceUID condid = workarea.get(host.mem)->uid;
return condvar_signal(host.kernel, export_name, thread_id, condid,
Condvar::SignalTarget(Condvar::SignalTarget::Type::All), SyncWeight::Light);
}
EXPORT(int, _sceKernelSignalLwCondTo) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelStartThread, SceUID thid, SceSize arglen, Ptr<void> argp) {
auto thread = lock_and_find(thid, host.kernel.threads, host.kernel.mutex);
Ptr<void> new_argp(0);
if (!thread) {
return SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID;
}
if (thread->status == ThreadStatus::run) {
return SCE_KERNEL_ERROR_RUNNING;
}
const int res = thread->start(host.kernel, arglen, argp);
if (res < 0) {
return RET_ERROR(res);
}
return res;
}
EXPORT(int, _sceKernelTryReceiveMsgPipeVector) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelTrySendMsgPipeVector) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelUnlockLwMutex) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitCond) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitCondCB) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitEventCB) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelWaitEventFlag, SceUID evfId, SceUInt32 bitPattern, SceUInt32 waitMode, SceUInt32 *pResultPat, SceUInt32 *pTimeout) {
return eventflag_wait(host.kernel, export_name, thread_id, evfId, bitPattern, waitMode, pResultPat, pTimeout);
}
EXPORT(SceInt32, _sceKernelWaitEventFlagCB, SceUID evfId, SceUInt32 bitPattern, SceUInt32 waitMode, SceUInt32 *pResultPat, SceUInt32 *pTimeout) {
STUBBED("no CB");
return eventflag_wait(host.kernel, export_name, thread_id, evfId, bitPattern, waitMode, pResultPat, pTimeout);
}
EXPORT(int, _sceKernelWaitException) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitExceptionCB) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitLwCond, Ptr<SceKernelLwCondWork> workarea, SceUInt32 *timeout) {
const auto cond_id = workarea.get(host.mem)->uid;
return condvar_wait(host.kernel, host.mem, export_name, thread_id, cond_id, timeout, SyncWeight::Light);
}
EXPORT(int, _sceKernelWaitLwCondCB, Ptr<SceKernelLwCondWork> workarea, SceUInt32 *timeout) {
const auto cond_id = workarea.get(host.mem)->uid;
return condvar_wait(host.kernel, host.mem, export_name, thread_id, cond_id, timeout, SyncWeight::Light);
}
EXPORT(int, _sceKernelWaitMultipleEvents) {
return UNIMPLEMENTED();
}
EXPORT(int, _sceKernelWaitMultipleEventsCB) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, _sceKernelWaitSema, SceUID semaId, SceInt32 needCount, SceUInt32 *pTimeout) {
return semaphore_wait(host.kernel, export_name, thread_id, semaId, needCount, pTimeout);
}
EXPORT(SceInt32, _sceKernelWaitSemaCB, SceUID semaId, SceInt32 needCount, SceUInt32 *pTimeout) {
process_callbacks(host.kernel, thread_id);
return semaphore_wait(host.kernel, export_name, thread_id, semaId, needCount, pTimeout);
}
EXPORT(int, _sceKernelWaitSignal, uint32_t unknown, uint32_t delay, uint32_t timeout) {
STUBBED("sceKernelWaitSignal");
const auto thread = lock_and_find(thread_id, host.kernel.threads, host.kernel.mutex);
thread->update_status(ThreadStatus::wait);
thread->signal.wait();
thread->update_status(ThreadStatus::run);
return SCE_KERNEL_OK;
}
EXPORT(int, _sceKernelWaitSignalCB) {
return UNIMPLEMENTED();
}
int wait_thread_end(ThreadStatePtr &waiter, ThreadStatePtr &target, int *stat) {
std::unique_lock<std::mutex> waiter_lock(waiter->mutex);
{
const std::unique_lock<std::mutex> thread_lock(target->mutex);
if (target->status == ThreadStatus::dormant) {
if (stat != nullptr) {
*stat = target->returned_value;
}
return 0;
}
waiter->update_status(ThreadStatus::wait);
target->waiting_threads.push_back(waiter);
}
waiter->status_cond.wait(waiter_lock, [&]() { return waiter->status == ThreadStatus::run; });
return 0;
}
EXPORT(int, _sceKernelWaitThreadEnd, SceUID thid, int *stat, SceUInt *timeout) {
auto waiter = lock_and_find(thread_id, host.kernel.threads, host.kernel.mutex);
auto target = lock_and_find(thid, host.kernel.threads, host.kernel.mutex);
if (!target) {
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
}
return wait_thread_end(waiter, target, stat);
}
EXPORT(int, _sceKernelWaitThreadEndCB, SceUID thid, int *stat, SceUInt *timeout) {
auto waiter = lock_and_find(thread_id, host.kernel.threads, host.kernel.mutex);
auto target = lock_and_find(thid, host.kernel.threads, host.kernel.mutex);
if (!target) {
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
}
STUBBED("No CB");
return wait_thread_end(waiter, target, stat);
}
EXPORT(SceInt32, sceKernelCancelCallback, SceUID callbackId) {
const CallbackPtr cb = lock_and_find(callbackId, host.kernel.callbacks, host.kernel.mutex);
if (!cb)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_CALLBACK_ID);
cb->cancel();
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelChangeActiveCpuMask) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, sceKernelChangeThreadCpuAffinityMask, SceUID thid, SceInt32 affinity_mask) {
const ThreadStatePtr thread = host.kernel.get_thread(thid ? thid : thread_id);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
const SceInt32 old_affinity = thread->affinity_mask;
if (affinity_mask & ~SCE_KERNEL_CPU_MASK_USER_ALL)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_CPU_AFFINITY_MASK);
thread->affinity_mask = affinity_mask;
return old_affinity;
}
EXPORT(SceInt32, sceKernelChangeThreadPriority2, SceUID thid, SceInt32 priority) {
const ThreadStatePtr thread = host.kernel.get_thread(thid ? thid : thread_id);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
const SceInt32 old_priority = thread->priority;
if (priority == SCE_KERNEL_CURRENT_THREAD_PRIORITY) {
priority = host.kernel.get_thread(thread_id)->priority;
}
if (priority >= SCE_KERNEL_HIGHEST_DEFAULT_PRIORITY
&& priority <= SCE_KERNEL_LOWEST_DEFAULT_PRIORITY) {
priority = SCE_KERNEL_GAME_DEFAULT_PRIORITY_ACTUAL + (priority - SCE_KERNEL_DEFAULT_PRIORITY);
}
if (priority < SCE_KERNEL_HIGHEST_PRIORITY_USER || priority > SCE_KERNEL_LOWEST_PRIORITY_USER)
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_PRIORITY);
thread->priority = priority;
return old_priority;
}
EXPORT(SceInt32, sceKernelChangeThreadPriority, SceUID thid, SceInt32 priority) {
auto err = CALL_EXPORT(sceKernelChangeThreadPriority2, thid, priority);
if (err < 0)
return err;
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelChangeThreadVfpException) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, sceKernelCheckCallback) {
return process_callbacks(host.kernel, thread_id);
}
EXPORT(int, sceKernelCheckWaitableStatus) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, sceKernelClearEvent, SceUID eventId, SceUInt32 clearPattern) {
return eventflag_clear(host.kernel, export_name, eventId, clearPattern);
}
EXPORT(SceInt32, sceKernelClearEventFlag, SceUID evfId, SceUInt32 bitPattern) {
return eventflag_clear(host.kernel, export_name, evfId, bitPattern);
}
EXPORT(int, sceKernelCloseCond) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseEventFlag) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseMsgPipe) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseMutex) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseMutex_089) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseRWLock) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseSema) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseSimpleEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelCloseTimer) {
return STUBBED("References not implemented.");
}
EXPORT(SceUID, sceKernelCreateCallback, char *name, SceUInt32 attr, Ptr<SceKernelCallbackFunction> callbackFunc, Ptr<void> pCommon) {
if (attr || !callbackFunc.address())
return RET_ERROR(SCE_KERNEL_ERROR_ILLEGAL_ATTR);
ThreadStatePtr thread = host.kernel.get_thread(thread_id);
std::string cb_name = name;
auto cb = std::make_shared<Callback>(thread_id, thread, cb_name, callbackFunc, pCommon);
std::lock_guard lock(host.kernel.mutex);
SceUID cb_uid = host.kernel.get_next_uid();
host.kernel.callbacks.emplace(cb_uid, cb);
thread->callbacks.push_back(cb);
return cb_uid;
}
EXPORT(int, sceKernelCreateThreadForUser, const char *name, SceKernelThreadEntry entry, int init_priority, SceKernelCreateThread_opt *options) {
if (options->cpu_affinity_mask & ~SCE_KERNEL_CPU_MASK_USER_ALL) {
return RET_ERROR(SCE_KERNEL_ERROR_INVALID_CPU_AFFINITY);
}
const ThreadStatePtr thread = host.kernel.create_thread(host.mem, name, entry.cast<void>(), init_priority, options->cpu_affinity_mask, options->stack_size, options->option.get(host.mem));
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_ERROR);
return thread->id;
}
int delay_thread(SceUInt delay_us) {
if (delay_us == 0)
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
std::this_thread::sleep_for(std::chrono::microseconds(delay_us));
return SCE_KERNEL_OK;
}
int delay_thread_cb(HostState &host, SceUID thread_id, SceUInt delay_us) {
auto start = std::chrono::high_resolution_clock::now(); // Meseaure the time taken to process callbacks
process_callbacks(host.kernel, thread_id);
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
if (delay_us > elapsed.count()) // If we spent less time than requested processing callbacks, sleep the remaining time
return delay_thread(delay_us - elapsed.count());
else // Else return directly
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelDelayThread, SceUInt delay) {
return delay_thread(delay);
}
EXPORT(int, sceKernelDelayThread200, SceUInt delay) {
if (delay < 201)
delay = 201;
return delay_thread(delay);
}
EXPORT(int, sceKernelDelayThreadCB, SceUInt delay) {
return delay_thread_cb(host, thread_id, delay);
}
EXPORT(int, sceKernelDelayThreadCB200, SceUInt delay) {
if (delay < 201)
delay = 201;
return delay_thread_cb(host, thread_id, delay);
}
EXPORT(int, sceKernelDeleteCallback) {
// TODO
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelDeleteCond, SceUID condition_variable_id) {
return condvar_delete(host.kernel, export_name, thread_id, condition_variable_id, SyncWeight::Heavy);
}
EXPORT(int, sceKernelDeleteEventFlag, SceUID event_id) {
return eventflag_delete(host.kernel, export_name, thread_id, event_id);
}
EXPORT(int, sceKernelDeleteMsgPipe) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelDeleteMutex, SceUID mutexid) {
return mutex_delete(host.kernel, export_name, thread_id, mutexid, SyncWeight::Heavy);
}
EXPORT(SceInt32, sceKernelDeleteRWLock, SceUID lock_id) {
return rwlock_delete(host.kernel, host.mem, export_name, thread_id, lock_id);
}
EXPORT(int, sceKernelDeleteSema, SceUID semaid) {
return semaphore_delete(host.kernel, export_name, thread_id, semaid);
}
EXPORT(int, sceKernelDeleteSimpleEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelDeleteThread, SceUID thid) {
const ThreadStatePtr thread = lock_and_find(thid, host.kernel.threads, host.kernel.mutex);
if (!thread || thread->status != ThreadStatus::dormant) {
return SCE_KERNEL_ERROR_NOT_DORMANT;
}
host.kernel.exit_delete_thread(thread);
return 0;
}
EXPORT(int, sceKernelDeleteTimer, SceUID timer_handle) {
host.kernel.timers.erase(timer_handle);
return 0;
}
EXPORT(int, sceKernelExitDeleteThread, int status) {
const ThreadStatePtr thread = lock_and_find(thread_id, host.kernel.threads, host.kernel.mutex);
host.kernel.exit_delete_thread(thread);
return status;
}
EXPORT(SceInt32, sceKernelGetCallbackCount, SceUID callbackId) {
const CallbackPtr cb = lock_and_find(callbackId, host.kernel.callbacks, host.kernel.mutex);
if (!cb)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_CALLBACK_ID);
return cb->get_num_notifications();
}
EXPORT(int, sceKernelGetMsgPipeCreatorId) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelGetProcessId) {
STUBBED("pid: 0");
return 0;
}
EXPORT(uint64_t, sceKernelGetSystemTimeWide) {
return get_current_time();
}
EXPORT(SceInt32, sceKernelGetThreadCpuAffinityMask, SceUID thid) {
return CALL_EXPORT(_sceKernelGetThreadCpuAffinityMask, thid);
}
EXPORT(int, sceKernelGetThreadStackFreeSize) {
return UNIMPLEMENTED();
}
EXPORT(Ptr<void>, sceKernelGetThreadTLSAddr, SceUID thid, int key) {
return host.kernel.get_thread_tls_addr(host.mem, thid, key);
}
EXPORT(int, sceKernelGetThreadmgrUIDClass) {
return UNIMPLEMENTED();
}
EXPORT(uint64_t, sceKernelGetTimerBaseWide, SceUID timer_handle) {
const TimerPtr timer_info = lock_and_find(timer_handle, host.kernel.timers, host.kernel.mutex);
if (!timer_info)
return -1;
return timer_info->time;
}
EXPORT(uint64_t, sceKernelGetTimerTimeWide, SceUID timer_handle) {
const TimerPtr timer_info = lock_and_find(timer_handle, host.kernel.timers, host.kernel.mutex);
if (!timer_info)
return -1;
return get_current_time() - timer_info->time;
}
EXPORT(SceInt32, sceKernelNotifyCallback, SceUID callbackId, SceInt32 notifyArg) {
const CallbackPtr cb = lock_and_find(callbackId, host.kernel.callbacks, host.kernel.mutex);
if (!cb)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_CALLBACK_ID);
cb->direct_notify(notifyArg);
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelOpenCond) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenEventFlag) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenMsgPipe, const char *name) {
return msgpipe_find(host.kernel, export_name, name);
}
EXPORT(int, sceKernelOpenMutex) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenMutex_089) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenRWLock) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenSema) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelOpenSimpleEvent) {
return UNIMPLEMENTED();
}
EXPORT(SceUID, sceKernelOpenTimer, const char *name) {
STUBBED("References not implemented.");
SceUID timer_handle = -1;
TimerPtr timer_info;
host.kernel.mutex.lock();
for (const auto &timer : host.kernel.timers) {
if (timer.second->name == name) {
timer_handle = timer.first;
timer_info = timer.second;
break;
}
}
host.kernel.mutex.unlock();
assert(timer_info->openable);
return timer_handle;
}
EXPORT(int, sceKernelPollSema, SceUID semaid, int32_t needCount) {
assert(needCount >= 0);
const SemaphorePtr semaphore = lock_and_find(semaid, host.kernel.semaphores, host.kernel.mutex);
if (!semaphore) {
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_SEMA_ID);
}
std::unique_lock<std::mutex> semaphore_lock(semaphore->mutex);
if (semaphore->val < needCount) {
return SCE_KERNEL_ERROR_SEMA_ZERO;
}
semaphore->val -= needCount;
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelPulseEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelRegisterCallbackToEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelResumeThreadForVM, SceUID threadId) {
STUBBED("STUB");
const ThreadStatePtr thread = lock_and_find(threadId, host.kernel.threads, host.kernel.mutex);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
thread->resume();
return 0;
}
EXPORT(int, sceKernelSendSignal, SceUID target_thread_id) {
STUBBED("sceKernelSendSignal");
const auto thread = lock_and_find(target_thread_id, host.kernel.threads, host.kernel.mutex);
if (!thread->signal.send()) {
return SCE_KERNEL_ERROR_ALREADY_SENT;
}
return SCE_KERNEL_OK;
}
EXPORT(int, sceKernelSetEvent) {
return UNIMPLEMENTED();
}
EXPORT(SceInt32, sceKernelSetEventFlag, SceUID evfId, SceUInt32 bitPattern) {
return eventflag_set(host.kernel, export_name, thread_id, evfId, bitPattern);
}
EXPORT(int, sceKernelSetTimerTimeWide) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelSignalCond, SceUID condid) {
return condvar_signal(host.kernel, export_name, thread_id, condid,
Condvar::SignalTarget(Condvar::SignalTarget::Type::Any), SyncWeight::Heavy);
}
EXPORT(int, sceKernelSignalCondAll, SceUID condid) {
return condvar_signal(host.kernel, export_name, thread_id, condid,
Condvar::SignalTarget(Condvar::SignalTarget::Type::All), SyncWeight::Heavy);
}
EXPORT(int, sceKernelSignalCondTo, SceUID condid, SceUID thread_target) {
return condvar_signal(host.kernel, export_name, thread_id, condid,
Condvar::SignalTarget(Condvar::SignalTarget::Type::Specific, thread_target), SyncWeight::Heavy);
}
EXPORT(int, sceKernelSignalSema, SceUID semaid, int signal) {
return semaphore_signal(host.kernel, export_name, thread_id, semaid, signal);
}
EXPORT(int, sceKernelStartTimer, SceUID timer_handle) {
const TimerPtr &timer_info = host.kernel.timers[timer_handle];
if (timer_info->is_started)
return false;
timer_info->is_started = true;
timer_info->time = get_current_time();
return true;
}
EXPORT(int, sceKernelStopTimer, SceUID timer_handle) {
const TimerPtr timer_info = lock_and_find(timer_handle, host.kernel.timers, host.kernel.mutex);
if (!timer_info->is_started)
return false;
timer_info->is_started = false;
timer_info->time = get_current_time();
return true;
}
EXPORT(int, sceKernelSuspendThreadForVM, SceUID threadId) {
STUBBED("STUB");
const ThreadStatePtr thread = lock_and_find(threadId, host.kernel.threads, host.kernel.mutex);
if (!thread)
return RET_ERROR(SCE_KERNEL_ERROR_UNKNOWN_THREAD_ID);
thread->suspend();
return 0;
}
EXPORT(int, sceKernelTryLockMutex, SceUID mutexid, int lock_count) {
return mutex_try_lock(host.kernel, host.mem, export_name, thread_id, mutexid, lock_count, SyncWeight::Heavy);
}
EXPORT(int, sceKernelTryLockReadRWLock) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelTryLockWriteRWLock) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelUnlockMutex, SceUID mutexid, int unlock_count) {
return mutex_unlock(host.kernel, export_name, thread_id, mutexid, unlock_count, SyncWeight::Heavy);
}
EXPORT(int, sceKernelUnlockReadRWLock, SceUID lock_id) {
return rwlock_unlock(host.kernel, host.mem, export_name, thread_id, lock_id, false);
}
EXPORT(int, sceKernelUnlockWriteRWLock, SceUID lock_id) {
return rwlock_unlock(host.kernel, host.mem, export_name, thread_id, lock_id, true);
}
EXPORT(int, sceKernelUnregisterCallbackFromEvent) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelUnregisterCallbackFromEventAll) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelUnregisterThreadEventHandler) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelWaitThreadEndCB_089) {
return UNIMPLEMENTED();
}
EXPORT(int, sceKernelWaitThreadEnd_089) {
return UNIMPLEMENTED();
}
BRIDGE_IMPL(__sceKernelCreateLwMutex)
BRIDGE_IMPL(_sceKernelCancelEvent)
BRIDGE_IMPL(_sceKernelCancelEventFlag)
BRIDGE_IMPL(_sceKernelCancelEventWithSetPattern)
BRIDGE_IMPL(_sceKernelCancelMsgPipe)
BRIDGE_IMPL(_sceKernelCancelMutex)
BRIDGE_IMPL(_sceKernelCancelRWLock)
BRIDGE_IMPL(_sceKernelCancelSema)
BRIDGE_IMPL(_sceKernelCancelTimer)
BRIDGE_IMPL(_sceKernelCreateCond)
BRIDGE_IMPL(_sceKernelCreateEventFlag)
BRIDGE_IMPL(_sceKernelCreateLwCond)
BRIDGE_IMPL(_sceKernelCreateMsgPipeWithLR)
BRIDGE_IMPL(_sceKernelCreateMutex)
BRIDGE_IMPL(_sceKernelCreateRWLock)
BRIDGE_IMPL(_sceKernelCreateSema)
BRIDGE_IMPL(_sceKernelCreateSema_16XX)
BRIDGE_IMPL(_sceKernelCreateSimpleEvent)
BRIDGE_IMPL(_sceKernelCreateTimer)
BRIDGE_IMPL(_sceKernelDeleteLwCond)
BRIDGE_IMPL(_sceKernelDeleteLwMutex)
BRIDGE_IMPL(_sceKernelExitCallback)
BRIDGE_IMPL(_sceKernelGetCallbackInfo)
BRIDGE_IMPL(_sceKernelGetCondInfo)
BRIDGE_IMPL(_sceKernelGetEventFlagInfo)
BRIDGE_IMPL(_sceKernelGetEventInfo)
BRIDGE_IMPL(_sceKernelGetEventPattern)
BRIDGE_IMPL(_sceKernelGetLwCondInfo)
BRIDGE_IMPL(_sceKernelGetLwCondInfoById)
BRIDGE_IMPL(_sceKernelGetLwMutexInfoById)
BRIDGE_IMPL(_sceKernelGetMsgPipeInfo)
BRIDGE_IMPL(_sceKernelGetMutexInfo)
BRIDGE_IMPL(_sceKernelGetRWLockInfo)
BRIDGE_IMPL(_sceKernelGetSemaInfo)
BRIDGE_IMPL(_sceKernelGetSystemInfo)
BRIDGE_IMPL(_sceKernelGetSystemTime)
BRIDGE_IMPL(_sceKernelGetThreadContextForVM)
BRIDGE_IMPL(_sceKernelGetThreadCpuAffinityMask)
BRIDGE_IMPL(_sceKernelGetThreadEventInfo)
BRIDGE_IMPL(_sceKernelGetThreadExitStatus)
BRIDGE_IMPL(_sceKernelGetThreadInfo)
BRIDGE_IMPL(_sceKernelGetThreadRunStatus)
BRIDGE_IMPL(_sceKernelGetTimerBase)
BRIDGE_IMPL(_sceKernelGetTimerEventRemainingTime)
BRIDGE_IMPL(_sceKernelGetTimerInfo)
BRIDGE_IMPL(_sceKernelGetTimerTime)
BRIDGE_IMPL(_sceKernelLockLwMutex)
BRIDGE_IMPL(_sceKernelLockMutex)
BRIDGE_IMPL(_sceKernelLockMutexCB)
BRIDGE_IMPL(_sceKernelLockReadRWLock)
BRIDGE_IMPL(_sceKernelLockReadRWLockCB)
BRIDGE_IMPL(_sceKernelLockWriteRWLock)
BRIDGE_IMPL(_sceKernelLockWriteRWLockCB)
BRIDGE_IMPL(_sceKernelPMonThreadGetCounter)
BRIDGE_IMPL(_sceKernelPollEvent)
BRIDGE_IMPL(_sceKernelPollEventFlag)
BRIDGE_IMPL(_sceKernelPulseEventWithNotifyCallback)
BRIDGE_IMPL(_sceKernelReceiveMsgPipeVector)
BRIDGE_IMPL(_sceKernelReceiveMsgPipeVectorCB)
BRIDGE_IMPL(_sceKernelRegisterThreadEventHandler)
BRIDGE_IMPL(_sceKernelSendMsgPipeVector)
BRIDGE_IMPL(_sceKernelSendMsgPipeVectorCB)
BRIDGE_IMPL(_sceKernelSetEventWithNotifyCallback)
BRIDGE_IMPL(_sceKernelSetThreadContextForVM)
BRIDGE_IMPL(_sceKernelSetTimerEvent)
BRIDGE_IMPL(_sceKernelSetTimerTime)
BRIDGE_IMPL(_sceKernelSignalLwCond)
BRIDGE_IMPL(_sceKernelSignalLwCondAll)
BRIDGE_IMPL(_sceKernelSignalLwCondTo)
BRIDGE_IMPL(_sceKernelStartThread)
BRIDGE_IMPL(_sceKernelTryReceiveMsgPipeVector)
BRIDGE_IMPL(_sceKernelTrySendMsgPipeVector)
BRIDGE_IMPL(_sceKernelUnlockLwMutex)
BRIDGE_IMPL(_sceKernelWaitCond)
BRIDGE_IMPL(_sceKernelWaitCondCB)
BRIDGE_IMPL(_sceKernelWaitEvent)
BRIDGE_IMPL(_sceKernelWaitEventCB)
BRIDGE_IMPL(_sceKernelWaitEventFlag)
BRIDGE_IMPL(_sceKernelWaitEventFlagCB)
BRIDGE_IMPL(_sceKernelWaitException)
BRIDGE_IMPL(_sceKernelWaitExceptionCB)
BRIDGE_IMPL(_sceKernelWaitLwCond)
BRIDGE_IMPL(_sceKernelWaitLwCondCB)
BRIDGE_IMPL(_sceKernelWaitMultipleEvents)
BRIDGE_IMPL(_sceKernelWaitMultipleEventsCB)
BRIDGE_IMPL(_sceKernelWaitSema)
BRIDGE_IMPL(_sceKernelWaitSemaCB)
BRIDGE_IMPL(_sceKernelWaitSignal)
BRIDGE_IMPL(_sceKernelWaitSignalCB)
BRIDGE_IMPL(_sceKernelWaitThreadEnd)
BRIDGE_IMPL(_sceKernelWaitThreadEndCB)
BRIDGE_IMPL(sceKernelCancelCallback)
BRIDGE_IMPL(sceKernelChangeActiveCpuMask)
BRIDGE_IMPL(sceKernelChangeThreadCpuAffinityMask)
BRIDGE_IMPL(sceKernelChangeThreadPriority)
BRIDGE_IMPL(sceKernelChangeThreadPriority2)
BRIDGE_IMPL(sceKernelChangeThreadVfpException)
BRIDGE_IMPL(sceKernelCheckCallback)
BRIDGE_IMPL(sceKernelCheckWaitableStatus)
BRIDGE_IMPL(sceKernelClearEvent)
BRIDGE_IMPL(sceKernelClearEventFlag)
BRIDGE_IMPL(sceKernelCloseCond)
BRIDGE_IMPL(sceKernelCloseEventFlag)
BRIDGE_IMPL(sceKernelCloseMsgPipe)
BRIDGE_IMPL(sceKernelCloseMutex)
BRIDGE_IMPL(sceKernelCloseMutex_089)
BRIDGE_IMPL(sceKernelCloseRWLock)
BRIDGE_IMPL(sceKernelCloseSema)
BRIDGE_IMPL(sceKernelCloseSimpleEvent)
BRIDGE_IMPL(sceKernelCloseTimer)
BRIDGE_IMPL(sceKernelCreateCallback)
BRIDGE_IMPL(sceKernelCreateThreadForUser)
BRIDGE_IMPL(sceKernelDelayThread)
BRIDGE_IMPL(sceKernelDelayThread200)
BRIDGE_IMPL(sceKernelDelayThreadCB)
BRIDGE_IMPL(sceKernelDelayThreadCB200)
BRIDGE_IMPL(sceKernelDeleteCallback)
BRIDGE_IMPL(sceKernelDeleteCond)
BRIDGE_IMPL(sceKernelDeleteEventFlag)
BRIDGE_IMPL(sceKernelDeleteMsgPipe)
BRIDGE_IMPL(sceKernelDeleteMutex)
BRIDGE_IMPL(sceKernelDeleteRWLock)
BRIDGE_IMPL(sceKernelDeleteSema)
BRIDGE_IMPL(sceKernelDeleteSimpleEvent)
BRIDGE_IMPL(sceKernelDeleteThread)
BRIDGE_IMPL(sceKernelDeleteTimer)
BRIDGE_IMPL(sceKernelExitDeleteThread)
BRIDGE_IMPL(sceKernelGetCallbackCount)
BRIDGE_IMPL(sceKernelGetMsgPipeCreatorId)
BRIDGE_IMPL(sceKernelGetProcessId)
BRIDGE_IMPL(sceKernelGetSystemTimeWide)
BRIDGE_IMPL(sceKernelGetThreadCpuAffinityMask)
BRIDGE_IMPL(sceKernelGetThreadStackFreeSize)
BRIDGE_IMPL(sceKernelGetThreadTLSAddr)
BRIDGE_IMPL(sceKernelGetThreadmgrUIDClass)
BRIDGE_IMPL(sceKernelGetTimerBaseWide)
BRIDGE_IMPL(sceKernelGetTimerTimeWide)
BRIDGE_IMPL(sceKernelNotifyCallback)
BRIDGE_IMPL(sceKernelOpenCond)
BRIDGE_IMPL(sceKernelOpenEventFlag)
BRIDGE_IMPL(sceKernelOpenMsgPipe)
BRIDGE_IMPL(sceKernelOpenMutex)
BRIDGE_IMPL(sceKernelOpenMutex_089)
BRIDGE_IMPL(sceKernelOpenRWLock)
BRIDGE_IMPL(sceKernelOpenSema)
BRIDGE_IMPL(sceKernelOpenSimpleEvent)
BRIDGE_IMPL(sceKernelOpenTimer)
BRIDGE_IMPL(sceKernelPollSema)
BRIDGE_IMPL(sceKernelPulseEvent)
BRIDGE_IMPL(sceKernelRegisterCallbackToEvent)
BRIDGE_IMPL(sceKernelResumeThreadForVM)
BRIDGE_IMPL(sceKernelSendSignal)
BRIDGE_IMPL(sceKernelSetEvent)
BRIDGE_IMPL(sceKernelSetEventFlag)
BRIDGE_IMPL(sceKernelSetTimerTimeWide)
BRIDGE_IMPL(sceKernelSignalCond)
BRIDGE_IMPL(sceKernelSignalCondAll)
BRIDGE_IMPL(sceKernelSignalCondTo)
BRIDGE_IMPL(sceKernelSignalSema)
BRIDGE_IMPL(sceKernelStartTimer)
BRIDGE_IMPL(sceKernelStopTimer)
BRIDGE_IMPL(sceKernelSuspendThreadForVM)
BRIDGE_IMPL(sceKernelTryLockMutex)
BRIDGE_IMPL(sceKernelTryLockReadRWLock)
BRIDGE_IMPL(sceKernelTryLockWriteRWLock)
BRIDGE_IMPL(sceKernelUnlockMutex)
BRIDGE_IMPL(sceKernelUnlockReadRWLock)
BRIDGE_IMPL(sceKernelUnlockWriteRWLock)
BRIDGE_IMPL(sceKernelUnregisterCallbackFromEvent)
BRIDGE_IMPL(sceKernelUnregisterCallbackFromEventAll)
BRIDGE_IMPL(sceKernelUnregisterThreadEventHandler)
BRIDGE_IMPL(sceKernelWaitThreadEndCB_089)
BRIDGE_IMPL(sceKernelWaitThreadEnd_089)