2013-11-03 20:23:16 +01:00
# pragma once
2015-07-01 00:25:52 +02:00
2014-08-25 16:56:13 +02:00
# include "Utilities/Thread.h"
2015-07-01 00:25:52 +02:00
enum CPUThreadType
2013-11-03 20:23:16 +01:00
{
CPU_THREAD_PPU ,
CPU_THREAD_SPU ,
CPU_THREAD_RAW_SPU ,
2013-11-05 20:22:58 +01:00
CPU_THREAD_ARMv7 ,
2013-11-03 20:23:16 +01:00
} ;
2015-07-01 00:25:52 +02:00
// CPU Thread State Flags
2015-03-16 22:38:21 +01:00
enum : u64
{
2015-07-01 19:09:26 +02:00
CPU_STATE_STOPPED = ( 1ull < < 0 ) , // basic execution state (stopped by default), removed by Exec()
2015-07-03 18:07:36 +02:00
CPU_STATE_PAUSED = ( 1ull < < 1 ) , // pauses thread execution, set by the debugger (manually or after step execution)
CPU_STATE_SLEEP = ( 1ull < < 2 ) , // shouldn't affect thread execution, set by Sleep() call, removed by the latest Awake() call, may possibly indicate waiting state of the thread
CPU_STATE_STEP = ( 1ull < < 3 ) , // forces the thread to pause after executing just one instruction or something appropriate, set by the debugger
CPU_STATE_DEAD = ( 1ull < < 4 ) , // indicates irreversible exit of the thread
CPU_STATE_RETURN = ( 1ull < < 5 ) , // used for callback return
2015-07-15 20:11:32 +02:00
CPU_STATE_SIGNAL = ( 1ull < < 6 ) , // used for HLE signaling
CPU_STATE_INTR = ( 1ull < < 7 ) , // thread interrupted
2015-07-03 18:07:36 +02:00
2015-07-15 20:11:32 +02:00
CPU_STATE_MAX = ( 1ull < < 8 ) , // added to (subtracted from) m_state by Sleep()/Awake() calls to trigger status check
2015-03-16 22:38:21 +01:00
} ;
2015-07-01 00:25:52 +02:00
// "HLE return" exception event
2015-08-11 15:26:08 +02:00
class CPUThreadReturn { } ;
2015-07-01 00:25:52 +02:00
// CPUThread::Stop exception event
2015-08-11 15:26:08 +02:00
class CPUThreadStop { } ;
2015-07-01 00:25:52 +02:00
// CPUThread::Exit exception event
2015-08-11 15:26:08 +02:00
class CPUThreadExit { } ;
2015-07-01 00:25:52 +02:00
2014-08-23 22:40:04 +02:00
class CPUDecoder ;
2015-08-19 13:04:58 +02:00
class CPUThread : public named_thread_t , public std : : enable_shared_from_this < CPUThread >
2013-11-03 20:23:16 +01:00
{
2015-08-19 13:04:58 +02:00
using named_thread_t : : start ;
2015-08-11 15:26:08 +02:00
2013-11-03 20:23:16 +01:00
protected :
2015-08-19 13:04:58 +02:00
using named_thread_t : : detach ;
using named_thread_t : : join ;
using named_thread_t : : joinable ;
2015-08-11 15:26:08 +02:00
2015-09-18 00:41:14 +02:00
atomic_t < u64 > m_state { CPU_STATE_STOPPED } ; // thread state flags
2015-03-16 22:38:21 +01:00
2015-07-01 00:25:52 +02:00
std : : unique_ptr < CPUDecoder > m_dec ;
2013-11-03 20:23:16 +01:00
2015-07-01 00:25:52 +02:00
const u32 m_id ;
const CPUThreadType m_type ;
const std : : string m_name ; // changing m_name would be terribly thread-unsafe in current implementation
2013-11-03 20:23:16 +01:00
2015-07-01 00:25:52 +02:00
CPUThread ( CPUThreadType type , const std : : string & name , std : : function < std : : string ( ) > thread_name ) ;
2013-11-05 19:12:18 +01:00
2015-07-01 00:25:52 +02:00
public :
virtual ~ CPUThread ( ) override ;
2014-11-09 07:20:01 +01:00
2015-07-19 13:36:32 +02:00
u32 get_id ( ) const { return m_id ; }
CPUThreadType get_type ( ) const { return m_type ; }
std : : string get_name ( ) const { return m_name ; }
2015-02-18 17:22:06 +01:00
2015-09-18 00:41:14 +02:00
bool is_alive ( ) const { return ( m_state & CPU_STATE_DEAD ) = = 0 ; }
bool is_stopped ( ) const { return ( m_state & CPU_STATE_STOPPED ) ! = 0 ; }
2015-07-19 13:36:32 +02:00
virtual bool is_paused ( ) const ;
2015-03-16 22:38:21 +01:00
2015-07-19 13:36:32 +02:00
virtual void dump_info ( ) const ;
virtual u32 get_pc ( ) const = 0 ;
virtual u32 get_offset ( ) const = 0 ;
virtual void do_run ( ) = 0 ;
virtual void task ( ) = 0 ;
2013-11-03 20:23:16 +01:00
2015-07-19 13:36:32 +02:00
virtual void init_regs ( ) = 0 ;
virtual void init_stack ( ) = 0 ;
virtual void close_stack ( ) = 0 ;
2013-11-03 20:23:16 +01:00
2015-07-03 18:07:36 +02:00
// initialize thread
2015-07-19 13:36:32 +02:00
void run ( ) ;
2015-07-03 18:07:36 +02:00
// called by the debugger, don't use
2015-07-19 13:36:32 +02:00
void pause ( ) ;
2015-07-03 18:07:36 +02:00
// called by the debugger, don't use
2015-07-19 13:36:32 +02:00
void resume ( ) ;
2015-07-03 18:07:36 +02:00
// stop thread execution
2015-07-19 13:36:32 +02:00
void stop ( ) ;
2015-07-03 18:07:36 +02:00
// start thread execution (removing STOP status)
2015-07-19 13:36:32 +02:00
void exec ( ) ;
2015-07-03 18:07:36 +02:00
// exit thread execution
2015-07-19 13:36:32 +02:00
void exit ( ) ;
2015-07-03 18:07:36 +02:00
// called by the debugger, don't use
2015-07-19 13:36:32 +02:00
void step ( ) ;
2015-07-03 18:07:36 +02:00
// trigger thread status check
2015-07-19 13:36:32 +02:00
void sleep ( ) ;
2015-07-03 18:07:36 +02:00
// untrigger thread status check
2015-07-19 13:36:32 +02:00
void awake ( ) ;
2015-07-03 18:07:36 +02:00
2015-07-08 00:33:24 +02:00
// set SIGNAL and notify (returns true if set)
2015-07-19 13:36:32 +02:00
bool signal ( ) ;
2015-07-08 00:33:24 +02:00
// test SIGNAL and reset
2015-07-19 13:36:32 +02:00
bool unsignal ( ) ;
2015-07-08 00:33:24 +02:00
2015-07-03 18:07:36 +02:00
// process m_state flags, returns true if the checker must return
2015-07-19 13:36:32 +02:00
bool check_status ( ) ;
2013-11-03 20:23:16 +01:00
2015-08-10 21:39:52 +02:00
virtual bool handle_interrupt ( ) { return false ; }
2014-04-01 02:33:55 +02:00
std : : string GetFName ( ) const
2013-11-03 20:23:16 +01:00
{
2015-07-01 00:25:52 +02:00
return fmt : : format ( " %s[0x%x] Thread (%s) " , GetTypeString ( ) , m_id , m_name ) ;
2013-11-03 20:23:16 +01:00
}
2015-07-01 00:25:52 +02:00
static const char * CPUThreadTypeToString ( CPUThreadType type )
2013-11-03 20:23:16 +01:00
{
2015-07-01 00:25:52 +02:00
switch ( type )
2013-11-03 20:23:16 +01:00
{
case CPU_THREAD_PPU : return " PPU " ;
case CPU_THREAD_SPU : return " SPU " ;
case CPU_THREAD_RAW_SPU : return " RawSPU " ;
2013-11-05 20:22:58 +01:00
case CPU_THREAD_ARMv7 : return " ARMv7 " ;
2013-11-03 20:23:16 +01:00
}
return " Unknown " ;
}
2015-08-08 19:59:10 +02:00
const char * ThreadStatusToString ( ) const
2014-09-07 15:47:53 +02:00
{
2015-07-01 00:25:52 +02:00
// TODO
//switch (ThreadStatus())
//{
//case CPUThread_Ready: return "Ready";
//case CPUThread_Running: return "Running";
//case CPUThread_Paused: return "Paused";
//case CPUThread_Stopped: return "Stopped";
//case CPUThread_Sleeping: return "Sleeping";
//case CPUThread_Break: return "Break";
//case CPUThread_Step: return "Step";
//}
2014-09-07 15:47:53 +02:00
2015-07-01 00:25:52 +02:00
return " Unknown " ;
}
2013-11-03 20:23:16 +01:00
2015-07-01 00:25:52 +02:00
const char * GetTypeString ( ) const
2013-11-03 20:23:16 +01:00
{
2015-07-01 00:25:52 +02:00
return CPUThreadTypeToString ( m_type ) ;
2013-11-03 20:23:16 +01:00
}
2015-07-01 00:25:52 +02:00
CPUDecoder * GetDecoder ( )
{
return m_dec . get ( ) ;
} ;
2013-11-03 20:23:16 +01:00
2015-07-01 00:25:52 +02:00
virtual std : : string RegsToString ( ) const = 0 ;
virtual std : : string ReadRegString ( const std : : string & reg ) const = 0 ;
2014-04-01 02:33:55 +02:00
virtual bool WriteRegString ( const std : : string & reg , std : : string value ) = 0 ;
2013-11-03 20:23:16 +01:00
} ;
2014-11-19 15:16:30 +01:00
class cpu_thread
{
protected :
2015-03-04 22:51:14 +01:00
std : : shared_ptr < CPUThread > thread ;
2014-11-19 15:16:30 +01:00
public :
2015-07-01 00:25:52 +02:00
//u32 get_entry() const
//{
// return thread->entry;
//}
2014-11-19 15:16:30 +01:00
virtual cpu_thread & args ( std : : initializer_list < std : : string > values ) = 0 ;
virtual cpu_thread & run ( ) = 0 ;
2015-07-01 00:25:52 +02:00
//u64 join()
//{
// if (!joinable())
2015-07-02 03:54:36 +02:00
// throw EXCEPTION("thread must be joinable for join");
2014-11-19 15:16:30 +01:00
2015-07-01 00:25:52 +02:00
// thread->SetJoinable(false);
2014-11-19 15:16:30 +01:00
2015-07-01 00:25:52 +02:00
// while (thread->IsRunning())
// std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
2014-11-19 15:16:30 +01:00
2015-07-01 00:25:52 +02:00
// return thread->GetExitStatus();
//}
2014-11-19 15:16:30 +01:00
2015-07-01 00:25:52 +02:00
//bool joinable() const
//{
// return thread->IsJoinable();
//}
2014-11-19 15:16:30 +01:00
2015-07-19 13:36:32 +02:00
//u32 get_id() const
//{
// return thread->GetId();
//}
2015-02-01 14:52:34 +01:00
} ;