void* OpqThreadImpl(void* arg_opaq) { OpqThreadData* opqthreaddata = (OpqThreadData*)arg_opaq; OpMultiQ* popq = opqthreaddata->mpOpQ; std::string opqn = popq->mName; SetCurrentThreadName(opqn.c_str()); static int icounter = 0; int thid = opqthreaddata->miThreadID + 4; std::string channam = ork::FormatString("opqth%d", int(thid)); //////////////////////////////////////////////// // main opq loop //////////////////////////////////////////////// popq->mThreadsRunning.fetch_add(1); while (false == popq->mbOkToExit) { popq->BlockingIterate(thid); } popq->mThreadsRunning.fetch_sub(1); //////////////////////////////////////////////// //printf( "popq<%p> thread exiting...\n", popq ); return (void*)0; }
void ResourceResidencyQueue::CleanThreadFunc() { SetCurrentThreadName("CommandList Clean Thread"); std::vector<std::unique_ptr<Task>> workingSet; while (m_runThreads) { std::unique_lock<std::mutex> lk(m_cleanMutex); m_cleanCv.wait(lk, [this] {return !m_runThreads || !m_cleanQueue.empty(); }); while (!m_cleanQueue.empty()) { std::unique_ptr<Task> task = std::move(m_cleanQueue.front()); workingSet.push_back(std::move(task)); m_cleanQueue.pop(); } lk.unlock(); for (auto& task : workingSet) { task->syncPoint.m_fence->Wait(task->syncPoint.m_value); for (const MemoryObject& res : task->resources) { // TODO... } } workingSet.clear(); } }
void BasicThread::DoRun(std::shared_ptr<Object>&& refTracker) { assert(m_running); // Make our own session current before we do anything else: CurrentContextPusher pusher(GetContext()); // Set the thread name no matter what: if(GetName()) SetCurrentThreadName(); // Now we wait for the thread to be good to go: try { Run(); } catch(dispatch_aborted_exception&) { // Okay, this is fine, a dispatcher is terminating--this is a normal way to // end a dispatcher loop. } catch(...) { try { // Ask that the enclosing context filter this exception, if possible: GetContext()->FilterException(); } catch(...) { // Generic exception, unhandled, we can't do anything about this } // Signal shutdown on the enclosing context--cannot wait, if we wait we WILL deadlock GetContext()->SignalShutdown(false); } // Run loop is over, time to clean up DoRunLoopCleanup(pusher.Pop(), std::move(refTracker)); }
DWORD __stdcall CCPUFrequencyMonitor::StaticPerCPUSamplingThread(LPVOID param) { SetCurrentThreadName("CPU frequency measuring thread"); auto* pState = reinterpret_cast<CPUSamplerState*>(param); pState->pOwner->PerCPUSamplingThread(pState->cpuNumber); return 0; }
DWORD __stdcall CCPUFrequencyMonitor::StaticMonitorThread(LPVOID param) { SetCurrentThreadName("CPU frequency monitor thread"); auto* pThis = reinterpret_cast<CCPUFrequencyMonitor*>(param); pThis->MonitorThread(); return 0; }
DWORD __stdcall CWorkingSetMonitor::StaticWSMonitorThread(LPVOID param) { SetCurrentThreadName("Working set monitor thread"); CWorkingSetMonitor* pThis = reinterpret_cast<CWorkingSetMonitor*>(param); pThis->WSMonitorThread(); return 0; }
DWORD WINAPI Thread::entryPoint(LPVOID param) { SetCurrentThreadName(((Thread*)param)->threadName); CrashHandler::registerThreadCrashHandlers(); ((Thread*)param)->run(); CrashHandler::unregisterThreadCrashHandlers(); return 0; }
void Thread::thread_func(void* arg) { Thread* thread = (Thread*)arg; ThreadTask* task = thread->_task; task->_stopRequested = false; SetCurrentThreadName(task->ToString()); try { task->Run(); } catch (const Exception& e) { CoreLib::OnUnhandledException(e, task->ToString()); } catch (...) { Xli::Exception e("An unsupported C++ exception was thrown"); CoreLib::OnUnhandledException(e, task->ToString()); } thread->_state = ThreadStateStopped; }
DWORD workerThreadMain(LPVOID pData) { THREAD_DATA *pThreadData = (THREAD_DATA*)pData; SWR_CONTEXT *pContext = pThreadData->pContext; uint32_t threadId = pThreadData->threadId; uint32_t workerId = pThreadData->workerId; bindThread(pContext, threadId, pThreadData->procGroupId, pThreadData->forceBindProcGroup); { char threadName[64]; sprintf_s(threadName, #if defined(_WIN32) "SWRWorker_%02d_NUMA%d_Core%02d_T%d", #else // linux pthread name limited to 16 chars (including \0) "w%03d-n%d-c%03d-t%d", #endif workerId, pThreadData->numaId, pThreadData->coreId, pThreadData->htId); SetCurrentThreadName(threadName); } RDTSC_INIT(threadId); // Only need offset numa index from base for correct masking uint32_t numaNode = pThreadData->numaId - pContext->threadInfo.BASE_NUMA_NODE; uint32_t numaMask = pContext->threadPool.numaMask; // flush denormals to 0 _mm_setcsr(_mm_getcsr() | _MM_FLUSH_ZERO_ON | _MM_DENORMALS_ZERO_ON); // Track tiles locked by other threads. If we try to lock a macrotile and find its already // locked then we'll add it to this list so that we don't try and lock it again. TileSet lockedTiles; // each worker has the ability to work on any of the queued draws as long as certain // conditions are met. the data associated // with a draw is guaranteed to be active as long as a worker hasn't signaled that he // has moved on to the next draw when he determines there is no more work to do. The api // thread will not increment the head of the dc ring until all workers have moved past the // current head. // the logic to determine what to work on is: // 1- try to work on the FE any draw that is queued. For now there are no dependencies // on the FE work, so any worker can grab any FE and process in parallel. Eventually // we'll need dependency tracking to force serialization on FEs. The worker will try // to pick an FE by atomically incrementing a counter in the swr context. he'll keep // trying until he reaches the tail. // 2- BE work must be done in strict order. we accomplish this today by pulling work off // the oldest draw (ie the head) of the dcRing. the worker can determine if there is // any work left by comparing the total # of binned work items and the total # of completed // work items. If they are equal, then there is no more work to do for this draw, and // the worker can safely increment its oldestDraw counter and move on to the next draw. std::unique_lock<std::mutex> lock(pContext->WaitLock, std::defer_lock); auto threadHasWork = [&](uint32_t curDraw) { return curDraw != pContext->dcRing.GetHead(); }; uint32_t curDrawBE = 0; uint32_t curDrawFE = 0; bool bShutdown = false; while (true) { if (bShutdown && !threadHasWork(curDrawBE)) { break; } uint32_t loop = 0; while (loop++ < KNOB_WORKER_SPIN_LOOP_COUNT && !threadHasWork(curDrawBE)) { _mm_pause(); } if (!threadHasWork(curDrawBE)) { lock.lock(); // check for thread idle condition again under lock if (threadHasWork(curDrawBE)) { lock.unlock(); continue; } pContext->FifosNotEmpty.wait(lock); lock.unlock(); } if (IsBEThread) { RDTSC_BEGIN(WorkerWorkOnFifoBE, 0); bShutdown |= WorkOnFifoBE(pContext, workerId, curDrawBE, lockedTiles, numaNode, numaMask); RDTSC_END(WorkerWorkOnFifoBE, 0); WorkOnCompute(pContext, workerId, curDrawBE); } if (IsFEThread) { WorkOnFifoFE(pContext, workerId, curDrawFE); if (!IsBEThread) { curDrawBE = curDrawFE; } } } return 0; }
void UpdateThread::run() // virtual { SetCurrentThreadName( "UpdateRunLoop" ); ork::Timer timr; timr.Start(); int icounter = 0; OpqTest opqtest(&UpdateSerialOpQ()); while( false==mbEXITING ) { icounter++; float fsecs = timr.SecsSinceStart(); if( fsecs > 10.0f ) { printf( "ups<%f>\n", float(icounter)/fsecs ); timr.Start(); icounter=0; } //////////////////////////////////////////////// // process serial update opQ //////////////////////////////////////////////// while(UpdateSerialOpQ().Process()); //////////////////////////////////////////////// // update scene //////////////////////////////////////////////// switch( gUpdateStatus.meStatus ) { case EUPD_START: mpVP->NotInDrawSync(); gUpdateStatus.SetState(EUPD_RUNNING); break; case EUPD_RUNNING: { //ork::PerfMarkerPush( "ork.begin_update" ); ent::DrawableBuffer* dbuf = ork::ent::DrawableBuffer::LockWriteBuffer(7); { OrkAssert(dbuf); auto psi = (ent::SceneInst*) mpVP->GetSceneInst(); if( psi ) { auto cmci = psi->GetCMCI(); float frame_rate = cmci ? cmci->GetCurrentFrameRate() : 0.0f; bool externally_fixed_rate = (frame_rate!=0.0f); if( externally_fixed_rate ) { RenderSyncToken syntok; if( DrawableBuffer::mOfflineUpdateSynchro.try_pop(syntok) ) { syntok.mFrameIndex++; psi->Update(); DrawableBuffer::mOfflineRenderSynchro.push(syntok); } } else psi->Update(); } mpVP->QueueSceneInstToDb(dbuf); } ork::ent::DrawableBuffer::UnLockWriteBuffer(dbuf); //ork::PerfMarkerPush( "ork.end_update" ); break; } case EUPD_STOP: mpVP->NotInDrawSync(); gUpdateStatus.SetState(EUPD_STOPPED); break; case EUPD_STOPPED: mpVP->NotInDrawSync(); break; default: assert(false); break; } //////////////////////////////////////////////// ork::msleep(1); } }
void* ix_kb_thread( void* pctx ) { SetCurrentThreadName( "IxKeyboardThread" ); for(int i=0; i<256; i++) ix_kb_state[i] = false; //int fd = open("/dev/input/event10", O_RDONLY ); int fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY ); if( fd<0 ) while(1) usleep(1<<20); struct input_event ev[64]; std::queue<U8> byte_queue; while(1) { int rd = read(fd,ev,sizeof(input_event)*64); if( rd>0 ) { U8* psrc = (U8*) ev; for( int i=0; i<rd; i++ ) { byte_queue.push(psrc[i]); } } while(byte_queue.size()>=sizeof(input_event)) { input_event oev; u8* pdest = (U8*) & oev; for( int i=0; i<sizeof(input_event); i++ ) { pdest[i]=byte_queue.front(); byte_queue.pop(); } if( oev.type == 1 ) { bool bkdown = (oev.value == 1); bool bkup = (oev.value == 0); bool bksta = (0!=oev.value); printf( "ev typ<%d> cod<%d> val<%d>\n", oev.type, oev.code, oev.value ); switch(oev.code) { case 17: // w ix_kb_state['W'] = bksta; break; case 30: // a ix_kb_state['A'] = bksta; break; case 31: // s ix_kb_state['S'] = bksta; break; case 32: // d ix_kb_state['D'] = bksta; break; case 24: // o ix_kb_state['O'] = bksta; break; case 25: // p ix_kb_state['P'] = bksta; break; case 33: // f ix_kb_state['F'] = bksta; break; //case 105: // L // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_LEFT] = bksta; // break; //case 106: // R // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_RIGHT] = bksta; // break; //case 103: // U // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_UP] = bksta; // break; //case 108: // D // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_DOWN] = bksta; // break; //case 42: // lshift // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_LSHIFT] = bksta; // break; //case 29: // lctrl // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_LCTRL] = bksta; // break; //case 56: // lalt // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_LALT] = bksta; // break; // case 28: // return // ix_kb_state[ork::lev2::ETRIG_RAW_KEY_ENTER] = bksta; // break; // 0 11 // 9 10 // [ 26 default: break; } } } // printf( "rd<%d>\n", rd ); } }