2012-11-01 15:19:01 +00:00
// Copyright (c) 2012- PPSSPP Project.
// 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
2012-11-04 22:01:49 +00:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 15:19:01 +00:00
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
# pragma once
// There's a good description of the thread scheduling rules in:
// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/ThreadManForUser.java
# include "sceKernelModule.h"
# include "HLE.h"
void sceKernelChangeThreadPriority ( ) ;
2013-01-02 01:04:06 +00:00
int __KernelCreateThread ( const char * threadName , SceUID moduleID , u32 entry , u32 prio , int stacksize , u32 attr , u32 optionAddr ) ;
2012-12-09 08:29:10 +00:00
int sceKernelCreateThread ( const char * threadName , u32 entry , u32 prio , int stacksize , u32 attr , u32 optionAddr ) ;
2013-03-06 15:40:34 +00:00
int sceKernelDelayThread ( u32 usec ) ;
int sceKernelDelayThreadCB ( u32 usec ) ;
2013-01-05 22:24:05 +00:00
void sceKernelDelaySysClockThread ( ) ;
void sceKernelDelaySysClockThreadCB ( ) ;
2012-12-09 08:29:10 +00:00
int sceKernelDeleteThread ( int threadHandle ) ;
2013-04-10 06:16:23 +00:00
void sceKernelExitDeleteThread ( int exitStatus ) ;
void sceKernelExitThread ( int exitStatus ) ;
void _sceKernelExitThread ( int exitStatus ) ;
SceUID sceKernelGetThreadId ( ) ;
2012-11-06 15:20:13 +00:00
void sceKernelGetThreadCurrentPriority ( ) ;
2012-12-09 08:29:10 +00:00
int sceKernelStartThread ( SceUID threadToStartID , u32 argSize , u32 argBlockPtr ) ;
2012-11-06 18:22:14 +00:00
u32 sceKernelSuspendDispatchThread ( ) ;
u32 sceKernelResumeDispatchThread ( u32 suspended ) ;
2013-01-07 18:02:11 +00:00
int sceKernelWaitThreadEnd ( SceUID threadID , u32 timeoutPtr ) ;
2013-01-05 22:06:28 +00:00
u32 sceKernelReferThreadStatus ( u32 uid , u32 statusPtr ) ;
u32 sceKernelReferThreadRunStatus ( u32 uid , u32 statusPtr ) ;
2013-01-08 03:44:39 +00:00
int sceKernelReleaseWaitThread ( SceUID threadID ) ;
2012-11-01 15:19:01 +00:00
void sceKernelChangeCurrentThreadAttr ( ) ;
2013-02-09 10:17:19 +00:00
int sceKernelRotateThreadReadyQueue ( int priority ) ;
2013-03-23 13:41:13 +00:00
int sceKernelCheckThreadStack ( ) ;
2012-11-01 15:19:01 +00:00
void sceKernelSuspendThread ( ) ;
void sceKernelResumeThread ( ) ;
void sceKernelWakeupThread ( ) ;
2012-11-11 23:04:57 +00:00
void sceKernelCancelWakeupThread ( ) ;
2012-12-09 08:29:10 +00:00
int sceKernelTerminateDeleteThread ( int threadno ) ;
2013-03-02 22:58:58 +00:00
int sceKernelTerminateThread ( SceUID threadID ) ;
2013-01-07 18:02:11 +00:00
int sceKernelWaitThreadEndCB ( SceUID threadID , u32 timeoutPtr ) ;
2012-11-01 15:19:01 +00:00
void sceKernelGetThreadExitStatus ( ) ;
2012-12-17 21:20:32 +00:00
u32 sceKernelGetThreadmanIdType ( u32 ) ;
u32 sceKernelGetThreadmanIdList ( u32 type , u32 readBufPtr , u32 readBufSize , u32 idCountPtr ) ;
2013-02-03 18:53:38 +00:00
u32 sceKernelExtendThreadStack ( u32 cpu , u32 size , u32 entryAddr , u32 entryParameter ) ;
2012-11-01 15:19:01 +00:00
2012-12-30 20:30:33 +00:00
struct SceKernelSysClock {
u32 lo ;
u32 hi ;
} ;
2012-11-01 15:19:01 +00:00
2013-03-27 07:51:46 +00:00
// TODO: Map these to PSP wait types.
enum WaitType
2012-11-01 15:19:01 +00:00
{
WAITTYPE_NONE = 0 ,
WAITTYPE_SLEEP = 1 ,
WAITTYPE_DELAY = 2 ,
WAITTYPE_SEMA = 3 ,
WAITTYPE_EVENTFLAG = 4 ,
WAITTYPE_MBX = 5 ,
WAITTYPE_VPL = 6 ,
WAITTYPE_FPL = 7 ,
2012-11-10 22:17:15 +00:00
WAITTYPE_MSGPIPE = 8 , // fake
2012-11-01 15:19:01 +00:00
WAITTYPE_THREADEND = 9 ,
WAITTYPE_AUDIOCHANNEL = 10 , // this is fake, should be replaced with 8 eventflags ( ?? )
WAITTYPE_UMD = 11 , // this is fake, should be replaced with 1 eventflag ( ?? )
WAITTYPE_VBLANK = 12 , // fake
2012-11-19 01:54:55 +00:00
WAITTYPE_MUTEX = 13 ,
2012-11-21 08:21:10 +00:00
WAITTYPE_LWMUTEX = 14 ,
2012-12-03 01:03:13 +00:00
WAITTYPE_CTRL = 15 ,
2013-03-10 10:43:50 +00:00
WAITTYPE_IO = 16 ,
2013-04-06 05:38:19 +00:00
WAITTYPE_GEDRAWSYNC = 17 ,
2013-04-06 09:28:49 +00:00
WAITTYPE_GELISTSYNC = 18 ,
2013-03-27 07:51:46 +00:00
NUM_WAITTYPES
2012-11-01 15:19:01 +00:00
} ;
2013-03-27 07:51:46 +00:00
// Suspend wait and timeout while a thread enters a callback.
typedef void ( * WaitBeginCallbackFunc ) ( SceUID threadID , SceUID prevCallbackId ) ;
// Resume wait and timeout as a thread exits a callback.
typedef void ( * WaitEndCallbackFunc ) ( SceUID threadID , SceUID prevCallbackId , u32 & returnValue ) ;
void __KernelRegisterWaitTypeFuncs ( WaitType type , WaitBeginCallbackFunc beginFunc , WaitEndCallbackFunc endFunc ) ;
2012-11-01 15:19:01 +00:00
struct ThreadContext
{
2012-12-30 20:30:33 +00:00
void reset ( ) ;
u32 r [ 32 ] ;
float f [ 32 ] ;
float v [ 128 ] ;
u32 vfpuCtrl [ 16 ] ;
2013-01-26 19:27:06 +00:00
u32 pc ;
2012-12-30 20:30:33 +00:00
u32 hi ;
u32 lo ;
u32 fcr0 ;
u32 fcr31 ;
2013-01-26 19:27:06 +00:00
u32 fpcond ;
2012-11-01 15:19:01 +00:00
} ;
// Internal API, used by implementations of kernel functions
void __KernelThreadingInit ( ) ;
2012-12-28 03:30:36 +00:00
void __KernelThreadingDoState ( PointerWrap & p ) ;
void __KernelThreadingDoStateLate ( PointerWrap & p ) ;
2012-11-01 15:19:01 +00:00
void __KernelThreadingShutdown ( ) ;
2012-12-27 06:45:19 +00:00
KernelObject * __KernelThreadObject ( ) ;
KernelObject * __KernelCallbackObject ( ) ;
2012-11-01 15:19:01 +00:00
2013-01-05 22:24:05 +00:00
void __KernelScheduleWakeup ( int threadnumber , s64 usFromNow ) ;
2012-11-01 15:19:01 +00:00
SceUID __KernelGetCurThread ( ) ;
2013-03-23 13:26:54 +00:00
u32 __KernelGetCurThreadStack ( ) ;
2013-03-11 05:25:03 +00:00
const char * __KernelGetThreadName ( SceUID threadID ) ;
2012-11-01 15:19:01 +00:00
2013-04-07 18:28:37 +00:00
void __KernelSaveContext ( ThreadContext * ctx , bool vfpuEnabled ) ;
void __KernelLoadContext ( ThreadContext * ctx , bool vfpuEnabled ) ;
2012-11-01 15:19:01 +00:00
2012-12-17 19:14:06 +00:00
// TODO: Replace this with __KernelResumeThreadFromWait over time as it's misguided.
// It's better that each subsystem keeps track of the list of waiting threads
// and resumes them manually one by one using __KernelResumeThreadFromWait.
2013-01-26 18:59:17 +00:00
bool __KernelTriggerWait ( WaitType type , int id , const char * reason , bool dontSwitch = false ) ;
bool __KernelTriggerWait ( WaitType type , int id , int retVal , const char * reason , bool dontSwitch ) ;
2012-11-17 13:20:04 +00:00
u32 __KernelResumeThreadFromWait ( SceUID threadID ) ; // can return an error value
2013-03-10 17:59:59 +00:00
u32 __KernelResumeThreadFromWait ( SceUID threadID , u32 retval ) ;
u32 __KernelResumeThreadFromWait ( SceUID threadID , u64 retval ) ;
inline u32 __KernelResumeThreadFromWait ( SceUID threadID , int retval )
{
return __KernelResumeThreadFromWait ( threadID , ( u32 ) retval ) ;
}
inline u32 __KernelResumeThreadFromWait ( SceUID threadID , s64 retval )
{
return __KernelResumeThreadFromWait ( threadID , ( u64 ) retval ) ;
}
2012-11-01 15:19:01 +00:00
u32 __KernelGetWaitValue ( SceUID threadID , u32 & error ) ;
2012-11-19 03:13:39 +00:00
u32 __KernelGetWaitTimeoutPtr ( SceUID threadID , u32 & error ) ;
2012-11-20 08:18:11 +00:00
SceUID __KernelGetWaitID ( SceUID threadID , WaitType type , u32 & error ) ;
2013-03-27 07:51:46 +00:00
SceUID __KernelGetCurrentCallbackID ( SceUID threadID , u32 & error ) ;
2013-01-26 18:44:04 +00:00
void __KernelWaitCurThread ( WaitType type , SceUID waitId , u32 waitValue , u32 timeoutPtr , bool processCallbacks , const char * reason ) ;
2013-03-30 20:48:29 +00:00
void __KernelWaitCallbacksCurThread ( WaitType type , SceUID waitID , u32 waitValue , u32 timeoutPtr ) ;
2012-11-01 15:19:01 +00:00
void __KernelReSchedule ( const char * reason = " no reason " ) ;
2012-11-07 14:44:48 +00:00
void __KernelReSchedule ( bool doCallbacks , const char * reason ) ;
2012-11-06 14:46:21 +00:00
// Registered callback types
enum RegisteredCallbackType {
2012-12-30 20:30:33 +00:00
THREAD_CALLBACK_UMD = 0 ,
THREAD_CALLBACK_IO = 1 ,
THREAD_CALLBACK_MEMORYSTICK = 2 ,
THREAD_CALLBACK_MEMORYSTICK_FAT = 3 ,
THREAD_CALLBACK_POWER = 4 ,
THREAD_CALLBACK_EXIT = 5 ,
THREAD_CALLBACK_USER_DEFINED = 6 ,
THREAD_CALLBACK_SIZE = 7 ,
THREAD_CALLBACK_NUM_TYPES = 8 ,
2012-11-06 14:46:21 +00:00
} ;
// These operate on the current thread
u32 __KernelRegisterCallback ( RegisteredCallbackType type , SceUID cbId ) ;
u32 __KernelUnregisterCallback ( RegisteredCallbackType type , SceUID cbId ) ;
// If cbId == -1, all the callbacks of the type on all the threads get notified.
// If not, only this particular callback gets notified.
u32 __KernelNotifyCallbackType ( RegisteredCallbackType type , SceUID cbId , int notifyArg ) ;
2012-11-01 15:19:01 +00:00
SceUID __KernelGetCurThread ( ) ;
2012-11-17 13:20:04 +00:00
SceUID __KernelGetCurThreadModuleId ( ) ;
2012-11-01 15:19:01 +00:00
void __KernelSetupRootThread ( SceUID moduleId , int args , const char * argp , int prio , int stacksize , int attr ) ; //represents the real PSP elf loader, run before execution
2013-04-11 04:16:31 +00:00
void __KernelStartIdleThreads ( SceUID moduleId ) ;
2012-11-07 14:44:48 +00:00
void __KernelReturnFromThread ( ) ; // Called as HLE function
2012-11-08 13:24:51 +00:00
u32 __KernelGetThreadPrio ( SceUID id ) ;
2013-01-17 08:45:13 +00:00
bool __KernelThreadSortPriority ( SceUID thread1 , SceUID thread2 ) ;
2013-03-25 06:30:32 +00:00
bool __KernelIsDispatchEnabled ( ) ;
2012-11-01 15:19:01 +00:00
2012-11-17 13:20:04 +00:00
void __KernelIdle ( ) ;
2012-11-01 15:19:01 +00:00
2012-11-07 14:44:48 +00:00
u32 __KernelMipsCallReturnAddress ( ) ;
u32 __KernelInterruptReturnAddress ( ) ; // TODO: remove
2012-11-06 14:46:21 +00:00
// Internal access - used by sceSetGeCallback
u32 __KernelCreateCallback ( const char * name , u32 entrypoint , u32 signalArg ) ;
void sceKernelCreateCallback ( ) ;
void sceKernelDeleteCallback ( ) ;
void sceKernelNotifyCallback ( ) ;
void sceKernelCancelCallback ( ) ;
void sceKernelGetCallbackCount ( ) ;
2012-11-07 14:44:48 +00:00
void sceKernelCheckCallback ( ) ;
2012-11-06 14:46:21 +00:00
void sceKernelGetCallbackCount ( ) ;
void sceKernelReferCallbackStatus ( ) ;
2012-11-13 17:05:26 +00:00
class Action ;
// Not an official Callback object, just calls a mips function on the current thread.
2013-02-03 02:03:55 +00:00
void __KernelDirectMipsCall ( u32 entryPoint , Action * afterAction , u32 args [ ] , int numargs , bool reschedAfter ) ;
2012-11-13 17:05:26 +00:00
2012-11-07 14:44:48 +00:00
void __KernelReturnFromMipsCall ( ) ; // Called as HLE function
2012-11-06 14:46:21 +00:00
bool __KernelInCallback ( ) ;
// Should be called by (nearly) all ...CB functions.
bool __KernelCheckCallbacks ( ) ;
2012-12-02 02:43:45 +00:00
bool __KernelForceCallbacks ( ) ;
2013-03-29 07:27:33 +00:00
bool __KernelCurHasReadyCallbacks ( ) ;
2012-11-07 14:44:48 +00:00
class Thread ;
void __KernelSwitchContext ( Thread * target , const char * reason ) ;
2013-03-09 22:21:21 +00:00
bool __KernelExecutePendingMipsCalls ( Thread * currentThread , bool reschedAfter ) ;
2012-12-08 06:25:42 +00:00
void __KernelNotifyCallback ( RegisteredCallbackType type , SceUID cbId , int notifyArg ) ;
2012-11-07 14:44:48 +00:00
2012-12-18 08:58:46 +00:00
// Switch to an idle / non-user thread, if not already on one.
// Returns whether a switch occurred.
bool __KernelSwitchOffThread ( const char * reason ) ;
2013-04-07 00:03:39 +00:00
bool __KernelSwitchToThread ( SceUID threadID , const char * reason ) ;
2012-12-18 08:58:46 +00:00
2012-11-07 14:44:48 +00:00
// A call into game code. These can be pending on a thread.
// Similar to Callback-s (NOT CallbackInfos) in JPCSP.
2012-12-28 03:30:36 +00:00
typedef Action * ( * ActionCreator ) ( ) ;
Action * __KernelCreateAction ( int actionType ) ;
int __KernelRegisterActionType ( ActionCreator creator ) ;
void __KernelRestoreActionType ( int actionType , ActionCreator creator ) ;
2012-12-29 06:32:56 +00:00
2012-11-07 14:44:48 +00:00
struct MipsCall {
2013-02-03 02:46:23 +00:00
MipsCall ( )
{
doAfter = NULL ;
}
2012-11-07 14:44:48 +00:00
u32 entryPoint ;
u32 cbId ;
u32 args [ 6 ] ;
int numArgs ;
Action * doAfter ;
u32 savedIdRegister ;
u32 savedRa ;
u32 savedPc ;
u32 savedV0 ;
u32 savedV1 ;
2012-12-28 03:30:36 +00:00
std : : string tag ;
2012-12-08 19:23:20 +00:00
u32 savedId ;
2012-12-09 04:09:20 +00:00
bool reschedAfter ;
2012-12-28 03:30:36 +00:00
void DoState ( PointerWrap & p ) ;
2013-01-06 23:53:44 +00:00
void setReturnValue ( u32 value ) ;
2013-03-10 17:59:59 +00:00
void setReturnValue ( u64 value ) ;
inline void setReturnValue ( int value )
{
setReturnValue ( ( u32 ) value ) ;
}
inline void setReturnValue ( s64 value )
{
setReturnValue ( ( u64 ) value ) ;
}
2013-01-06 23:53:44 +00:00
} ;
class Action
{
public :
virtual ~ Action ( ) { }
virtual void run ( MipsCall & call ) = 0 ;
virtual void DoState ( PointerWrap & p ) = 0 ;
int actionTypeID ;
2012-11-07 14:44:48 +00:00
} ;
2012-12-30 20:30:33 +00:00
2012-11-07 14:44:48 +00:00
enum ThreadStatus
{
THREADSTATUS_RUNNING = 1 ,
THREADSTATUS_READY = 2 ,
THREADSTATUS_WAIT = 4 ,
THREADSTATUS_SUSPEND = 8 ,
THREADSTATUS_DORMANT = 16 ,
THREADSTATUS_DEAD = 32 ,
THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
} ;
void __KernelChangeThreadState ( Thread * thread , ThreadStatus newStatus ) ;
2012-11-20 08:18:11 +00:00
typedef void ( * ThreadCallback ) ( SceUID threadID ) ;
void __KernelListenThreadEnd ( ThreadCallback callback ) ;
2013-02-10 15:36:06 +00:00
struct DebugThreadInfo
{
SceUID id ;
char name [ KERNELOBJECT_MAX_NAME_LENGTH + 1 ] ;
u32 status ;
int curPC ;
int entrypoint ;
bool isCurrent ;
} ;
std : : vector < DebugThreadInfo > GetThreadsInfo ( ) ;
void __KernelChangeThreadState ( SceUID threadId , ThreadStatus newStatus ) ;