static VOID __stdcall clemu_groupthread_proc ( LPVOID lpParameter ) { clemuKernelGroup *group = (clemuKernelGroup *)lpParameter; clemuKernelJob *job = (clemuKernelJob *)(group->GetParent()); int curwfid = 0; // while(true) { group->SetCurWF(curwfid); // PROCESS GROUP HERE while(!group->IsEndof() || (job->GetNbrWavefronts() > curwfid) ) { curwfid = group->GetCurWF(); // switch to the first thread of a wavefront SwitchToFiber(group->GetTFiber(curwfid, 0)->m_FIBER_id); // select new wf curwfid = (group->IsEndof()) ? (curwfid + 1) : (curwfid + 1) % job->GetNbrWavefronts(); group->SetCurWF(curwfid); } // back to scheduler SwitchToFiber(job->GetFiber()->m_FIBER_id); } }
/* * Free function. Saves the current context in @p from * and restores the context in @p to. On windows the from * parameter is ignored. The current context is saved on the * current fiber. * Note that if the current thread is not a fiber, it will be * converted to fiber on the fly on call and unconverted before * return. This is expensive. The user should convert the * current thread to a fiber once on thread creation for better performance. * Note that we can't leave the thread unconverted on return or else we * will leak resources on thread destruction. Do the right thing by * default. */ friend void swap_context(fibers_context_impl_base& from, const fibers_context_impl_base& to, default_hint) { if(!is_fiber()) { HPX_ASSERT(from.m_ctx == 0); from.m_ctx = ConvertThreadToFiber(0); HPX_ASSERT(from.m_ctx != 0); #if HPX_HAVE_SWAP_CONTEXT_EMULATION != 0 switch_to_fiber(to.m_ctx); #else SwitchToFiber(to.m_ctx); #endif BOOL result = ConvertFiberToThread(); HPX_ASSERT(result); HPX_UNUSED(result); from.m_ctx = 0; } else { bool call_from_main = from.m_ctx == 0; if(call_from_main) from.m_ctx = GetCurrentFiber(); #if HPX_HAVE_SWAP_CONTEXT_EMULATION != 0 switch_to_fiber(to.m_ctx); #else SwitchToFiber(to.m_ctx); #endif if(call_from_main) from.m_ctx = 0; } }
FiberPool_::coro_pull_interface* FiberPool_::getFiber(size_t size, void** sp, coro_handler h, void* param /*= NULL*/) { assert(size && size % 4096 == 0 && size <= 1024 * 1024); void* currentFiber = NULL; #if _WIN32_WINNT >= 0x0600 if (IsThreadAFiber()) { currentFiber = GetCurrentFiber(); } else { currentFiber = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH); } #else//#elif _MSC_VER >= 0x0501 currentFiber = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH); if (!currentFiber) { currentFiber = GetCurrentFiber(); } #endif { fiber_pool_pck& pool = s_fiberPool._fiberPool[size / 4096 - 1]; pool._mutex.lock(); if (!pool._pool.empty()) { coro_pull_interface* oldFiber = pool._pool.back(); pool._pool.pop_back(); pool._mutex.unlock(); oldFiber->_fiber._pushHandle = currentFiber; oldFiber->_fiber._currentHandler = h; oldFiber->_fiber._fiberHandle->_param = param; oldFiber->_fiber._tick = 0; *sp = oldFiber->_fiber._fiberHandle->_stackTop; SwitchToFiber(oldFiber->_fiber._fiberHandle); return oldFiber; } pool._mutex.unlock(); } s_fiberPool._stackCount++; s_fiberPool._stackTotalSize += size; coro_pull_interface* newFiber = new coro_pull_interface; #ifdef _WIN64 newFiber->_fiber._fiberHandle = (FiberStruct_*)CreateFiberEx(size, 64 * 1024, FIBER_FLAG_FLOAT_SWITCH, FiberPool_::fiberHandler, newFiber); #else newFiber->_fiber._fiberHandle = (FiberStruct_*)CreateFiberEx(size, 0, FIBER_FLAG_FLOAT_SWITCH, FiberPool_::fiberHandler, newFiber); #endif if (newFiber->_fiber._fiberHandle) { newFiber->_fiber._pushHandle = currentFiber; newFiber->_fiber._currentHandler = h; newFiber->_fiber._fiberHandle->_param = param; newFiber->_fiber._tick = 0; *sp = newFiber->_fiber._fiberHandle->_stackTop; SwitchToFiber(newFiber->_fiber._fiberHandle); return newFiber; } delete newFiber; throw std::shared_ptr<string>(new string("Fiber不足")); }
VOID __stdcall Fiber2( LPVOID lpParameter ) { buffer[i++] = '2'; while( i < sizeof(buffer) - 1 ) { buffer[i++] = 'a'; SwitchToFiber( g_pFibers[FIBER1] ); } SwitchToFiber( g_pFibers[FIBER_PRIMARY] ); }
VOID WINAPI FiberA(DWORD) { for (;;) { puts("A"); SwitchToFiber(mainFiber); puts("B"); SwitchToFiber(mainFiber); puts("C"); SwitchToFiber(mainFiber); } }
VOID WINAPI FiberB(DWORD) { for (;;) { puts("1"); SwitchToFiber(mainFiber); puts("2"); SwitchToFiber(mainFiber); puts("3"); SwitchToFiber(mainFiber); } }
int main(int argc, WCHAR* argv[]) { fiberA = CreateFiber(0, (LPFIBER_START_ROUTINE)FiberA, (LPVOID)0); fiberB = CreateFiber(0, (LPFIBER_START_ROUTINE)FiberB, (LPVOID)0); mainFiber = ConvertThreadToFiber(NULL); for (int i = 0; i < 20; i++) { SwitchToFiber(fiberA); SwitchToFiber(fiberB); Sleep(100); } return 0; }
void WINAPI FiberFunc(PVOID pvParam) { PFIBERINFO pFiberInfo = (PFIBERINFO) pvParam; /* Stores a value in the calling fiber's fiber local storage (FLS) slot * for the specified FLS index. * Each fiber has its own slot for each FLS index. */ FlsSetValue(g_dwSlot, TEXT("Computation")); LogMessage(TEXT("entering computation...")); // Update the window showing which fiber is executing. SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation")); // Get the current count in the EDIT control. int nCount = GetDlgItemInt(pFiberInfo->hwnd, IDC_COUNT, NULL, FALSE); // Count from 0 to nCount, updating the STATIC control. for (int x = 0; x <= nCount; x++) { // UI events have higher priority than counting. // If there are any UI events, handle them ASAP. /* Retrieves the type of messages found in the calling thread's message queue. */ if (HIWORD(GetQueueStatus(QS_ALLEVENTS)) != 0) { // The UI fiber has something to do; temporarily // pause counting and handle the UI events. SwitchToFiber(pFiberInfo->pFiberUI); // The UI has no more events; continue counting. SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation")); } // Update the STATIC control with the most recent count. SetDlgItemInt(pFiberInfo->hwnd, IDC_ANSWER, x, FALSE); // Sleep for a while to exaggerate the effect; remove // the call to Sleep in production code. Sleep(200); } // Indicate that counting is complete. pFiberInfo->bps = BPS_DONE; // Reschedule the UI thread. When the UI thread is running // and has no events to process, the thread is put to sleep. // NOTE: If we just allow the fiber function to return, // the thread and the UI fiber die -- we don't want this! SwitchToFiber(pFiberInfo->pFiberUI); }
void Processor::coreEntryPoint(Core *core) { tCurrentCore = core; core->primaryFiber = ConvertThreadToFiber(NULL); while (mRunning) { std::unique_lock<std::mutex> lock(mMutex); if (auto fiber = peekNextFiber(core->id)) { // Remove fiber from schedule queue mFiberQueue.erase(std::remove(mFiberQueue.begin(), mFiberQueue.end(), fiber), mFiberQueue.end()); // Switch to fiber core->currentFiber = fiber; fiber->coreID = core->id; fiber->parentFiber = core->primaryFiber; fiber->thread->state = OSThreadState::Running; lock.unlock(); gLog->trace("Core {} enter thread {}", core->id, fiber->thread->id); SwitchToFiber(fiber->handle); } else { // Wait for a valid fiber gLog->trace("Core {} wait for thread", core->id); mCondition.wait(lock); } } }
// Return to the interrupted thread void Processor::finishInterrupt() { auto core = tCurrentCore; auto fiber = core->interruptedFiber; core->currentFiber = fiber; core->interruptedFiber = nullptr; gLog->trace("Exit interrupt core {}", core->id); if (!fiber) { SwitchToFiber(core->primaryFiber); } else { SwitchToFiber(fiber->handle); } }
static void yield(YieldOperation &&yieldOperation) { Coroutine::Impl *pImpl = (Coroutine::Impl*)GetFiberData(); pImpl->yieldOperation = &yieldOperation; assert(pImpl != nullptr); SwitchToFiber(pImpl->pReturnFiber); }
static void coroutineEntry() { Coroutine::Impl *pImpl = (Coroutine::Impl*)GetFiberData(); pImpl->entry(); pImpl->status = Coroutine::Status::Terminated; SwitchToFiber(pImpl->pReturnFiber); }
void Fiber::Continue() { if (m_fiber) { SwitchToFiber(m_fiber); } }
void do_update_logic(WPARAM wParam, LPARAM lParam) { Impl::SCRIPT_END_HANDLER_LIST* end_handlers = reinterpret_cast<Impl::SCRIPT_END_HANDLER_LIST*>(lParam); { SCRIPT_LIST::iterator it = scripts_.begin(); for(; it != scripts_.end(); ++it) { FiberContextImpl* pScript = static_cast<FiberContextImpl*>(*it); if(pScript->is_running()) { pScript->timestamp_ = timestamp_; SwitchToFiber(pScript->fiber_); } } } { SCRIPT_LIST::iterator it = scripts_.begin(); for(; it != scripts_.end(); ) { FiberContextImpl* pScript = static_cast<FiberContextImpl*>(*it); if(!pScript->is_running() && (NULL != end_handlers)) { if(pScript->callbacker_) { FiberScriptEndHandler handler; handler.id = pScript->id_; handler.param = pScript->param_; handler.handler = pScript->callbacker_; end_handlers->push_back(handler); } DeleteFiber(pScript->fiber_); delete *it; it = scripts_.erase(it); } else { ++it; } } } }
// Sleep the interrupt thread until the first interrupt happens void Processor::waitFirstInterrupt() { auto core = tCurrentCore; auto fiber = core->currentFiber; core->interruptHandlerFiber = fiber; SwitchToFiber(core->primaryFiber); }
void __stdcall TaskScheduler::FiberSwitchStart(void *arg) { TaskScheduler *taskScheduler = (TaskScheduler *)arg; while (true) { taskScheduler->m_fiberPool.enqueue(tls_currentFiber); SwitchToFiber(tls_fiberToSwitchTo); } }
void InkCoro_Scheduler::wrapper(LPVOID arg) { InkCoro_Scheduler_wrapper_arg *tmp = (InkCoro_Scheduler_wrapper_arg *)arg; tmp->co->func(tmp->co->arg); tmp->sched->destroy(tmp->co); SwitchToFiber(tmp->sched->main_fib); return; }
static void stop (Acid64 &inst) { inst.engine->stop (); SafeThreadToFibre convert(inst.mainFiber); while (inst.engine->state() != sid2_stopped) SwitchToFiber (inst.engineFiber); inst.cycleCorrection = 0; }
void Processor::reschedule(bool hasSchedulerLock, bool yield) { std::unique_lock<std::mutex> lock { mMutex }; auto core = tCurrentCore; if (!core) { // Ran from host thread return; } auto fiber = core->currentFiber; auto thread = fiber->thread; auto next = peekNextFiberNoLock(core->id); // Priority is 0 = highest, 31 = lowest if (thread->suspendCounter <= 0 && thread->state == OSThreadState::Running) { if (!next) { // There is no thread to reschedule to return; } if (yield) { // Yield will transfer control to threads with equal or better priority if (thread->basePriority < next->thread->basePriority) { return; } } else { // Only reschedule to more important threads if (thread->basePriority <= next->thread->basePriority) { return; } } } // Change state to ready, only if this thread is running if (fiber->thread->state == OSThreadState::Running) { fiber->thread->state = OSThreadState::Ready; } // Add this fiber to queue queueNoLock(fiber); if (hasSchedulerLock) { OSUnlockScheduler(); } gLog->trace("Core {} leave thread {}", core->id, fiber->thread->id); // Return to main scheduler fiber lock.unlock(); SwitchToFiber(core->primaryFiber); // Reacquire scheduler lock if needed if (hasSchedulerLock) { OSLockScheduler(); } }
void Processor::exit() { // Return to parent fiber auto core = tCurrentCore; auto fiber = tCurrentCore->currentFiber; gLog->trace("Core {} exit thread {}", core->id, fiber->thread->id); SwitchToFiber(fiber->parentFiber); }
void Return() { ESS_ASSERT( GetCurrentFiber() == m_handle ); ESS_ASSERT( m_fiberToReturn != 0); LPVOID ret = m_fiberToReturn; m_fiberToReturn = 0; SwitchToFiber(ret); }
static void runNewFiber() { Fiber* fiber = g_pFiberPool[InterlockedDecrement(&g_fiberPoolHead) + 1]; fiber->status = RUNNING; Thread* thread = TlsGetValue(g_threadData); thread->pCurrentFiber = fiber; SwitchToFiber(fiber->fiber); }
void coroutine_yield(struct schedule * S) { int id = S->running; struct coroutine* C; assert(id >= 0); C = S->co[id]; C->status = COROUTINE_SUSPEND; S->running = -1; SwitchToFiber(S->main); }
void Run() { ESS_ASSERT(m_fiberToReturn == 0); m_fiberToReturn = GetCurrentFiber(); ESS_ASSERT(m_fiberToReturn != 0); ESS_ASSERT(m_fiberToReturn != m_handle); SwitchToFiber(m_handle); }
void Dispatcher::contextProcedure() { assert(GetCurrentThreadId() == threadId); assert(firstReusableContext == nullptr); NativeContext context; context.interrupted = false; context.next = nullptr; context.inExecutionQueue = false; firstReusableContext = &context; SwitchToFiber(currentContext->fiber); for (;;) { ++runningContextCount; try { context.procedure(); } catch (...) { } if (context.group != nullptr) { if (context.groupPrev != nullptr) { assert(context.groupPrev->groupNext == &context); context.groupPrev->groupNext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = context.groupPrev; } else { assert(context.group->lastContext == &context); context.group->lastContext = context.groupPrev; } } else { assert(context.group->firstContext == &context); context.group->firstContext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = nullptr; } else { assert(context.group->lastContext == &context); if (context.group->firstWaiter != nullptr) { if (firstResumingContext != nullptr) { assert(lastResumingContext->next == nullptr); lastResumingContext->next = context.group->firstWaiter; } else { firstResumingContext = context.group->firstWaiter; } lastResumingContext = context.group->lastWaiter; context.group->firstWaiter = nullptr; } } } pushReusableContext(context); } dispatch(); } }
/* * implementation for context_switch */ void context_switch(sc_context * pContext) { assert(pContext != NULL); if (pContext->pFiber != NULL && !completed(pContext)) { if (current_context != NULL) if (!completed(current_context)) current_context->state = FS_DELAYED; current_context = pContext; SwitchToFiber(pContext->pFiber); } return; }
void __stdcall TaskScheduler::CounterWaitStart(void *arg) { TaskScheduler *taskScheduler = (TaskScheduler *)arg; while (true) { EnterCriticalSection(&taskScheduler->m_waitingTaskLock); taskScheduler->m_waitingTasks.emplace_back(tls_currentFiber, tls_waitingCounter, tls_waitingValue); LeaveCriticalSection(&taskScheduler->m_waitingTaskLock); SwitchToFiber(tls_fiberToSwitchTo); } }
void dpy_flushkeys(void) { if (GetCurrentFiber() == uifiber) { while (numqueued) { currentkey = dequeue(); SwitchToFiber(appfiber); } } }
void rawCorSwitchToFiber(void *fiber) { #if defined(CORHOST) DWORD *cookie; corhost->SwitchOutLogicalThreadState(&cookie); #endif SwitchToFiber(fiber); #if defined(CORHOST) corhost->SwitchInLogicalThreadState(cookie); #endif }
void sc_cor_pkg_fiber::abort( sc_cor* next_cor ) { sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // Switch SJLJ exception handling function contexts _Unwind_SjLj_Register(&curr_cor->m_eh); _Unwind_SjLj_Unregister(&new_cor->m_eh); curr_cor = new_cor; # endif SwitchToFiber( new_cor->m_fiber ); }