the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1100 lines 29 kB view raw
1#include "stdafx.h" 2 3 4#include "C4JThread.h" 5#ifdef __PSVITA__ 6#include "..\Minecraft.Client\PSVita\PSVitaExtras\ShutdownManager.h" 7#include "..\Minecraft.Client\PSVita\PSVitaExtras\PSVitaTLSStorage.h" 8 9// AP - this comes from the low level user_malloc.c file used to overide the default memory functions. These must be called when a thread is started/stopped 10extern "C" { 11extern void user_registerthread(); 12extern void user_removethread(); 13} 14#else 15#include "..\Minecraft.Client\PS3\PS3Extras\ShutdownManager.h" 16 17#endif 18 19std::vector<C4JThread*> C4JThread::ms_threadList; 20CRITICAL_SECTION C4JThread::ms_threadListCS; 21 22#ifdef _XBOX_ONE 23 // 4J Stu - On XboxOne the main thread is not the one that does all the static init, so we have to set this up later 24C4JThread *C4JThread::m_mainThread = NULL; 25 26void C4JThread::StaticInit() 27{ 28 m_mainThread = new C4JThread("Main thread"); 29} 30#else 31C4JThread C4JThread::m_mainThread("Main thread"); 32#endif 33 34#ifdef __ORBIS__ 35__thread SceKernelCpumask C4JThread::m_oldAffinityMask; 36#endif 37 38 39#if __PSVITA__ 40static SceInt32 g_DefaultCPU; 41static SceInt32 g_DefaultPriority; 42#endif 43 44C4JThread::C4JThread( C4JThreadStartFunc* startFunc, void* param, const char* threadName, int stackSize/* = 0*/ ) 45{ 46 m_startFunc = startFunc; 47 m_threadParam = param; 48 m_stackSize = stackSize; 49 50 // to match XBox, if the stack size is zero, use the default 64k 51 if(m_stackSize == 0) 52 m_stackSize = 65536 * 2; 53 // make sure it's at least 16K 54 if(m_stackSize < 16384) 55 m_stackSize = 16384; 56 57#ifdef __PS3__ 58 sprintf(m_threadName, "(4J) %s", threadName ); 59#else 60 sprintf_s(m_threadName,64, "(4J) %s", threadName ); 61#endif 62 63 m_isRunning = false; 64 m_hasStarted = false; 65 66 m_exitCode = STILL_ACTIVE; 67 68#ifdef __PS3__ 69 m_completionFlag = new Event(Event::e_modeManualClear); 70 m_threadID = 0; 71 m_lastSleepTime = 0; 72 m_priority = 1002; // main thread has priority 1001 73#elif defined __ORBIS__ 74 m_completionFlag = new Event(Event::e_modeManualClear); 75 m_threadID = 0; 76 m_lastSleepTime = 0; 77 scePthreadAttrInit(&m_threadAttr); 78 int err = scePthreadAttrSetaffinity(&m_threadAttr, 63); // set the thread affinity to all cores to start with 79 assert(err == SCE_OK); 80 m_oldAffinityMask = 0; 81 m_priority = SCE_KERNEL_PRIO_FIFO_DEFAULT; 82#elif defined __PSVITA__ 83 m_completionFlag = new Event(Event::e_modeManualClear); 84 m_threadID = 0; 85 m_lastSleepTime = 0; 86 m_priority = g_DefaultPriority; 87 //m_CPUMask = SCE_KERNEL_CPU_MASK_USER_ALL; 88 89 // AP - I had trouble getting the cpu to change once the thread was created so I've hard coded them here 90 // The main work division is... 91 // 0 - Main 92 // 1 - Chunk/Tile Update 93 // 2 - Server/Audio 94 // These three can sometimes consume ALL the CPU time so they are set to below average priority so as not to block other critical threads 95 int CPU = SCE_KERNEL_CPU_MASK_USER_ALL; 96 if( !strcmp(threadName, "Chunk update") ) 97 { 98 CPU = SCE_KERNEL_CPU_MASK_USER_2; 99 m_priority = g_DefaultPriority + 1; 100 } 101 if( !strcmp(threadName, "Server" ) ) 102 { 103 CPU = SCE_KERNEL_CPU_MASK_USER_1; 104 m_priority = g_DefaultPriority + 1; 105 } 106 // make sure Tile Update doesn't go on cpu 0 because it will hold up the main thread. And it can't go on cpu 1 because Chunk Update crashes. 107 if( !strcmp(threadName, "Tile update") ) 108 { 109 CPU = SCE_KERNEL_CPU_MASK_USER_1; 110 } 111 112 m_threadID = sceKernelCreateThread(m_threadName, entryPoint, g_DefaultPriority, m_stackSize, 0, CPU, NULL); 113 app.DebugPrintf("***************************** start thread %s **************************\n", m_threadName); 114#else 115 m_threadID = 0; 116 m_threadHandle = 0; 117 m_threadHandle = CreateThread(NULL, m_stackSize, entryPoint, this, CREATE_SUSPENDED, &m_threadID); 118#endif 119 EnterCriticalSection(&ms_threadListCS); 120 ms_threadList.push_back(this); 121 LeaveCriticalSection(&ms_threadListCS); 122} 123 124// only used for the main thread 125C4JThread::C4JThread( const char* mainThreadName) 126{ 127#ifdef __PSVITA__ 128 user_registerthread(); 129#endif 130 131 m_startFunc = NULL; 132 m_threadParam = NULL; 133 m_stackSize = 0; 134 135#ifdef __PS3__ 136 sprintf(m_threadName, "(4J) %s", mainThreadName); 137#else 138 sprintf_s(m_threadName, 64, "(4J) %s", mainThreadName); 139#endif 140 m_isRunning = true; 141 m_hasStarted = true; 142 m_lastSleepTime = System::currentTimeMillis(); 143 144 // should be the first thread to be created, so init the static critical section for the threadlist here 145 InitializeCriticalSection(&ms_threadListCS); 146 147 148#ifdef __PS3__ 149 m_completionFlag = new Event(Event::e_modeManualClear); 150 sys_ppu_thread_get_id(&m_threadID); 151#elif defined __ORBIS__ 152 m_completionFlag = new Event(Event::e_modeManualClear); 153 m_threadID = scePthreadSelf(); 154 m_priority = SCE_KERNEL_PRIO_FIFO_DEFAULT; 155#elif defined __PSVITA__ 156 m_completionFlag = new Event(Event::e_modeManualClear); 157 g_DefaultPriority = sceKernelGetThreadCurrentPriority(); 158 m_threadID = sceKernelGetThreadId(); 159 int err = sceKernelChangeThreadCpuAffinityMask(m_threadID, SCE_KERNEL_CPU_MASK_USER_0); 160// sceKernelChangeThreadPriority(m_threadID, g_DefaultPriority + 1); 161 g_DefaultCPU = SCE_KERNEL_CPU_MASK_USER_ALL;//sceKernelGetThreadCpuAffinityMask(m_threadID); 162#else 163 m_threadID = GetCurrentThreadId(); 164 m_threadHandle = GetCurrentThread(); 165#endif 166#ifdef _XBOX_ONE 167 SetThreadName(-1, m_threadName); 168#endif 169 EnterCriticalSection(&ms_threadListCS); 170 ms_threadList.push_back(this); 171 LeaveCriticalSection(&ms_threadListCS); 172} 173 174C4JThread::~C4JThread() 175{ 176#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ 177 delete m_completionFlag; 178#endif 179 180#if defined __ORBIS__ 181 scePthreadJoin(m_threadID, NULL); 182#endif 183 184 EnterCriticalSection(&ms_threadListCS); 185 186 for( AUTO_VAR(it,ms_threadList.begin()); it != ms_threadList.end(); it++ ) 187 { 188 if( (*it) == this ) 189 { 190 ms_threadList.erase(it); 191 LeaveCriticalSection(&ms_threadListCS); 192 return; 193 } 194 } 195 196 LeaveCriticalSection(&ms_threadListCS); 197} 198 199#ifdef __PS3__ 200void C4JThread::entryPoint(uint64_t param) 201{ 202 C4JThread* pThread = (C4JThread*)param; 203 pThread->m_exitCode = (*pThread->m_startFunc)(pThread->m_threadParam); 204 pThread->m_completionFlag->Set(); 205 pThread->m_isRunning = false; 206 sys_ppu_thread_exit(0); 207} 208#elif defined __ORBIS__ 209void * C4JThread::entryPoint(void *param) 210{ 211 C4JThread* pThread = (C4JThread*)param; 212 pThread->m_exitCode = (*pThread->m_startFunc)(pThread->m_threadParam); 213 pThread->m_completionFlag->Set(); 214 pThread->m_isRunning = false; 215 scePthreadExit(NULL); 216} 217#elif defined __PSVITA__ 218struct StrArg { 219 C4JThread* Thread; 220}; 221 222SceInt32 C4JThread::entryPoint(SceSize argSize, void *pArgBlock) 223{ 224 StrArg *strArg = (StrArg*)pArgBlock; 225 C4JThread* pThread = strArg->Thread; 226 user_registerthread(); 227 pThread->m_exitCode = (*pThread->m_startFunc)(pThread->m_threadParam); 228 app.DebugPrintf("***************************** thread exit %s **************************\n", pThread->m_threadName); 229 pThread->m_completionFlag->Set(); 230 pThread->m_isRunning = false; 231 232 // AP - make sure we clean up this thread's storage and memory 233 PSVitaTLSStorage::RemoveThread(pThread->m_threadID); 234 user_removethread(); 235 236 sceKernelExitDeleteThread(NULL); 237 238 return pThread->m_exitCode; 239} 240#else 241DWORD WINAPI C4JThread::entryPoint(LPVOID lpParam) 242{ 243 C4JThread* pThread = (C4JThread*)lpParam; 244 SetThreadName(-1, pThread->m_threadName); 245 pThread->m_exitCode = (*pThread->m_startFunc)(pThread->m_threadParam); 246 pThread->m_isRunning = false; 247 return pThread->m_exitCode; 248} 249#endif 250 251 252 253 254void C4JThread::Run() 255{ 256#ifdef __PS3__ 257 // prio specifies the priority value of the PPU thread within the range from 0 to 3071 where 0 is the highest. 258 // One of the following values is set to flags: 259 // 0 - non-joinable non-interrupt thread 260 // SYS_PPU_THREAD_CREATE_JOINABLE - Create a joinable thread 261 // SYS_PPU_THREAD_CREATE_INTERRUPT - Create an interrupt thread 262 uint64_t flags = 0; 263 int err = sys_ppu_thread_create(&m_threadID, entryPoint, (uint64_t)this, m_priority, m_stackSize, flags, m_threadName); 264#elif defined __ORBIS__ 265 scePthreadAttrSetstacksize(&m_threadAttr, m_stackSize); 266 scePthreadAttrSetguardsize(&m_threadAttr, 1024); 267 int ret = scePthreadCreate(&m_threadID, &m_threadAttr, entryPoint, this, m_threadName); 268 assert( ret == SCE_OK ); 269 scePthreadSetprio(m_threadID,m_priority); 270 scePthreadAttrDestroy(&m_threadAttr); 271#elif defined __PSVITA__ 272 StrArg strArg = {this}; 273// m_threadID = sceKernelCreateThread(m_threadName, entryPoint, m_priority, m_stackSize, 0, m_CPUMask, NULL); 274 sceKernelStartThread( m_threadID, sizeof(strArg), &strArg); 275#else 276 ResumeThread(m_threadHandle); 277#endif 278 m_lastSleepTime = System::currentTimeMillis(); 279 m_isRunning = true; 280 m_hasStarted = true; 281} 282 283void C4JThread::SetProcessor( int proc ) 284{ 285#ifdef __PS3__ 286 // does nothing since we only have the 1 processor 287#elif defined __ORBIS__ 288 scePthreadAttrSetaffinity(&m_threadAttr, 1 << proc); 289#elif defined __PSVITA__ 290 int Proc = proc >> 1; // convert from 360's 3 cores * 2 hardware threads to Vita's 3 cores 291 int Mask = SCE_KERNEL_CPU_MASK_USER_0 << Proc; 292 //m_CPUMask = Mask; 293// int err = sceKernelChangeThreadCpuAffinityMask(m_threadID, Mask); 294 int Newmask = sceKernelGetThreadCpuAffinityMask(m_threadID); 295 app.DebugPrintf("***************************** set thread proc %s %d %d %d **************************\n", m_threadName, proc, Mask, Newmask); 296#elif defined _DURANGO 297 SetThreadAffinityMask(m_threadHandle, 1 << proc ); 298#else 299 XSetThreadProcessor( m_threadHandle, proc); 300#endif 301} 302 303void C4JThread::SetPriority( int priority ) 304{ 305#ifdef __PS3__ 306 switch(priority) 307 { 308 case THREAD_PRIORITY_LOWEST: m_priority = 1003; break; 309 case THREAD_PRIORITY_BELOW_NORMAL: m_priority = 1002; break; 310 case THREAD_PRIORITY_NORMAL: m_priority = 1001; break; // same as main thread 311 case THREAD_PRIORITY_ABOVE_NORMAL: m_priority = 1000; break; 312 case THREAD_PRIORITY_HIGHEST: m_priority = 999; break; 313 } 314 if(m_threadID != 0) 315 sys_ppu_thread_set_priority(m_threadID, m_priority); 316 //int erro = sys_ppu_thread_set_priority(m_threadID, priority); 317#elif defined __ORBIS__ 318 319 switch(priority) 320 { 321 case THREAD_PRIORITY_LOWEST: m_priority = SCE_KERNEL_PRIO_FIFO_LOWEST; break; 322 case THREAD_PRIORITY_BELOW_NORMAL: m_priority = SCE_KERNEL_PRIO_FIFO_LOWEST + ((SCE_KERNEL_PRIO_FIFO_DEFAULT-SCE_KERNEL_PRIO_FIFO_LOWEST)/2); break; 323 case THREAD_PRIORITY_NORMAL: m_priority = SCE_KERNEL_PRIO_FIFO_DEFAULT; break; // same as main thread 324 case THREAD_PRIORITY_ABOVE_NORMAL: m_priority = SCE_KERNEL_PRIO_FIFO_DEFAULT + ((SCE_KERNEL_PRIO_FIFO_HIGHEST-SCE_KERNEL_PRIO_FIFO_DEFAULT)/2); break; 325 case THREAD_PRIORITY_HIGHEST: m_priority = SCE_KERNEL_PRIO_FIFO_HIGHEST; break; 326 } 327 328 if( m_threadID != 0 ) 329 { 330 scePthreadSetprio(m_threadID,m_priority); 331 } 332#elif defined __PSVITA__ 333 int Mid = g_DefaultPriority;//(SCE_KERNEL_LOWEST_PRIORITY_USER + SCE_KERNEL_HIGHEST_PRIORITY_USER) / 2; 334 switch(priority) 335 { 336 case THREAD_PRIORITY_LOWEST: 337 m_priority = SCE_KERNEL_LOWEST_PRIORITY_USER; 338 break; 339 case THREAD_PRIORITY_BELOW_NORMAL: 340 m_priority = Mid + 1; 341 break; 342 case THREAD_PRIORITY_NORMAL: 343 m_priority = Mid; 344 break; // same as main thread 345 case THREAD_PRIORITY_ABOVE_NORMAL: 346 m_priority = Mid - 1; 347 break; 348 case THREAD_PRIORITY_HIGHEST: 349 m_priority = SCE_KERNEL_HIGHEST_PRIORITY_USER; 350 break; 351 } 352 353// sceKernelChangeThreadPriority(m_threadID, m_priority); 354 app.DebugPrintf("***************************** set thread prio %s %d %d **************************\n", m_threadName, priority, m_priority); 355#else 356 SetThreadPriority(m_threadHandle, priority); 357#endif // __PS3__ 358} 359 360DWORD C4JThread::WaitForCompletion( int timeoutMs ) 361{ 362#ifdef __PS3__ 363 if(timeoutMs == INFINITE) 364 timeoutMs = SYS_NO_TIMEOUT ; 365 return m_completionFlag->WaitForSignal(timeoutMs); 366#elif defined __ORBIS__ 367 return m_completionFlag->WaitForSignal( timeoutMs ); 368#elif defined __PSVITA__ 369 return m_completionFlag->WaitForSignal( timeoutMs ); 370/* SceUInt32 Timeout = timeoutMs * 1000; 371 SceInt32 err = sceKernelWaitThreadEnd(m_threadID, &m_exitCode, &Timeout); 372 if( err == 0 ) 373 { 374 return m_exitCode; 375 } 376 else 377 { 378 if( err == SCE_KERNEL_ERROR_WAIT_TIMEOUT ) 379 { 380 return WAIT_TIMEOUT; 381 } 382 else 383 { 384 // AP - not sure what to do here 385 return 0; 386 } 387 }*/ 388 389// return m_exitCode; 390#else 391 return WaitForSingleObject(m_threadHandle, timeoutMs); 392#endif // __PS3__ 393} 394 395int C4JThread::GetExitCode() 396{ 397#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ 398 return m_exitCode; 399#else 400 DWORD exitcode = 0; 401 GetExitCodeThread(m_threadHandle, &exitcode); 402 403 return *((int *)&exitcode); 404#endif 405} 406 407void C4JThread::Sleep( int millisecs ) 408{ 409#ifdef __PS3__ 410 if(millisecs == 0) 411 { 412 // https://ps3.scedev.net/forums/thread/116470/ 413 // "sys_timer_usleep(0) does not yield the CPU." 414 sys_ppu_thread_yield(); 415 } 416 else 417 sys_timer_usleep(millisecs * 1000); 418#elif defined __ORBIS__ 419 sceKernelUsleep(((SceKernelUseconds)millisecs) * 1000); 420#elif defined __PSVITA__ 421 // 4J Stu - 0 is an error, so add a tiny sleep when we just want to yield 422 sceKernelDelayThread(millisecs * 1000 + 1); 423#else 424 ::Sleep(millisecs); 425#endif // __PS3__ 426} 427 428C4JThread* C4JThread::getCurrentThread() 429{ 430#ifdef __PS3__ 431 sys_ppu_thread_t currThreadID; 432 sys_ppu_thread_get_id(&currThreadID); 433#elif defined __ORBIS__ 434 ScePthread currThreadID = scePthreadSelf(); 435#elif defined __PSVITA__ 436 SceUID currThreadID = sceKernelGetThreadId(); 437#else 438 DWORD currThreadID = GetCurrentThreadId(); 439#endif //__PS3__ 440 EnterCriticalSection(&ms_threadListCS); 441 442 for(int i=0;i<ms_threadList.size(); i++) 443 { 444 if(currThreadID == ms_threadList[i]->m_threadID) 445 { 446 LeaveCriticalSection(&ms_threadListCS); 447 return ms_threadList[i]; 448 } 449 } 450 451 LeaveCriticalSection(&ms_threadListCS); 452 453 return NULL; 454} 455 456bool C4JThread::isMainThread() 457{ 458#ifdef _XBOX_ONE 459 return getCurrentThread() == m_mainThread; 460#else 461 return getCurrentThread() == &m_mainThread; 462#endif 463} 464 465C4JThread::Event::Event(EMode mode/* = e_modeAutoClear*/) 466{ 467 m_mode = mode; 468#ifdef __PS3__ 469 sys_event_flag_attribute_t attr; 470 // default values taken from sys_event_flag_attribute_initialize 471 attr.attr_protocol = SYS_SYNC_PRIORITY; 472 attr.attr_pshared = SYS_SYNC_NOT_PROCESS_SHARED; 473 attr.key = 0; 474 attr.flags = 0; 475 attr.type = SYS_SYNC_WAITER_SINGLE; 476 attr.name[0] = '\0'; 477 sys_event_flag_attribute_initialize(attr); 478 479 int err = sys_event_flag_create(&m_event, &attr, 0); 480 481#elif defined __ORBIS__ 482 char name[1] = {0}; 483 sceKernelCreateEventFlag( &m_event, name, SCE_KERNEL_EVF_ATTR_TH_FIFO | SCE_KERNEL_EVF_ATTR_MULTI, 0, NULL); 484#elif defined __PSVITA__ 485 char name[1] = {0}; 486 m_event = sceKernelCreateEventFlag( name, SCE_KERNEL_EVF_ATTR_TH_FIFO | SCE_KERNEL_EVF_ATTR_MULTI, 0, NULL); 487#else 488 m_event = CreateEvent( NULL, (m_mode == e_modeManualClear), FALSE, NULL ); 489#endif //__PS3__ 490} 491 492 493C4JThread::Event::~Event() 494{ 495#ifdef __PS3__ 496 sys_event_flag_destroy(m_event); 497#elif defined __ORBIS__ 498 sceKernelDeleteEventFlag(m_event); 499#elif defined __PSVITA__ 500 sceKernelDeleteEventFlag(m_event); 501#else 502 CloseHandle( m_event ); 503#endif // __PS3__ 504} 505 506 507void C4JThread::Event::Set() 508{ 509#ifdef __PS3__ 510 int err =sys_event_flag_set(m_event, 1); 511#elif defined __ORBIS__ 512 sceKernelSetEventFlag(m_event, 1); 513#elif defined __PSVITA__ 514 sceKernelSetEventFlag(m_event, 1); 515#else 516 SetEvent(m_event); 517#endif //__PS3__ 518} 519 520void C4JThread::Event::Clear() 521{ 522#ifdef __PS3__ 523 int err =sys_event_flag_clear(m_event, ~(1)); 524#elif defined __ORBIS__ 525 sceKernelClearEventFlag(m_event, ~(1)); 526#elif defined __PSVITA__ 527 sceKernelClearEventFlag(m_event, ~1); 528#else 529 ResetEvent(m_event); 530#endif //__PS3__ 531} 532 533DWORD C4JThread::Event::WaitForSignal( int timeoutMs ) 534{ 535#ifdef __PS3__ 536 if(timeoutMs == INFINITE) 537 timeoutMs = SYS_NO_TIMEOUT ; 538 int timoutMicrosecs = timeoutMs * 1000; 539 uint32_t mode = SYS_EVENT_FLAG_WAIT_AND; 540 if(m_mode == e_modeAutoClear) 541 mode |= SYS_EVENT_FLAG_WAIT_CLEAR; 542 int err = sys_event_flag_wait(m_event, 1, mode, 0, timoutMicrosecs); 543 544 switch(err) 545 { 546 case CELL_OK: return WAIT_OBJECT_0; 547 case ETIMEDOUT: return WAIT_TIMEOUT; 548 case ECANCELED: return WAIT_ABANDONED; 549 default: return WAIT_FAILED; 550 } 551 552#elif defined __ORBIS__ 553 SceKernelUseconds timeoutMicrosecs; 554 SceKernelUseconds *pTimeoutMicrosecs; 555 if( timeoutMs == INFINITE ) 556 { 557 pTimeoutMicrosecs = NULL; 558 } 559 else 560 { 561 timeoutMicrosecs = ((SceKernelUseconds)timeoutMs) * 1000; 562 pTimeoutMicrosecs = &timeoutMicrosecs; 563 } 564 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 565 if(m_mode == e_modeAutoClear) 566 { 567 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT; 568 } 569 int err = sceKernelWaitEventFlag(m_event, 1, waitMode, NULL, pTimeoutMicrosecs); 570 switch(err) 571 { 572 case SCE_OK: return WAIT_OBJECT_0; 573 case SCE_KERNEL_ERROR_ETIMEDOUT: return WAIT_TIMEOUT; 574 case SCE_KERNEL_ERROR_ECANCELED: return WAIT_ABANDONED; 575 default: return WAIT_FAILED; 576 } 577#elif defined __PSVITA__ 578 SceUInt32 timeoutMicrosecs; 579 SceUInt32 *pTimeoutMicrosecs; 580 if( timeoutMs == INFINITE ) 581 { 582 pTimeoutMicrosecs = NULL; 583 } 584 else 585 { 586 timeoutMicrosecs = ((SceInt32)timeoutMs) * 1000; 587 pTimeoutMicrosecs = &timeoutMicrosecs; 588 } 589 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 590 if(m_mode == e_modeAutoClear) 591 { 592 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL; 593 } 594 int err = sceKernelWaitEventFlag(m_event, 1, waitMode, NULL, pTimeoutMicrosecs); 595 switch(err) 596 { 597 case SCE_OK: return WAIT_OBJECT_0; 598 case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return WAIT_TIMEOUT; 599 case SCE_KERNEL_ERROR_WAIT_CANCEL: return WAIT_ABANDONED; 600 default: return WAIT_FAILED; 601 } 602#else 603 return WaitForSingleObject(m_event, timeoutMs); 604#endif // __PS3__ 605} 606 607C4JThread::EventArray::EventArray( int size, EMode mode/* = e_modeAutoClear*/) 608{ 609 assert(size<32); 610 m_size = size; 611 m_mode = mode; 612#ifdef __PS3__ 613 sys_event_flag_attribute_t attr; 614 // default values taken from sys_event_flag_attribute_initialize 615 attr.attr_protocol = SYS_SYNC_PRIORITY; 616 attr.attr_pshared = SYS_SYNC_NOT_PROCESS_SHARED; 617 attr.key = 0; 618 attr.flags = 0; 619 attr.type = SYS_SYNC_WAITER_SINGLE; 620 attr.name[0] = '\0'; 621 sys_event_flag_attribute_initialize(attr); 622 int err = sys_event_flag_create(&m_events, &attr, 0); 623 assert(err == CELL_OK); 624#elif defined __ORBIS__ 625 char name[1] = {0}; 626 sceKernelCreateEventFlag( &m_events, name, SCE_KERNEL_EVF_ATTR_TH_FIFO | SCE_KERNEL_EVF_ATTR_MULTI, 0, NULL); 627#elif defined __PSVITA__ 628 char name[1] = {0}; 629 m_events = sceKernelCreateEventFlag( name, SCE_KERNEL_EVF_ATTR_TH_FIFO | SCE_KERNEL_EVF_ATTR_MULTI, 0, NULL); 630#else 631 m_events = new HANDLE[size]; 632 for(int i=0;i<size;i++) 633 { 634 m_events[i] = CreateEvent(NULL, (m_mode == e_modeManualClear), FALSE, NULL ); 635 } 636#endif // __PS3__ 637} 638 639 640void C4JThread::EventArray::Set(int index) 641{ 642#ifdef __PS3__ 643 int err =sys_event_flag_set(m_events, 1<<index); 644 assert(err == CELL_OK); 645#elif defined __ORBIS__ 646 sceKernelSetEventFlag(m_events, 1<<index); 647#elif defined __PSVITA__ 648 sceKernelSetEventFlag(m_events, 1<<index); 649#else 650 SetEvent(m_events[index]); 651#endif //__PS3__ 652} 653 654void C4JThread::EventArray::Clear(int index) 655{ 656#ifdef __PS3__ 657 int err =sys_event_flag_clear(m_events, ~(1<<index)); 658 assert(err == CELL_OK); 659#elif defined __ORBIS__ 660 sceKernelClearEventFlag(m_events, ~(1<<index)); 661#elif defined __PSVITA__ 662 sceKernelClearEventFlag(m_events, ~(1<<index)); 663#else 664 ResetEvent(m_events[index]); 665#endif //__PS3__ 666} 667 668void C4JThread::EventArray::SetAll() 669{ 670 for(int i=0;i<m_size;i++) 671 Set(i); 672} 673 674void C4JThread::EventArray::ClearAll() 675{ 676 for(int i=0;i<m_size;i++) 677 Clear(i); 678} 679 680DWORD C4JThread::EventArray::WaitForSingle(int index, int timeoutMs ) 681{ 682 DWORD retVal; 683#ifdef __PS3__ 684 int timeoutMicrosecs; 685 if(timeoutMs == INFINITE) 686 timeoutMicrosecs = SYS_NO_TIMEOUT; 687 else 688 timeoutMicrosecs = timeoutMs * 1000; 689 uint32_t mode = SYS_EVENT_FLAG_WAIT_AND; 690 if(m_mode == e_modeAutoClear) 691 mode |= SYS_EVENT_FLAG_WAIT_CLEAR; 692 693 int err = sys_event_flag_wait(m_events, 1<<index, mode, 0, timeoutMicrosecs); 694 695 switch(err) 696 { 697 case CELL_OK: 698 retVal = WAIT_OBJECT_0; 699 break; 700 case ETIMEDOUT: 701 retVal = WAIT_TIMEOUT; 702 break; 703 case ECANCELED: 704 retVal = WAIT_ABANDONED; 705 break; 706 default: 707 assert(0); 708 retVal = WAIT_FAILED; 709 break; 710 } 711#elif defined __ORBIS__ 712 SceKernelUseconds timeoutMicrosecs; 713 SceKernelUseconds *pTimeoutMicrosecs; 714 if( timeoutMs == INFINITE ) 715 { 716 pTimeoutMicrosecs = NULL; 717 } 718 else 719 { 720 timeoutMicrosecs = ((SceKernelUseconds)timeoutMs) * 1000; 721 pTimeoutMicrosecs = &timeoutMicrosecs; 722 } 723 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 724 if(m_mode == e_modeAutoClear) 725 { 726 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT; 727 } 728 uint64_t resultPat; 729 int err = sceKernelWaitEventFlag(m_events, 1<<index, waitMode, &resultPat, pTimeoutMicrosecs); 730 assert(err != SCE_KERNEL_ERROR_ETIMEDOUT); 731 switch(err) 732 { 733 case SCE_OK: 734 retVal = WAIT_OBJECT_0; 735 break; 736 case SCE_KERNEL_ERROR_ETIMEDOUT: 737 retVal = WAIT_TIMEOUT; 738 break; 739 case SCE_KERNEL_ERROR_ECANCELED: 740 retVal = WAIT_ABANDONED; 741 break; 742 default: 743 retVal = WAIT_FAILED; 744 break; 745 } 746#elif defined __PSVITA__ 747 SceUInt32 timeoutMicrosecs; 748 SceUInt32 *pTimeoutMicrosecs; 749 if( timeoutMs == INFINITE ) 750 { 751 pTimeoutMicrosecs = NULL; 752 } 753 else 754 { 755 timeoutMicrosecs = ((SceUInt32)timeoutMs) * 1000; 756 pTimeoutMicrosecs = &timeoutMicrosecs; 757 } 758 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 759 if(m_mode == e_modeAutoClear) 760 { 761 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL; 762 } 763 int err = sceKernelWaitEventFlag(m_events, 1<<index, waitMode, NULL, pTimeoutMicrosecs); 764 switch(err) 765 { 766 case SCE_OK: return WAIT_OBJECT_0; 767 case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return WAIT_TIMEOUT; 768 case SCE_KERNEL_ERROR_WAIT_CANCEL: return WAIT_ABANDONED; 769 default: return WAIT_FAILED; 770 } 771#else 772 retVal = WaitForSingleObject(m_events[index], timeoutMs); 773#endif // __PS3__ 774 775 return retVal; 776} 777 778DWORD C4JThread::EventArray::WaitForAll(int timeoutMs ) 779{ 780 DWORD retVal; 781#ifdef __PS3__ 782 if(timeoutMs == INFINITE) 783 timeoutMs = SYS_NO_TIMEOUT ; 784 int timoutMicrosecs = timeoutMs * 1000; 785 unsigned int bitmask = 0; 786 for(int i=0;i<m_size;i++) 787 bitmask |= (1<<i); 788 789 uint32_t mode = SYS_EVENT_FLAG_WAIT_AND; 790 if(m_mode == e_modeAutoClear) 791 mode |= SYS_EVENT_FLAG_WAIT_CLEAR; 792 793 int err = sys_event_flag_wait(m_events, bitmask, mode, 0, timoutMicrosecs); 794 795 switch(err) 796 { 797 case CELL_OK: 798 retVal = WAIT_OBJECT_0; 799 break; 800 case ETIMEDOUT: 801 retVal = WAIT_TIMEOUT; 802 break; 803 case ECANCELED: 804 retVal = WAIT_ABANDONED; 805 break; 806 default: 807 assert(0); 808 retVal = WAIT_FAILED; 809 break; 810 } 811 812#elif defined __ORBIS__ 813 SceKernelUseconds timeoutMicrosecs; 814 SceKernelUseconds *pTimeoutMicrosecs; 815 if( timeoutMs == INFINITE ) 816 { 817 pTimeoutMicrosecs = NULL; 818 } 819 else 820 { 821 timeoutMicrosecs = ((SceKernelUseconds)timeoutMs) * 1000; 822 pTimeoutMicrosecs = &timeoutMicrosecs; 823 } 824 unsigned int bitmask = 0; 825 for(int i=0;i<m_size;i++) 826 bitmask |= (1<<i); 827 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 828 if(m_mode == e_modeAutoClear) 829 { 830 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT; 831 } 832 int err = sceKernelWaitEventFlag(m_events, bitmask, waitMode, NULL, pTimeoutMicrosecs); 833 switch(err) 834 { 835 case SCE_OK: 836 retVal = WAIT_OBJECT_0; 837 break; 838 case SCE_KERNEL_ERROR_ETIMEDOUT: 839 retVal = WAIT_TIMEOUT; 840 break; 841 case SCE_KERNEL_ERROR_ECANCELED: 842 retVal = WAIT_ABANDONED; 843 break; 844 default: 845 retVal = WAIT_FAILED; 846 break; 847 } 848#elif defined __PSVITA__ 849 SceUInt32 timeoutMicrosecs; 850 SceUInt32 *pTimeoutMicrosecs; 851 if( timeoutMs == INFINITE ) 852 { 853 pTimeoutMicrosecs = NULL; 854 } 855 else 856 { 857 timeoutMicrosecs = ((SceUInt32)timeoutMs) * 1000; 858 pTimeoutMicrosecs = &timeoutMicrosecs; 859 } 860 unsigned int bitmask = 0; 861 for(int i=0;i<m_size;i++) 862 bitmask |= (1<<i); 863 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_AND; 864 if(m_mode == e_modeAutoClear) 865 { 866 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL; 867 } 868 int err = sceKernelWaitEventFlag(m_events, bitmask, waitMode, NULL, pTimeoutMicrosecs); 869 switch(err) 870 { 871 case SCE_OK: return WAIT_OBJECT_0; 872 case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return WAIT_TIMEOUT; 873 case SCE_KERNEL_ERROR_WAIT_CANCEL: return WAIT_ABANDONED; 874 default: return WAIT_FAILED; 875 } 876#else 877 retVal = WaitForMultipleObjects(m_size, m_events, true, timeoutMs); 878#endif // __PS3__ 879 880 return retVal; 881} 882 883DWORD C4JThread::EventArray::WaitForAny(int timeoutMs ) 884{ 885#ifdef __PS3__ 886 if(timeoutMs == INFINITE) 887 timeoutMs = SYS_NO_TIMEOUT ; 888 int timoutMicrosecs = timeoutMs * 1000; 889 unsigned int bitmask = 0; 890 for(int i=0;i<m_size;i++) 891 bitmask |= (1<<i); 892 893 uint32_t mode = SYS_EVENT_FLAG_WAIT_OR; 894 if(m_mode == e_modeAutoClear) 895 mode |= SYS_EVENT_FLAG_WAIT_CLEAR; 896 897 int err = sys_event_flag_wait(m_events, bitmask, mode, 0, timoutMicrosecs); 898 899 switch(err) 900 { 901 case CELL_OK: return WAIT_OBJECT_0; 902 case ETIMEDOUT: return WAIT_TIMEOUT; 903 case ECANCELED: return WAIT_ABANDONED; 904 default: 905 assert(0); 906 return WAIT_FAILED; 907 } 908 909#elif defined __ORBIS__ 910 SceKernelUseconds timeoutMicrosecs; 911 SceKernelUseconds *pTimeoutMicrosecs; 912 if( timeoutMs == INFINITE ) 913 { 914 pTimeoutMicrosecs = NULL; 915 } 916 else 917 { 918 timeoutMicrosecs = ((SceKernelUseconds)timeoutMs) * 1000; 919 pTimeoutMicrosecs = &timeoutMicrosecs; 920 } 921 unsigned int bitmask = 0; 922 for(int i=0;i<m_size;i++) 923 bitmask |= (1<<i); 924 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_OR; 925 if(m_mode == e_modeAutoClear) 926 { 927 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_PAT; 928 } 929 int err = sceKernelWaitEventFlag(m_events, bitmask, waitMode, NULL, pTimeoutMicrosecs); 930 switch(err) 931 { 932 case SCE_OK: return WAIT_OBJECT_0; 933 case SCE_KERNEL_ERROR_ETIMEDOUT: return WAIT_TIMEOUT; 934 case SCE_KERNEL_ERROR_ECANCELED: return WAIT_ABANDONED; 935 default: return WAIT_FAILED; 936 } 937#elif defined __PSVITA__ 938 SceUInt32 timeoutMicrosecs; 939 SceUInt32 *pTimeoutMicrosecs; 940 if( timeoutMs == INFINITE ) 941 { 942 pTimeoutMicrosecs = NULL; 943 } 944 else 945 { 946 timeoutMicrosecs = ((SceUInt32)timeoutMs) * 1000; 947 pTimeoutMicrosecs = &timeoutMicrosecs; 948 } 949 unsigned int bitmask = 0; 950 for(int i=0;i<m_size;i++) 951 bitmask |= (1<<i); 952 uint32_t waitMode = SCE_KERNEL_EVF_WAITMODE_OR; 953 if(m_mode == e_modeAutoClear) 954 { 955 waitMode |= SCE_KERNEL_EVF_WAITMODE_CLEAR_ALL; 956 } 957 int err = sceKernelWaitEventFlag(m_events, bitmask, waitMode, NULL, pTimeoutMicrosecs); 958 switch(err) 959 { 960 case SCE_OK: return WAIT_OBJECT_0; 961 case SCE_KERNEL_ERROR_WAIT_TIMEOUT: return WAIT_TIMEOUT; 962 case SCE_KERNEL_ERROR_WAIT_CANCEL: return WAIT_ABANDONED; 963 default: return WAIT_FAILED; 964 } 965#else 966 return WaitForMultipleObjects(m_size, m_events, false, timeoutMs); 967#endif // __PS3__ 968} 969 970#ifdef __PS3__ 971void C4JThread::EventArray::Cancel() 972{ 973 sys_event_flag_cancel(m_events, NULL); 974} 975#endif 976 977 978 979 980C4JThread::EventQueue::EventQueue( UpdateFunc* updateFunc, ThreadInitFunc threadInitFunc, const char* szThreadName) 981{ 982 m_updateFunc = updateFunc; 983 m_threadInitFunc = threadInitFunc; 984 strcpy(m_threadName, szThreadName); 985 m_thread = NULL; 986 m_startEvent = NULL; 987 m_finishedEvent = NULL; 988 m_processor = -1; 989 m_priority = THREAD_PRIORITY_HIGHEST+1; 990} 991 992void C4JThread::EventQueue::init() 993{ 994 m_startEvent = new C4JThread::EventArray(1); 995 m_finishedEvent = new C4JThread::Event(); 996 InitializeCriticalSection(&m_critSect); 997 m_thread = new C4JThread(threadFunc, this, m_threadName); 998 if(m_processor >= 0) 999 m_thread->SetProcessor(m_processor); 1000 if(m_priority != THREAD_PRIORITY_HIGHEST+1) 1001 m_thread->SetPriority(m_priority); 1002 m_thread->Run(); 1003} 1004 1005void C4JThread::EventQueue::sendEvent( Level* pLevel ) 1006{ 1007 if(m_thread == NULL) 1008 init(); 1009 EnterCriticalSection(&m_critSect); 1010 m_queue.push(pLevel); 1011 m_startEvent->Set(0); 1012 m_finishedEvent->Clear(); 1013 LeaveCriticalSection(&m_critSect); 1014} 1015 1016void C4JThread::EventQueue::waitForFinish() 1017{ 1018 if(m_thread == NULL) 1019 init(); 1020 EnterCriticalSection(&m_critSect); 1021 if(m_queue.empty()) 1022 { 1023 LeaveCriticalSection((&m_critSect)); 1024 return; 1025 } 1026 LeaveCriticalSection((&m_critSect)); 1027 m_finishedEvent->WaitForSignal(INFINITE); 1028} 1029 1030int C4JThread::EventQueue::threadFunc( void* lpParam ) 1031{ 1032 EventQueue* p = (EventQueue*)lpParam; 1033 p->threadPoll(); 1034 return 0; 1035} 1036 1037void C4JThread::EventQueue::threadPoll() 1038{ 1039 ShutdownManager::HasStarted(ShutdownManager::eEventQueueThreads, m_startEvent); 1040 1041 if(m_threadInitFunc) 1042 m_threadInitFunc(); 1043 1044 while(ShutdownManager::ShouldRun(ShutdownManager::eEventQueueThreads)) 1045 { 1046 1047 DWORD err = m_startEvent->WaitForAny(INFINITE); 1048 if(err == WAIT_OBJECT_0) 1049 { 1050 bool bListEmpty = true; 1051 do 1052 { 1053 EnterCriticalSection(&m_critSect); 1054 void* updateParam = m_queue.front(); 1055 LeaveCriticalSection(&m_critSect); 1056 1057 m_updateFunc(updateParam); 1058 1059 EnterCriticalSection(&m_critSect); 1060 m_queue.pop(); 1061 bListEmpty = m_queue.empty(); 1062 if(bListEmpty) 1063 { 1064 m_finishedEvent->Set(); 1065 } 1066 LeaveCriticalSection(&m_critSect); 1067 1068 } while(!bListEmpty); 1069 } 1070 }; 1071 1072 ShutdownManager::HasFinished(ShutdownManager::eEventQueueThreads); 1073} 1074 1075 1076#ifdef __ORBIS__ 1077 1078void C4JThread::PushAffinityAllCores() 1079{ 1080 assert(m_oldAffinityMask == 0); 1081 int err; 1082 ScePthread currThreadID = scePthreadSelf(); 1083 err = scePthreadGetaffinity(currThreadID, &m_oldAffinityMask); 1084 assert(err == SCE_OK); 1085 err = scePthreadSetaffinity(currThreadID, 63); 1086 assert(err == SCE_OK); 1087 1088 1089} 1090 1091void C4JThread::PopAffinity() 1092{ 1093 int err; 1094 ScePthread currThreadID = scePthreadSelf(); 1095 err = scePthreadSetaffinity(currThreadID, m_oldAffinityMask); 1096 m_oldAffinityMask = 0; 1097 assert(err == SCE_OK); 1098} 1099 1100#endif // __ORBIS__