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不足")); }
/* * @implemented */ LPVOID WINAPI ConvertThreadToFiber(LPVOID lpParameter) { /* Call the newer function */ return ConvertThreadToFiberEx(lpParameter, 0); }
Dispatcher::Dispatcher() { static_assert(sizeof(CRITICAL_SECTION) == sizeof(Dispatcher::criticalSection), "CRITICAL_SECTION size doesn't fit sizeof(Dispatcher::criticalSection)"); BOOL result = InitializeCriticalSectionAndSpinCount(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection), 4000); assert(result != FALSE); std::string message; if (ConvertThreadToFiberEx(NULL, 0) == NULL) { message = "ConvertThreadToFiberEx failed, " + lastErrorMessage(); } else { completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (completionPort == NULL) { message = "CreateIoCompletionPort failed, " + lastErrorMessage(); } else { WSADATA wsaData; int wsaResult = WSAStartup(0x0202, &wsaData); if (wsaResult != 0) { message = "WSAStartup failed, " + errorMessage(wsaResult); } else { remoteNotificationSent = false; reinterpret_cast<LPOVERLAPPED>(remoteSpawnOverlapped)->hEvent = NULL; threadId = GetCurrentThreadId(); mainContext.fiber = GetCurrentFiber(); mainContext.interrupted = false; mainContext.group = &contextGroup; mainContext.groupPrev = nullptr; mainContext.groupNext = nullptr; mainContext.inExecutionQueue = false; contextGroup.firstContext = nullptr; contextGroup.lastContext = nullptr; contextGroup.firstWaiter = nullptr; contextGroup.lastWaiter = nullptr; currentContext = &mainContext; firstResumingContext = nullptr; firstReusableContext = nullptr; runningContextCount = 0; return; } BOOL result2 = CloseHandle(completionPort); assert(result2 == TRUE); } BOOL result2 = ConvertFiberToThread(); assert(result == TRUE); } DeleteCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection)); throw std::runtime_error("Dispatcher::Dispatcher, " + message); }
Dispatcher::Dispatcher() { static_assert(sizeof(CRITICAL_SECTION) == sizeof(Dispatcher::criticalSection), "CRITICAL_SECTION size doesn't fit sizeof(Dispatcher::criticalSection)"); BOOL result = InitializeCriticalSectionAndSpinCount(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection), 4000); assert(result != FALSE); std::string message; if (ConvertThreadToFiberEx(NULL, 0) == NULL) { message = "ConvertThreadToFiberEx failed, result=" + std::to_string(GetLastError()); } else { threadHandle = OpenThread(THREAD_SET_CONTEXT, FALSE, GetCurrentThreadId()); if (threadHandle == NULL) { message = "OpenThread failed, result=" + std::to_string(GetLastError()); } else { completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (completionPort == NULL) { message = "CreateIoCompletionPort failed, result=" + std::to_string(GetLastError()); } else { WSADATA wsaData; int wsaResult = WSAStartup(0x0202, &wsaData); if (wsaResult != 0) { message = "WSAStartup failed, result=" + std::to_string(wsaResult); } else { contextCount = 0; remoteNotificationSent = false; reinterpret_cast<LPOVERLAPPED>(remoteSpawnOverlapped)->hEvent = NULL; threadId = GetCurrentThreadId(); return; } BOOL result = CloseHandle(completionPort); assert(result == TRUE); } BOOL result = CloseHandle(threadHandle); assert(result == TRUE); } BOOL result = ConvertFiberToThread(); assert(result == TRUE); } DeleteCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection)); throw std::runtime_error("Dispatcher::Dispatcher, " + message); }
void TaskScheduler::Initialize(GlobalArgs *globalArgs) { for (uint i = 0; i < FIBER_POOL_SIZE; ++i) { m_fiberPool.enqueue(CreateFiberEx(524288, 0, FIBER_FLAG_FLOAT_SWITCH, FiberStart, globalArgs)); } SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); // Create an additional thread for each logical processor m_numThreads = sysinfo.dwNumberOfProcessors; m_threads = new HANDLE[m_numThreads]; m_fiberSwitchingFibers = new void *[m_numThreads]; m_counterWaitingFibers = new void *[m_numThreads]; // Create a switching fiber for each thread for (uint i = 0; i < m_numThreads; ++i) { m_fiberSwitchingFibers[i] = CreateFiberEx(32768, 0, FIBER_FLAG_FLOAT_SWITCH, FiberSwitchStart, &globalArgs->TaskScheduler); m_counterWaitingFibers[i] = CreateFiberEx(32768, 0, FIBER_FLAG_FLOAT_SWITCH, CounterWaitStart, &globalArgs->TaskScheduler); } // Set the affinity for the current thread and convert it to a fiber SetThreadAffinityMask(GetCurrentThread(), 1); ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH); m_threads[0] = GetCurrentThread(); tls_threadId = 0; // Create the remaining threads for (DWORD i = 1; i < m_numThreads; ++i) { ThreadStartArgs *threadArgs = new ThreadStartArgs(); threadArgs->globalArgs = globalArgs; threadArgs->threadId = i; HANDLE threadHandle = (HANDLE)_beginthreadex(nullptr, 524288, ThreadStart, threadArgs, CREATE_SUSPENDED, nullptr); m_threads[i] = threadHandle; DWORD_PTR mask = 1 << i; SetThreadAffinityMask(threadHandle, mask); ResumeThread(threadHandle); } }
void Ink_initCoroutine() { ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH); return; }
int clemuGPU :: scheduleNextJob(void) { int ret = CL_EMU_SUCCESS; // TO DO : SELECT JOB // SELECT SE, SIMD clemuKernelJob *nextJob = m_job[0]; int cur_gbl_tid; clemuGPU* dev = (clemuGPU*)(nextJob->GetDev()); nextJob->m_next_active_group = 0; nextJob->m_fiber.m_FIBER_id = ConvertThreadToFiberEx(nextJob,FIBER_FLAG_FLOAT_SWITCH); nextJob->m_fiber.m_FLS_index = 0; // TO DO: NBR GROUPS > SIMDS // run for(int j = 0, grp_id = 0, wf_id = 0; j < nextJob->m_nbr_grpDim[1]; j++) { for(int i = 0; i < nextJob->m_nbr_grpDim[0]; i++, grp_id++, wf_id += nextJob->m_nbr_wavefronts) { int active_grp = nextJob->m_next_active_group; // activate if ( !nextJob->m_groups[active_grp].m_fiber.m_FIBER_id ) { nextJob->m_groups[active_grp].m_fiber.m_FIBER_id = CreateFiberEx( CLEMU_STACKCOMMITSIZE, CLEMU_STACKRESERVESIZE, FIBER_FLAG_FLOAT_SWITCH, clemu_groupthread_proc, &nextJob->m_groups[active_grp]); assert(nextJob->m_groups[active_grp].m_fiber.m_FIBER_id); nextJob->m_groups[active_grp].m_fiber.m_FLS_index = 0; } if ( !nextJob->m_groups[active_grp].m_td_fibers ) { nextJob->m_groups[active_grp].m_td_fibers = new CL_EMU_FIBER[nextJob->GetNbrInstances()]; assert(nextJob->m_groups[active_grp].m_td_fibers); memset(nextJob->m_groups[active_grp].m_td_fibers, 0, sizeof(CL_EMU_FIBER) * nextJob->GetNbrInstances()); } for(int l = 0, tid = 0; l < nextJob->GetNbrWavefronts(); l++) { int wf_sz = nextJob->GetRealWFSz(l); for(int m = 0; m < wf_sz; m++, tid++) { if ( !nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id ) { nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id = CreateFiberEx( CLEMU_STACKCOMMITSIZE, CLEMU_STACKRESERVESIZE, FIBER_FLAG_FLOAT_SWITCH, clemu_wavefrontthread_proc, &nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m]); assert(nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id); nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FLS_index = 0; //FlsAlloc(0); nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_group_ptr = &nextJob->m_groups[active_grp]; } } } nextJob->m_groups[active_grp].m_parent = nextJob; nextJob->m_groups[active_grp].m_grpCoord[0] = i; nextJob->m_groups[active_grp].m_grpCoord[1] = j; nextJob->m_groups[active_grp].m_grpCoord[2] = 0; nextJob->m_groups[active_grp].m_group_id = grp_id; nextJob->m_groups[active_grp].m_se_id = 0; nextJob->m_groups[active_grp].m_simd_id = active_grp % dev->GetNbrSIMD(); nextJob->m_groups[active_grp].m_first_hwwavefront = wf_id; cur_gbl_tid = grp_id * nextJob->m_actual_nbr_instances; nextJob->m_groups[active_grp].m_kernel = nextJob->GetKernel(); nextJob->m_groups[active_grp].m_endof_group = 0; // local memory setup // EXPLANATION: // The size comes either from invokation (argument) or from teh kernel declaration. // if it comes from declaration for teh first group there will be 0 sz which is max size. // second group will det the correect size and will be separated from teh first group int local_mem_sz = (nextJob->m_localmem_sz > clemuGetCompiledKernelMemSz(nextJob->m_groups[active_grp].m_kernel)) ? nextJob->m_localmem_sz : clemuGetCompiledKernelMemSz(nextJob->m_groups[active_grp].m_kernel); nextJob->m_groups[active_grp].m_localmem_sz = local_mem_sz; nextJob->m_groups[active_grp].m_localmem_ptr = (unsigned char*)dev->AssignLclMem(nextJob->m_groups[active_grp].m_simd_id,active_grp,local_mem_sz); if ( nextJob->m_groups[active_grp].m_nmb_arg > 0 ) { for( int l = 0; l < nextJob->m_groups[active_grp].m_nmb_arg; l++) { if ( (nextJob->m_groups[active_grp].m_args[l].m_flags & CL_ARG_LCL_MEM_SZ) == CL_ARG_LCL_MEM_SZ ) { nextJob->m_groups[active_grp].m_args[l].m_flags |= CL_ARG_LDS_PTR; nextJob->m_groups[active_grp].m_args[l].m_arg.parg = nextJob->m_groups[active_grp].m_localmem_ptr; break; } } } // nextJob->m_groups[grp_id].m_wf_fibers = new CL_EMU_FIBER[nextJob->m_nbr_wavefronts]; // assert(nextJob->m_groups[grp_id].m_wf_fibers); if ( !nextJob->m_groups[active_grp].m_td_fibers ) { nextJob->m_groups[active_grp].m_td_fibers = new CL_EMU_FIBER[nextJob->m_actual_nbr_instances]; assert(nextJob->m_groups[active_grp].m_td_fibers); } for(int l = 0, tid = 0; l < nextJob->m_nbr_wavefronts; l++) { int wf_sz = nextJob->GetRealWFSz(l); for(int m = 0; m < wf_sz; m++, tid++) { nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_grp_tid = l * wf_sz + m; nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_gbl_tid = cur_gbl_tid + nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_grp_tid; nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_wfid = l; nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_wf_tid = m; } } // schedule group nextJob->m_curgroup = active_grp; SwitchToFiber(nextJob->m_groups[active_grp].m_fiber.m_FIBER_id); // free if ( nextJob->m_groups[active_grp].m_td_fibers ) { for(int l = 0, tid = 0; l < nextJob->GetNbrWavefronts(); l++) { int wf_sz = nextJob->GetRealWFSz(l); for(int m = 0; m < wf_sz; m++, tid++) { if ( nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id ) { DeleteFiber(nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id); nextJob->m_groups[active_grp].m_td_fibers[l*wf_sz + m].m_FIBER_id = 0; } } } delete [] nextJob->m_groups[active_grp].m_td_fibers; nextJob->m_groups[active_grp].m_td_fibers = 0; } if ( nextJob->m_groups[active_grp].m_fiber.m_FIBER_id ) { DeleteFiber(nextJob->m_groups[active_grp].m_fiber.m_FIBER_id); nextJob->m_groups[active_grp].m_fiber.m_FIBER_id = 0; } nextJob->m_next_active_group = (active_grp + 1) % nextJob->m_nbr_active_group; } } nextJob->FreeJob(); ConvertFiberToThread(); nextJob->m_fiber.m_FIBER_id = 0; return(ret); }
Impl(FiberUID uid, FiberFlags flags) : Impl(uid, ConvertThreadToFiberEx(this, MakeFlags(flags))) { }