Merge branch 'master' into windows

This commit is contained in:
HappyDOGE
2022-07-27 12:58:56 +03:00
3089 changed files with 38639 additions and 844820 deletions
+13 -6
View File
@@ -171,17 +171,24 @@ typedef float vec_t;
// This assumes the ANSI/IEEE 754-1985 standard
//-----------------------------------------------------------------------------
inline unsigned long& FloatBits( vec_t& f )
// MoeMod : fix reinterpret_cast UB - Maybe fail with strict alias
union FloatCast_u
{
return *reinterpret_cast<unsigned long*>(&f);
vec_t f;
unsigned int i;
};
inline unsigned int& FloatBits( vec_t& f )
{
return reinterpret_cast<FloatCast_u *>(&f)->i;
}
inline unsigned long const& FloatBits( vec_t const& f )
inline unsigned int const& FloatBits( vec_t const& f )
{
return *reinterpret_cast<unsigned long const*>(&f);
return reinterpret_cast<FloatCast_u const*>(&f)->i;
}
inline vec_t BitsToFloat( unsigned long i )
inline vec_t BitsToFloat( unsigned int i )
{
vec_t f;
memcpy( &f, &i, sizeof(f));
@@ -193,7 +200,7 @@ inline bool IsFinite( vec_t f )
return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
}
inline unsigned long FloatAbsBits( vec_t f )
inline unsigned int FloatAbsBits( vec_t f )
{
return FloatBits(f) & 0x7FFFFFFF;
}
+8
View File
@@ -48,6 +48,14 @@
class Color;
class IDbgLogger
{
public:
virtual void Init(const char *logfile) = 0;
virtual void Write(const char *data) = 0;
};
PLATFORM_INTERFACE IDbgLogger *DebugLogger();
//-----------------------------------------------------------------------------
// Usage model for the Dbg library
+10 -5
View File
@@ -96,8 +96,8 @@ public:
virtual bool IsDebugHeap() = 0;
virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0;
virtual void RegisterAllocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0;
virtual void RegisterDeallocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0;
virtual void RegisterAllocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
virtual void RegisterDeallocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
virtual int GetVersion() = 0;
@@ -473,9 +473,14 @@ inline void MemAlloc_CheckAlloc( void *ptr, size_t nSize )
}
#if defined( OSX )
// Mac always aligns allocs, don't need to call posix_memalign which doesn't exist in 10.5.8 which TF2 still needs to run on
//inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; posix_memalign(&pTmp, alignment, size); return pTmp;}
inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; pTmp = malloc(size); MemAlloc_CheckAlloc( pTmp, size ); return pTmp;}
inline void *memalign(size_t alignment, size_t size) {
// MoeMod : 64bit fix
if(alignment < sizeof(void *))
alignment = sizeof(void *);
void *pTmp = nullptr;
posix_memalign(&pTmp, alignment, size);
return pTmp;
}
#endif
inline void *_aligned_malloc( size_t nSize, size_t align ) { void *ptr = memalign( align, nSize ); MemAlloc_CheckAlloc( ptr, nSize ); return ptr; }
+4
View File
@@ -29,7 +29,11 @@
#include <wchar.h>
#endif
#include <string.h>
#ifdef OSX
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif
#include "commonmacros.h"
#include "memalloc.h"
+46
View File
@@ -0,0 +1,46 @@
//========== Copyright (C) Valve Corporation, All rights reserved. ==========//
//
// Purpose: CVirtualMemoryManager interface
//
//===========================================================================//
#ifndef MEM_VIRT_H
#define MEM_VIRT_H
#ifdef _WIN32
#pragma once
#endif
#define VMM_KB ( 1024 )
#define VMM_MB ( 1024 * VMM_KB )
#ifdef _PS3
// Total virtual address space reserved by CVirtualMemoryManager on startup:
#define VMM_VIRTUAL_SIZE ( 512 * VMM_MB )
#define VMM_PAGE_SIZE ( 64 * VMM_KB )
#endif
// Allocate virtual sections via IMemAlloc::AllocateVirtualMemorySection
abstract_class IVirtualMemorySection
{
public:
// Information about memory section
virtual void * GetBaseAddress() = 0;
virtual size_t GetPageSize() = 0;
virtual size_t GetTotalSize() = 0;
// Functions to manage physical memory mapped to virtual memory
virtual bool CommitPages( void *pvBase, size_t numBytes ) = 0;
virtual void DecommitPages( void *pvBase, size_t numBytes ) = 0;
// Release the physical memory and associated virtual address space
virtual void Release() = 0;
};
// Get the IVirtualMemorySection associated with a given memory address (if any):
extern IVirtualMemorySection *GetMemorySectionForAddress( void *pAddress );
#endif // MEM_VIRT_H
+46 -9
View File
@@ -9,7 +9,7 @@
#ifndef PLATFORM_H
#define PLATFORM_H
#if defined(__x86_64__) || defined(_WIN64)
#if defined(__x86_64__) || defined(_WIN64) || defined(__aarch64__)
#define PLATFORM_64BITS 1
#endif
@@ -70,7 +70,11 @@
#include <time.h>
#endif
#ifdef OSX
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif
#include <new>
// need this for memset
@@ -171,6 +175,9 @@ typedef signed char int8;
typedef __int64 int64;
typedef unsigned __int64 uint64;
typedef int64 lint64;
typedef uint64 ulint64;
#ifdef PLATFORM_64BITS
typedef __int64 intp; // intp is an integer that can accomodate a pointer
typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
@@ -201,13 +208,17 @@ typedef signed char int8;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
typedef long int lint64;
typedef unsigned long int ulint64;
#ifdef PLATFORM_64BITS
typedef long long intp;
typedef unsigned long long uintp;
#else
typedef int intp;
typedef unsigned int uintp;
#endif
#endif
typedef void *HWND;
// Avoid redefinition warnings if a previous header defines this.
@@ -429,7 +440,17 @@ typedef void * HINSTANCE;
// On OSX, SIGTRAP doesn't really stop the thread cold when debugging.
// So if being debugged, use INT3 which is precise.
#ifdef OSX
#define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm ( "int $3" ); } else { raise(SIGTRAP); }
#if defined(__arm__) || defined(__aarch64__)
#ifdef __clang__
#define DebuggerBreak() do { if ( Plat_IsInDebugSession() ) { __builtin_debugtrap(); } else { raise(SIGTRAP); } } while(0)
#elif defined __GNUC__
#define DebuggerBreak() do { if ( Plat_IsInDebugSession() ) { __builtin_trap(); } else { raise(SIGTRAP); } } while(0)
#else
#define DebuggerBreak() raise(SIGTRAP)
#endif
#else
#define DebuggerBreak() do { if ( Plat_IsInDebugSession() ) { __asm ( "int $3" ); } else { raise(SIGTRAP); } } while(0)
#endif
#else
#define DebuggerBreak() raise(SIGTRAP)
#endif
@@ -504,6 +525,16 @@ typedef void * HINSTANCE;
#error
#endif
// !!! NOTE: if you get a compile error here, you are using VALIGNOF on an abstract type :NOTE !!!
#define VALIGNOF_PORTABLE( type ) ( sizeof( AlignOf_t<type> ) - sizeof( type ) )
#if defined( COMPILER_GCC ) || defined( COMPILER_MSVC )
#define VALIGNOF( type ) __alignof( type )
#define VALIGNOF_TEMPLATE_SAFE( type ) VALIGNOF_PORTABLE( type )
#else
#error "PORT: Code only tested with MSVC! Must validate with new compiler, and use built-in keyword if available."
#endif
// Pull in the /analyze code annotations.
#include "annotations.h"
@@ -600,6 +631,7 @@ typedef void * HINSTANCE;
#endif
// Used for standard calling conventions
#if defined( _WIN32 ) && !defined( _X360 )
#define STDCALL __stdcall
#define FASTCALL __fastcall
@@ -656,6 +688,11 @@ typedef void * HINSTANCE;
#ifdef _WIN32
#ifdef __SANITIZE_ADDRESS__
#undef FORCEINLINE
#define FORCEINLINE static
#endif
// Remove warnings from warning level 4.
#pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
#pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
@@ -752,7 +789,7 @@ typedef void * HINSTANCE;
#define _wtoi(arg) wcstol(arg, NULL, 10)
#define _wtoi64(arg) wcstoll(arg, NULL, 10)
typedef uint32 HMODULE;
typedef uintp HMODULE;
typedef void *HANDLE;
#endif
@@ -830,7 +867,7 @@ static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
#endif
#endif
#elif defined (__arm__)
#elif defined (__arm__) || defined (__aarch64__)
inline void SetupFPUControlWord() {}
#else
inline void SetupFPUControlWord()
@@ -1094,12 +1131,12 @@ FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex,
__storewordbytereverse( dword, dwordIndex<<2, base );
}
#else
FORCEINLINE unsigned long LoadLittleDWord( const unsigned long *base, unsigned int dwordIndex )
FORCEINLINE uint32 LoadLittleDWord( const uint32 *base, unsigned int dwordIndex )
{
return LittleDWord( base[dwordIndex] );
}
FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword )
FORCEINLINE void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
{
base[dwordIndex] = LittleDWord(dword);
}
@@ -1167,7 +1204,7 @@ PLATFORM_INTERFACE struct tm * Plat_localtime( const time_t *timep, struct tm *
inline uint64 Plat_Rdtsc()
{
#if defined( __arm__ ) && defined (POSIX)
#if (defined( __arm__ ) || defined( __aarch64__ )) && defined (POSIX)
struct timespec t;
clock_gettime( CLOCK_REALTIME, &t);
return t.tv_sec * 1000000000ULL + t.tv_nsec;
@@ -1479,7 +1516,7 @@ inline void ConstructThreeArg( T* pMemory, P1 const& arg1, P2 const& arg2, P3 co
template <class T>
inline T* CopyConstruct( T* pMemory, T const& src )
{
return reinterpret_cast<T*>(::new( pMemory ) T(src));
return ::new( pMemory ) T(src);
}
template <class T>
+7 -6
View File
@@ -144,14 +144,15 @@
#define timeGetTime timeGetTime__USE_VCR_MODE
#if defined( clock )
#undef clock
#endif
#define time time__USE_VCR_MODE
#endif
// MoeMod : breaks system header
//#define time time__USE_VCR_MODE
#if defined( recvfrom )
#undef recvfrom
#endif
#define recvfrom recvfrom__USE_VCR_MODE
//#if defined( recvfrom )
// #undef recvfrom
//#endif
//#define recvfrom recvfrom__USE_VCR_MODE
#if defined( GetCursorPos )
+1201 -396
View File
File diff suppressed because it is too large Load Diff
+653
View File
@@ -0,0 +1,653 @@
#ifndef THREADTOOLS_INL
#define THREADTOOLS_INL
// This file is included in threadtools.h for PS3 and threadtools.cpp for all other platforms
//
// Do not #include other files here
#ifndef _PS3
// this is defined in the .cpp for the PS3 to avoid introducing a dependency for files including the header
CTHREADLOCALPTR(CThread) g_pCurThread;
#define INLINE_ON_PS3
#else
// Inlining these functions on PS3 (which are called across PRX boundaries) saves us over 1ms per frame
#define INLINE_ON_PS3 inline
#endif
INLINE_ON_PS3 CThread::CThread() :
#ifdef _WIN32
m_hThread( NULL ),
m_threadId( 0 ),
#elif defined( _PS3 ) || defined(_POSIX)
m_threadId( 0 ),
m_threadZombieId( 0 ) ,
#endif
m_result( 0 ),
m_flags( 0 )
{
m_szName[0] = 0;
m_NotSuspendedEvent.Set();
}
//---------------------------------------------------------
INLINE_ON_PS3 CThread::~CThread()
{
#ifdef MSVC
if (m_hThread)
#elif defined(POSIX) && !defined( _PS3 )
if ( m_threadId )
#endif
{
if ( IsAlive() )
{
Msg( "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
#ifdef _WIN32
DoNewAssertDialog( __FILE__, __LINE__, "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
#endif
if ( GetCurrentCThread() == this )
{
Stop(); // BUGBUG: Alfred - this doesn't make sense, this destructor fires from the hosting thread not the thread itself!!
}
}
}
#if defined(POSIX) || defined( _PS3 )
if ( m_threadZombieId )
{
// just clean up zombie threads immediately (the destructor is fired from the hosting thread)
Join();
}
#endif
}
//---------------------------------------------------------
INLINE_ON_PS3 const char *CThread::GetName()
{
AUTO_LOCK( m_Lock );
if ( !m_szName[0] )
{
#if defined( _WIN32 )
_snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/%p)", this, m_hThread );
#elif defined( _PS3 )
snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p)", this );
#elif defined( POSIX )
_snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/0x%p)", this, (void*)m_threadId );
#endif
m_szName[sizeof(m_szName) - 1] = 0;
}
return m_szName;
}
//---------------------------------------------------------
INLINE_ON_PS3 void CThread::SetName(const char *pszName)
{
AUTO_LOCK( m_Lock );
strncpy( m_szName, pszName, sizeof(m_szName) - 1 );
m_szName[sizeof(m_szName) - 1] = 0;
}
//-----------------------------------------------------
// Functions for the other threads
//-----------------------------------------------------
// Start thread running - error if already running
INLINE_ON_PS3 bool CThread::Start( unsigned nBytesStack, ThreadPriorityEnum_t nPriority )
{
AUTO_LOCK( m_Lock );
if ( IsAlive() )
{
AssertMsg( 0, "Tried to create a thread that has already been created!" );
return false;
}
bool bInitSuccess = false;
CThreadEvent createComplete;
ThreadInit_t init = { this, &createComplete, &bInitSuccess };
#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
{
int iValidEntries = GetCallStack_Fast( init.ParentStackTrace, ARRAYSIZE( init.ParentStackTrace ), 0 );
for( int i = iValidEntries; i < ARRAYSIZE( init.ParentStackTrace ); ++i )
{
init.ParentStackTrace[i] = NULL;
}
}
#endif
#ifdef _WIN32
m_hThread = (HANDLE)CreateThread( NULL,
nBytesStack,
(LPTHREAD_START_ROUTINE)GetThreadProc(),
new ThreadInit_t(init),
nBytesStack ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0,
(LPDWORD)&m_threadId );
if( nPriority != TP_PRIORITY_DEFAULT )
{
SetThreadPriority( m_hThread, nPriority );
}
if ( !m_hThread )
{
AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
return false;
}
#elif PLATFORM_PS3
// On the PS3, a stack size of 0 doesn't imply a default stack size, so we need to force it to our
// own default size.
if ( nBytesStack == 0 )
{
nBytesStack = PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE;
}
//The thread is about to begin
m_threadEnd.Reset();
// sony documentation:
// "If the PPU thread is not joined by sys_ppu_thread_join() after exit,
// it should always be created as non-joinable (not specifying
// SYS_PPU_THREAD_CREATE_JOINABLE). Otherwise, some resources are left
// allocated after termination of the PPU thread as if memory leaks."
const char* threadName=m_szName;
if ( sys_ppu_thread_create( &m_threadId,
(void(*)(uint64_t))GetThreadProc(),
(uint64_t)(new ThreadInit_t( init )),
nPriority,
nBytesStack,
SYS_PPU_THREAD_CREATE_JOINABLE ,
threadName ) != CELL_OK )
{
AssertMsg1( 0, "Failed to create thread (error 0x%x)", errno );
return false;
}
bInitSuccess = true;
#elif POSIX
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setstacksize( &attr, MAX( nBytesStack, 1024u*1024 ) );
//lwss - fix memory leak here
m_threadInit = ThreadInit_t( init );
//if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), new ThreadInit_t( init ) ) != 0 )
if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), &m_threadInit ) != 0 )
//lwss end
{
AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
return false;
}
bInitSuccess = true;
#endif
if ( !WaitForCreateComplete( &createComplete ) )
{
Msg( "Thread failed to initialize\n" );
#ifdef _WIN32
CloseHandle( m_hThread );
m_hThread = NULL;
#elif defined( _PS3 )
m_threadEnd.Set();
m_threadId = NULL;
m_threadZombieId = 0;
#endif
return false;
}
if ( !bInitSuccess )
{
Msg( "Thread failed to initialize\n" );
#ifdef _WIN32
CloseHandle( m_hThread );
m_hThread = NULL;
#elif defined(POSIX) && !defined( _PS3 )
m_threadId = 0;
m_threadZombieId = 0;
#endif
return false;
}
#ifdef _WIN32
if ( !m_hThread )
{
Msg( "Thread exited immediately\n" );
}
#endif
#ifdef _WIN32
AddThreadHandleToIDMap( m_hThread, m_threadId );
return !!m_hThread;
#elif defined(POSIX)
return !!m_threadId;
#endif
}
//---------------------------------------------------------
//
// Return true if the thread has been created and hasn't yet exited
//
INLINE_ON_PS3 bool CThread::IsAlive()
{
#ifdef _WIN32
DWORD dwExitCode;
return (
m_hThread
&& GetExitCodeThread(m_hThread, &dwExitCode)
&& dwExitCode == STILL_ACTIVE );
#elif defined(POSIX)
return !!m_threadId;
#endif
}
// This method causes the current thread to wait until this thread
// is no longer alive.
INLINE_ON_PS3 bool CThread::Join( unsigned timeout )
{
#ifdef _WIN32
if ( m_hThread )
#elif defined(POSIX)
if ( m_threadId || m_threadZombieId )
#endif
{
AssertMsg(GetCurrentCThread() != this, _T("Thread cannot be joined with self"));
#ifdef _WIN32
return ThreadJoin( (ThreadHandle_t)m_hThread, timeout );
#elif defined(POSIX)
bool ret = ThreadJoin( (ThreadHandle_t)(m_threadId ? m_threadId : m_threadZombieId), timeout );
m_threadZombieId = 0;
return ret;
#endif
}
return true;
}
//---------------------------------------------------------
INLINE_ON_PS3 ThreadHandle_t CThread::GetThreadHandle()
{
#ifdef _WIN32
return (ThreadHandle_t)m_hThread;
#else
return (ThreadHandle_t)m_threadId;
#endif
}
//---------------------------------------------------------
INLINE_ON_PS3 int CThread::GetResult()
{
return m_result;
}
//-----------------------------------------------------
// Functions for both this, and maybe, and other threads
//-----------------------------------------------------
// Forcibly, abnormally, but relatively cleanly stop the thread
//
INLINE_ON_PS3 void CThread::Stop(int exitCode)
{
if ( !IsAlive() )
return;
if ( GetCurrentCThread() == this )
{
#if !defined( _PS3 )
m_result = exitCode;
if ( !( m_flags & SUPPORT_STOP_PROTOCOL ) )
{
OnExit();
g_pCurThread = NULL;
#ifdef _WIN32
CloseHandle( m_hThread );
RemoveThreadHandleToIDMap( m_hThread );
m_hThread = NULL;
#else
m_threadId = 0;
m_threadZombieId = 0;
#endif
}
else
{
throw exitCode;
}
#else
AssertMsg( false, "Called CThread::Stop() for a platform that doesn't have it!\n");
#endif
}
else
AssertMsg( 0, "Only thread can stop self: Use a higher-level protocol");
}
//---------------------------------------------------------
// Get the priority
INLINE_ON_PS3 int CThread::GetPriority() const
{
#ifdef _WIN32
return GetThreadPriority(m_hThread);
#elif defined( _PS3 )
return ThreadGetPriority( (ThreadHandle_t) m_threadId );
#elif defined(POSIX)
struct sched_param thread_param;
int policy;
pthread_getschedparam( m_threadId, &policy, &thread_param );
return thread_param.sched_priority;
#endif
}
//---------------------------------------------------------
// Set the priority
INLINE_ON_PS3 bool CThread::SetPriority(int priority)
{
#ifdef WIN32
return ThreadSetPriority( (ThreadHandle_t)m_hThread, priority );
#else
return ThreadSetPriority( (ThreadHandle_t)m_threadId, priority );
#endif
}
//---------------------------------------------------------
// Suspend a thread
INLINE_ON_PS3 unsigned CThread::Suspend()
{
AssertMsg( ThreadGetCurrentId() == (ThreadId_t)m_threadId, "Cannot call CThread::Suspend from outside thread" );
if ( ThreadGetCurrentId() != (ThreadId_t)m_threadId )
{
DebuggerBreakIfDebugging();
}
m_NotSuspendedEvent.Reset();
m_NotSuspendedEvent.Wait();
return 0;
}
//---------------------------------------------------------
INLINE_ON_PS3 unsigned CThread::Resume()
{
if ( m_NotSuspendedEvent.Check() )
{
DevWarning( "Called Resume() on a thread that is not suspended!\n" );
}
m_NotSuspendedEvent.Set();
return 0;
}
//---------------------------------------------------------
// Force hard-termination of thread. Used for critical failures.
INLINE_ON_PS3 bool CThread::Terminate(int exitCode)
{
#if defined( _X360 )
AssertMsg( 0, "Cannot terminate a thread on the Xbox!" );
return false;
#elif defined( _WIN32 )
// I hope you know what you're doing!
if (!TerminateThread(m_hThread, exitCode))
return false;
CloseHandle( m_hThread );
RemoveThreadHandleToIDMap( m_hThread );
m_hThread = NULL;
#elif defined( _PS3 )
m_threadEnd.Set();
m_threadId = NULL;
#elif defined(POSIX)
pthread_kill( m_threadId, SIGKILL );
m_threadId = 0;
#endif
return true;
}
//-----------------------------------------------------
// Global methods
//-----------------------------------------------------
// Get the Thread object that represents the current thread, if any.
// Can return NULL if the current thread was not created using
// CThread
//
INLINE_ON_PS3 CThread *CThread::GetCurrentCThread()
{
#ifdef _PS3
return GetCurThreadPS3();
#else
return g_pCurThread;
#endif
}
//---------------------------------------------------------
//
// Offer a context switch. Under Win32, equivalent to Sleep(0)
//
#ifdef Yield
#undef Yield
#endif
INLINE_ON_PS3 void CThread::Yield()
{
#ifdef _WIN32
::Sleep(0);
#elif defined( _PS3 )
// sys_ppu_thread_yield doesn't seem to function properly, so sleep instead.
sys_timer_usleep( 60 );
#elif defined(POSIX)
sched_yield();
#endif
}
//---------------------------------------------------------
//
// This method causes the current thread to yield and not to be
// scheduled for further execution until a certain amount of real
// time has elapsed, more or less. Duration is in milliseconds
INLINE_ON_PS3 void CThread::Sleep( unsigned duration )
{
#ifdef _WIN32
::Sleep(duration);
#elif defined (_PS3)
sys_timer_usleep( duration * 1000 );
#elif defined(POSIX)
usleep( duration * 1000 );
#endif
}
//---------------------------------------------------------
// Optional pre-run call, with ability to fail-create. Note Init()
// is forced synchronous with Start()
INLINE_ON_PS3 bool CThread::Init()
{
return true;
}
//---------------------------------------------------------
#if defined( _PS3 )
INLINE_ON_PS3 int CThread::Run()
{
return -1;
}
#endif // _PS3
// Called when the thread exits
INLINE_ON_PS3 void CThread::OnExit() { }
// Allow for custom start waiting
INLINE_ON_PS3 bool CThread::WaitForCreateComplete( CThreadEvent *pEvent )
{
// Force serialized thread creation...
if (!pEvent->Wait(60000))
{
AssertMsg( 0, "Probably deadlock or failure waiting for thread to initialize." );
return false;
}
return true;
}
INLINE_ON_PS3 bool CThread::IsThreadRunning()
{
#ifdef _PS3
// ThreadIsThreadIdRunning() doesn't work on PS3 if the thread is in a zombie state
return m_eventTheadExit.Check();
#else
return ThreadIsThreadIdRunning( (ThreadId_t)m_threadId );
#endif
}
//---------------------------------------------------------
INLINE_ON_PS3 CThread::ThreadProc_t CThread::GetThreadProc()
{
return ThreadProc;
}
INLINE_ON_PS3 void CThread::ThreadProcRunWithMinidumpHandler( void *pv )
{
ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
pInit->pThread->m_result = pInit->pThread->Run();
}
#ifdef _WIN32
unsigned long STDCALL CThread::ThreadProc(LPVOID pv)
#else
INLINE_ON_PS3 void* CThread::ThreadProc(LPVOID pv)
#endif
{
// #if defined( POSIX ) || defined( _PS3 )
ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
// #else
// std::auto_ptr<ThreadInit_t> pInit((ThreadInit_t *)pv);
// #endif
#ifdef _X360
// Make sure all threads are consistent w.r.t floating-point math
SetupFPUControlWord();
#endif
AllocateThreadID();
CThread *pThread = pInit->pThread;
#ifdef _PS3
SetCurThreadPS3( pThread );
#else
g_pCurThread = pThread;
#endif
pThread->m_pStackBase = AlignValue( &pThread, 4096 );
pInit->pThread->m_result = -1;
#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
CStackTop_ReferenceParentStack stackTop( pInit->ParentStackTrace, ARRAYSIZE( pInit->ParentStackTrace ) );
#endif
bool bInitSuccess = true;
if ( pInit->pfInitSuccess )
*(pInit->pfInitSuccess) = false;
#ifdef _PS3
*(pInit->pfInitSuccess) = pInit->pThread->Init();
#else
try
{
bInitSuccess = pInit->pThread->Init();
}
catch (...)
{
pInit->pInitCompleteEvent->Set();
throw;
}
#endif // _PS3
if ( pInit->pfInitSuccess )
*(pInit->pfInitSuccess) = bInitSuccess;
pInit->pInitCompleteEvent->Set();
if (!bInitSuccess)
return 0;
if ( !Plat_IsInDebugSession() && (pInit->pThread->m_flags & SUPPORT_STOP_PROTOCOL) )
{
#ifndef _PS3
try
#endif
{
pInit->pThread->m_result = pInit->pThread->Run();
}
#ifndef _PS3
catch (...)
{
}
#endif
}
else
{
#if defined( _WIN32 )
CatchAndWriteMiniDumpForVoidPtrFn( ThreadProcRunWithMinidumpHandler, pv, false );
#else
pInit->pThread->m_result = pInit->pThread->Run();
#endif
}
pInit->pThread->OnExit();
#ifdef _PS3
SetCurThreadPS3( NULL );
#else
g_pCurThread = NULL;
#endif
FreeThreadID();
AUTO_LOCK( pThread->m_Lock );
#ifdef _WIN32
CloseHandle( pThread->m_hThread );
RemoveThreadHandleToIDMap( pThread->m_hThread );
pThread->m_hThread = NULL;
#elif defined( _PS3 )
pThread->m_threadZombieId = pThread->m_threadId;
pThread->m_threadEnd.Set();
pThread->m_threadId = 0;
#elif defined(POSIX)
pThread->m_threadZombieId = pThread->m_threadId;
pThread->m_threadId = 0;
#else
#error
#endif
pThread->m_ExitEvent.Set();
#ifdef _PS3
{
pThread->m_Lock.Unlock();
sys_ppu_thread_exit( pInit->pThread->m_result );
// reacquire the lock in case thread exit didn't actually exit the thread, so that
// AUTO_LOCK won't double-unlock the lock (to keep it paired)
pThread->m_Lock.Lock();
}
#endif
#if defined( POSIX )|| defined( _PS3 )
return (void*)(uintp)pInit->pThread->m_result;
#else
return pInit->pThread->m_result;
#endif
}
#endif // THREADTOOLS_INL
+96 -73
View File
@@ -36,15 +36,38 @@
#if defined( PLATFORM_64BITS )
#if defined (PLATFORM_WINDOWS)
//typedef __m128i int128;
//inline int128 int128_zero() { return _mm_setzero_si128(); }
#else // PLATFORM_WINDOWS
typedef __int128_t int128;
#define int128_zero() 0
#endif// PLATFORM_WINDOWS
#define TSLIST_HEAD_ALIGNMENT 16
#define TSLIST_NODE_ALIGNMENT 16
#ifdef POSIX
inline bool ThreadInterlockedAssignIf128( int128 volatile * pDest, const int128 &value, const int128 &comparand )
{
// We do not want the original comparand modified by the swap
// so operate on a local copy.
int128 local_comparand = comparand;
return __sync_bool_compare_and_swap( pDest, local_comparand, value );
}
#endif
inline bool ThreadInterlockedAssignIf64x128( volatile int128 *pDest, const int128 &value, const int128 &comperand )
{ return ThreadInterlockedAssignIf128( pDest, value, comperand ); }
{
return ThreadInterlockedAssignIf128( pDest, value, comperand );
}
#else
#define TSLIST_HEAD_ALIGNMENT 8
#define TSLIST_NODE_ALIGNMENT 8
inline bool ThreadInterlockedAssignIf64x128( volatile int64 *pDest, const int64 value, const int64 comperand )
{ return ThreadInterlockedAssignIf64( pDest, value, comperand ); }
{
return ThreadInterlockedAssignIf64( pDest, value, comperand );
}
#endif
#ifdef _MSC_VER
@@ -99,13 +122,13 @@ union TSLIST_HEAD_ALIGN TSLHead_t
// because Sequence can be pretty much random. We could operate on both of them separately,
// but it could perhaps (?) lead to problems with store forwarding. I don't know 'cause I didn't
// performance-test or design original code, I'm just making it work on PowerPC.
#ifdef VALVE_BIG_ENDIAN
#ifdef VALVE_BIG_ENDIAN
int16 Sequence;
int16 Depth;
#else
#else
int16 Depth;
int16 Sequence;
#endif
#endif
#ifdef PLATFORM_64BITS
int32 Padding;
#endif
@@ -132,33 +155,33 @@ class CTSListBase
public:
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size )
static void * operator new(size_t size)
{
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
{
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
return pNode;
}
static void operator delete( void *p)
static void operator delete(void *p)
{
MemAlloc_FreeAligned( p );
}
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
{
MemAlloc_FreeAligned( p );
}
private:
// These ain't gonna work
static void * operator new[] ( size_t size );
static void operator delete [] ( void *p);
static void * operator new[]( size_t size );
static void operator delete[]( void *p );
public:
CTSListBase()
@@ -204,22 +227,22 @@ public:
TSLHead_t oldHead;
TSLHead_t newHead;
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
__lwsync(); // write-release barrier
#endif
#endif
#ifdef PLATFORM_64BITS
newHead.value.Padding = 0;
#endif
for (;;)
for ( ;; )
{
oldHead.value64x128 = m_Head.value64x128;
pNode->Next = oldHead.value.Next;
newHead.value.Next = pNode;
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence + 0x10001;
if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
{
break;
@@ -248,21 +271,21 @@ public:
#ifdef PLATFORM_64BITS
newHead.value.Padding = 0;
#endif
for (;;)
for ( ;; )
{
oldHead.value64x128 = m_Head.value64x128;
if ( !oldHead.value.Next )
return NULL;
newHead.value.Next = oldHead.value.Next->Next;
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
{
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
__lwsync(); // read-acquire barrier
#endif
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
__lwsync(); // read-acquire barrier
#endif
break;
}
ThreadPause();
@@ -301,7 +324,7 @@ public:
// I didn't construct this code. In any case, leaving it as is on big-endian
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence & 0xffff0000;
} while( !ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) );
} while ( !ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) );
return (TSLNodeBase_t *)oldHead.value.Next;
#endif
@@ -315,7 +338,7 @@ public:
int Count() const
{
#ifdef USE_NATIVE_SLIST
return QueryDepthSList( const_cast<TSLHead_t*>( &m_Head ) );
return QueryDepthSList( const_cast<TSLHead_t*>(&m_Head) );
#else
return m_Head.value.Depth;
#endif
@@ -349,7 +372,7 @@ public:
// similar to CTSSimpleList except that it allocates it's own pool objects
// and frees them on destruct. Also it does not overlay the TSNodeBase_t memory
// on T's memory
template< class T >
template< class T >
class TSLIST_HEAD_ALIGN CTSPool : public CTSListBase
{
// packs the node and the item (T) into a single struct and pools those
@@ -380,7 +403,7 @@ public:
void PutObject( T *pInfo )
{
char *pElem = (char *)pInfo;
pElem -= offsetof(simpleTSPoolStruct_t,elem);
pElem -= offsetof( simpleTSPoolStruct_t, elem );
simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)pElem;
CTSListBase::Push( pNode );
@@ -414,25 +437,25 @@ public:
Node_t( const T &init ) : elem( init ) {}
T elem;
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size )
{
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
static void * operator new(size_t size)
{
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, pFileName, nLine );
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_NODE_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
static void operator delete( void *p)
{
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
{
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_NODE_ALIGNMENT, pFileName, nLine );
return pNode;
}
static void operator delete(void *p)
{
MemAlloc_FreeAligned( p );
}
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
}
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
{
MemAlloc_FreeAligned( p );
}
@@ -476,7 +499,7 @@ public:
Push( new Node_t( init ) );
}
bool PopItem( T *pResult)
bool PopItem( T *pResult )
{
Node_t *pNode = Pop();
if ( !pNode )
@@ -564,7 +587,7 @@ public:
Push( pNode );
}
bool PopItem( T *pResult)
bool PopItem( T *pResult )
{
Node_t *pNode = Pop();
if ( !pNode )
@@ -608,37 +631,37 @@ class TSLIST_HEAD_ALIGN CTSQueue
public:
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size )
static void * operator new(size_t size)
{
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
{
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
return pNode;
}
static void operator delete( void *p)
static void operator delete(void *p)
{
MemAlloc_FreeAligned( p );
}
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
{
MemAlloc_FreeAligned( p );
}
private:
// These ain't gonna work
static void * operator new[] ( size_t size ) throw()
static void * operator new[]( size_t size ) throw()
{
return NULL;
}
static void operator delete [] ( void *p)
static void operator delete []( void *p )
{
}
@@ -647,24 +670,24 @@ public:
struct TSLIST_NODE_ALIGN Node_t
{
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size )
static void * operator new(size_t size)
{
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
{
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
return pNode;
}
static void operator delete( void *p)
static void operator delete(void *p)
{
MemAlloc_FreeAligned( p );
}
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
{
MemAlloc_FreeAligned( p );
}
@@ -679,13 +702,13 @@ public:
union TSLIST_HEAD_ALIGN NodeLink_t
{
// override new/delete so we can guarantee 8-byte aligned allocs
static void * operator new( size_t size )
static void * operator new(size_t size)
{
NodeLink_t *pNode = (NodeLink_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
NodeLink_t *pNode = (NodeLink_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
return pNode;
}
static void operator delete( void *p)
static void operator delete(void *p)
{
MemAlloc_FreeAligned( p );
}
@@ -740,12 +763,12 @@ public:
}
Node_t *pNode;
while ( ( pNode = Pop() ) != NULL )
while ( (pNode = Pop()) != NULL )
{
delete pNode;
}
while ( ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
while ( (pNode = (Node_t *)m_FreeNodes.Pop()) != NULL )
{
delete pNode;
}
@@ -765,7 +788,7 @@ public:
}
Node_t *pNode;
while ( ( pNode = Pop() ) != NULL )
while ( (pNode = Pop()) != NULL )
{
m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
}
@@ -846,7 +869,7 @@ public:
pNode->pNext = End();
for (;;)
for ( ;; )
{
oldTail.value.sequence = m_Tail.value.sequence;
oldTail.value.pNode = m_Tail.value.pNode;
@@ -870,7 +893,7 @@ public:
Node_t *Pop()
{
#define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
#define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
NodeLink_t * volatile pHead = &m_Head;
NodeLink_t * volatile pTail = &m_Tail;
Node_t * volatile * pHeadNode = &m_Head.value.pNode;
@@ -883,17 +906,17 @@ public:
intp tailSequence;
T elem;
for (;;)
for ( ;; )
{
head.value.sequence = *pHeadSequence; // must grab sequence first, which allows condition below to ensure pNext is valid
ThreadMemoryBarrier(); // need a barrier to prevent reordering of these assignments
head.value.pNode = *pHeadNode;
tailSequence = pTail->value.sequence;
pNext = head.value.pNode->pNext;
head.value.pNode = *pHeadNode;
tailSequence = pTail->value.sequence;
pNext = head.value.pNode->pNext;
// Checking pNext only to force optimizer to not reorder the assignment
// to pNext and the compare of the sequence
if ( !pNext || head.value.sequence != *pHeadSequence )
if ( !pNext || head.value.sequence != *pHeadSequence )
continue;
if ( bTestOptimizer )
@@ -916,7 +939,7 @@ public:
FinishPush( pNext, oldTail );
continue;
}
if ( pNext != End() )
{
elem = pNext->elem; // NOTE: next could be a freed node here, by design
@@ -991,7 +1014,7 @@ private:
NodeLink_t m_Tail;
CInterlockedInt m_Count;
CTSListBase m_FreeNodes;
} TSLIST_NODE_ALIGN_POST;
+1 -1
View File
@@ -190,7 +190,7 @@ typedef struct VCR_s
void *lpStartAddress,
void *lpParameter,
unsigned long dwCreationFlags,
unsigned long *lpThreadID );
uintp *lpThreadID );
unsigned long (*Hook_WaitForSingleObject)(
void *handle,
+1
View File
@@ -18,6 +18,7 @@
#if !( defined( _X360 ) && defined( _CERT ) )
#define VPROF_ENABLED
#endif
// TODO(nillerusr): make stubbed vprofile
#if defined(_X360) && defined(VPROF_ENABLED)
#include "tier0/pmc360.h"
+6
View File
@@ -19,6 +19,10 @@
#define tmBeginTimeSpanAt(...)
#define tmEndTimeSpanAt(...)
#define tmLeave(...)
#define TM_MESSAGE(...)
#define TM_ENTER(...)
#define TM_LEAVE(...)
#define TM_ZONE(...)
#define TM_ZONE_DEFAULT(...)
#define TM_ZONE_DEFAULT_PARAM(...)
#define TelemetryTick(...)
@@ -28,4 +32,6 @@
#define tmTryLock(...)
#define tmSetLockState(...)
typedef unsigned long long TmU64;
#endif // VPROF_TELEMETRY_H
+1 -1
View File
@@ -20,7 +20,7 @@
// Temporarily turn off Valve defines
#include "tier0/valve_off.h"
#if !defined(_WCHAR_T_DEFINED) && !defined(GNUC)
#if !defined(_WCHAR_T_DEFINED) && !defined( __WCHAR_TYPE__ ) && !defined(GNUC)
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif