void PixelPipeline::worker_main(int core) { #if defined(WIN32) && defined(PROFILE_PIPELINE) SetThreadIdealProcessor(GetCurrentThread(), core); SetThreadAffinityMask(GetCurrentThread(), 1 << core); unsigned __int64 ticks_waiting = 0; unsigned __int64 ticks_working = 0; #endif PixelThreadContext context(core, active_cores); while (true) { #if defined(WIN32) && defined(PROFILE_PIPELINE) unsigned __int64 wait_start_time = __rdtsc(); #endif int wakeup_reason = Event::wait(event_more_commands[core], event_stop); if (wakeup_reason != 0) break; event_more_commands[core].reset(); #if defined(WIN32) && defined(PROFILE_PIPELINE) unsigned __int64 wait_end_time = __rdtsc(); ticks_waiting += wait_end_time-wait_start_time; #endif process_commands(&context); #if defined(WIN32) && defined(PROFILE_PIPELINE) unsigned __int64 commands_end_time = __rdtsc(); ticks_working += commands_end_time-wait_end_time; #endif } #if defined(WIN32) && defined(PROFILE_PIPELINE) MessageBoxA( 0, cl_format("Pipeline core %1 spent %2 percent of its time waiting for commands", core, (int)(ticks_waiting*100/(ticks_working+ticks_waiting))).c_str(), "DEBUG", MB_OK); #endif }
/*! set the affinity of a given thread */ void setAffinity(HANDLE thread, ssize_t affinity) { #if (_WIN32_WINNT >= 0x0601) // FIXME: use getProcAddress to activate this feature only if supported by Windows int groups = GetActiveProcessorGroupCount(); int totalProcessors = 0, group = 0, number = 0; for (int i = 0; i<groups; i++) { int processors = GetActiveProcessorCount(i); if (totalProcessors + processors > affinity) { group = i; number = (int)affinity - totalProcessors; break; } totalProcessors += processors; } GROUP_AFFINITY groupAffinity; groupAffinity.Group = (WORD)group; groupAffinity.Mask = (KAFFINITY)(uint64(1) << number); groupAffinity.Reserved[0] = 0; groupAffinity.Reserved[1] = 0; groupAffinity.Reserved[2] = 0; if (!SetThreadGroupAffinity(thread, &groupAffinity, NULL)) THROW_RUNTIME_ERROR("cannot set thread group affinity"); PROCESSOR_NUMBER processorNumber; processorNumber.Group = group; processorNumber.Number = number; processorNumber.Reserved = 0; if (!SetThreadIdealProcessorEx(thread, &processorNumber, NULL)) THROW_RUNTIME_ERROR("cannot set ideal processor"); #else if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64(1) << affinity))) THROW_RUNTIME_ERROR("cannot set thread affinity mask"); if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1) THROW_RUNTIME_ERROR("cannot set ideal processor"); #endif }
/*! set the affinity of a given thread */ void setAffinity(HANDLE thread, ssize_t affinity) { #if (_WIN32_WINNT >= 0x0601) int groups = GetActiveProcessorGroupCount(); int totalProcessors = 0, group = 0, number = 0; for (int i = 0; i<groups; i++) { int processors = GetActiveProcessorCount(i); if (totalProcessors + processors > affinity) { group = i; number = (int)affinity - totalProcessors; break; } totalProcessors += processors; } GROUP_AFFINITY groupAffinity; groupAffinity.Group = (WORD)group; groupAffinity.Mask = (KAFFINITY)(uint64(1) << number); groupAffinity.Reserved[0] = 0; groupAffinity.Reserved[1] = 0; groupAffinity.Reserved[2] = 0; if (!SetThreadGroupAffinity(thread, &groupAffinity, NULL)) throw std::runtime_error("cannot set thread group affinity"); PROCESSOR_NUMBER processorNumber; processorNumber.Group = group; processorNumber.Number = number; processorNumber.Reserved = 0; if (!SetThreadIdealProcessorEx(thread, &processorNumber, NULL)) throw std::runtime_error("cannot set thread ideal processor"); #else if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64(1) << affinity))) throw std::runtime_error("cannot set thread affinity mask"); if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1) throw std::runtime_error("cannot set thread ideal processor"); #endif }
Application::Application(void): main_frame(), ec(), ecm(), fc(), evc(), evcm(), fcm(), navigator_manager(), graphic_factory(), layer_tree(), plugin_map(), three_dimension_camera_controller(NULL), two_dimension_camera_controller(NULL), dc(NULL), plugin_running(false), srs() { //for being able to load all type of images wxInitAllImageHandlers(); #ifdef WIN32 //This is to activate memory-leaks detection _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif wmsInitialize(); application_time = ApplicationTime::GetInstance(); application_time->Off(); cpw::IdGenerator::SetNamespace(GetMACaddress()); #ifdef WIN32 SetThreadAffinityMask(GetCurrentThread(), 0); #endif }
vm_status vm_affinity_thread_get(vm_thread *pthr, vm_affinity_mask *mptr) { DWORD processmask = 0; if(!mptr) return VM_NULL_PTR; if(mptr[0].msklen) { /* only one way to obtain thread affinity mask - set it again */ if (pthr[0].preset_affinity_mask) { mptr[0].mskbits[0] = (unsigned long)SetThreadAffinityMask(pthr[0].handle, pthr[0].preset_affinity_mask); return VM_OK; } else { if(GetProcessAffinityMask(pthr[0].handle, (PDWORD_PTR)&processmask, (PDWORD_PTR)mptr[0].mskbits)) return VM_OK; } } return VM_OPERATION_FAILED; }
/* ============== Sys_StartAsyncThread Start the thread that will call idCommon::Async() ============== */ void Sys_StartAsyncThread(void) { // create an auto-reset event that happens 60 times a second hTimer = CreateWaitableTimer(NULL, false, NULL); if (!hTimer) { common->Error("idPacketServer::Spawn: CreateWaitableTimer failed"); } LARGE_INTEGER t; t.HighPart = t.LowPart = 0; SetWaitableTimer(hTimer, &t, USERCMD_MSEC, NULL, NULL, TRUE); Sys_CreateThread((xthread_t)Sys_AsyncThread, NULL, THREAD_ABOVE_NORMAL, threadInfo, "Async", g_threads, &g_thread_count); #ifdef SET_THREAD_AFFINITY // give the async thread an affinity for the second cpu SetThreadAffinityMask((HANDLE)threadInfo.threadHandle, 2); #endif if (!threadInfo.threadHandle) { common->Error("Sys_StartAsyncThread: failed"); } }
// We don't call this directly from DLL_PROCESS_ATTACH because if we do things // can break when we're loaded via LoadLibrary // Instead this is called by LunaDLLInitHook, which is set up by // SetupLunaDLLInitHook that runs from DLL_PROCESS_ATTACH void LunaDLLInit() { InitGlobals(); #if PATCHIT TrySkipPatch(); #endif // PATCHIT // Test OpenGL support if (!gStartupSettings.noGL && LunaDLLTestGLFeatures()) { g_GLEngine.Enable(); } else { g_GLEngine.Disable(); } // Set processor affinity for the main thread. Switching cores is bad for stable frame rate DWORD curProcessor = GetCurrentProcessorNumberXP(); SetThreadAffinityMask(GetCurrentThread(), 1 << curProcessor); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); // Initialize GDI+ so we can make use of it ULONG_PTR m_gdiplusToken; // class member Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); }
bool CAdvThread::setAffinity() { #ifdef Q_OS_LINUX if(threadHandle != 0) { int j; for (j = 0; j < coreQuantity; j++) if(affinityData.coreMask & (1<<j)) CPU_SET(j, &cpuset); pthread_setaffinity_np(threadHandle, sizeof(cpu_set_t), &cpuset); } #else if(threadHandle != 0) { DWORD_PTR res = SetThreadAffinityMask(threadHandle, affinityData.coreMask); if (0 == res) { // failure } } #endif affinityData.coreChanged = 0; }
RakNetTimeNS RakNet::GetTimeNS( void ) { #if defined(_PS3) uint64_t curTime; if ( initialized == false) { ticksPerSecond = _PS3_GetTicksPerSecond(); // Use the function to get elapsed ticks, this is a macro. _PS3_GetElapsedTicks(curTime); uint64_t quotient, remainder; quotient=(curTime / ticksPerSecond); remainder=(curTime % ticksPerSecond); initialTime = (RakNetTimeNS) quotient*(RakNetTimeNS)1000000 + (remainder*(RakNetTimeNS)1000000 / ticksPerSecond); initialized = true; } #elif defined(_WIN32) // Win32 if ( initialized == false) { initialized = true; #if !defined(_WIN32_WCE) // Save the current process HANDLE mProc = GetCurrentProcess(); // Get the current Affinity #if _MSC_VER >= 1400 && defined (_M_X64) GetProcessAffinityMask(mProc, (PDWORD_PTR)&mProcMask, (PDWORD_PTR)&mSysMask); #else GetProcessAffinityMask(mProc, &mProcMask, &mSysMask); #endif mThread = GetCurrentThread(); #endif // !defined(_WIN32_WCE) QueryPerformanceFrequency( &yo ); } // 01/12/08 - According to the docs "The frequency cannot change while the system is running." so this shouldn't be necessary /* if (++queryCount==200) { // Set affinity to the first core SetThreadAffinityMask(mThread, 1); QueryPerformanceFrequency( &yo ); // Reset affinity SetThreadAffinityMask(mThread, mProcMask); queryCount=0; } */ #elif (defined(__GNUC__) || defined(__GCCXML__)) if ( initialized == false) { gettimeofday( &tp, 0 ); initialized=true; // I do this because otherwise RakNetTime in milliseconds won't work as it will underflow when dividing by 1000 to do the conversion initialTime = ( tp.tv_sec ) * (RakNetTimeNS) 1000000 + ( tp.tv_usec ); } #endif #if defined(_PS3) // Use the function to get elapsed ticks, this is a macro. _PS3_GetElapsedTicks(curTime); uint64_t quotient, remainder; quotient=(curTime / ticksPerSecond); remainder=(curTime % ticksPerSecond); curTime = (RakNetTimeNS) quotient*(RakNetTimeNS)1000000 + (remainder*(RakNetTimeNS)1000000 / ticksPerSecond); // Subtract from initialTime so the millisecond conversion does not underflow return curTime - initialTime; #elif defined(_WIN32) RakNetTimeNS curTime; static RakNetTimeNS lastQueryVal=(RakNetTimeNS)0; // static unsigned long lastTickCountVal = GetTickCount(); LARGE_INTEGER PerfVal; #if !defined(_WIN32_WCE) // Set affinity to the first core SetThreadAffinityMask(mThread, 1); #endif // !defined(_WIN32_WCE) // Docs: On a multiprocessor computer, it should not matter which processor is called. // However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function. // Query the timer QueryPerformanceCounter( &PerfVal ); #if !defined(_WIN32_WCE) // Reset affinity SetThreadAffinityMask(mThread, mProcMask); #endif // !defined(_WIN32_WCE) __int64 quotient, remainder; quotient=((PerfVal.QuadPart) / yo.QuadPart); remainder=((PerfVal.QuadPart) % yo.QuadPart); curTime = (RakNetTimeNS) quotient*(RakNetTimeNS)1000000 + (remainder*(RakNetTimeNS)1000000 / yo.QuadPart); // 08/26/08 - With the below workaround, the time seems to jump forward regardless. // Just make sure the time doesn't go backwards if (curTime < lastQueryVal) return lastQueryVal; lastQueryVal=curTime; /* #if !defined(_WIN32_WCE) if (lastQueryVal==0) { // First call lastQueryVal=curTime; return curTime; } // To workaround http://support.microsoft.com/kb/274323 where the timer can sometimes jump forward by hours or days unsigned long curTickCount = GetTickCount(); unsigned long elapsedTickCount = curTickCount - lastTickCountVal; RakNetTimeNS elapsedQueryVal = curTime - lastQueryVal; if (elapsedQueryVal/1000 > elapsedTickCount+100) { curTime=(RakNetTimeNS)lastQueryVal+(RakNetTimeNS)elapsedTickCount*(RakNetTimeNS)1000; } lastTickCountVal=curTickCount; lastQueryVal=curTime; #endif */ return curTime; #elif (defined(__GNUC__) || defined(__GCCXML__)) // GCC RakNetTimeNS curTime; gettimeofday( &tp, 0 ); curTime = ( tp.tv_sec ) * (RakNetTimeNS) 1000000 + ( tp.tv_usec ); // Subtract from initialTime so the millisecond conversion does not underflow return curTime - initialTime; #endif }
void b3Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo) { static int uniqueId = 0; uniqueId++; m_activeThreadStatus.resize(threadConstructionInfo.m_numThreads); m_completeHandles.resize(threadConstructionInfo.m_numThreads); m_maxNumTasks = threadConstructionInfo.m_numThreads; for (int i=0;i<threadConstructionInfo.m_numThreads;i++) { printf("starting thread %d\n",i); b3ThreadStatus& threadStatus = m_activeThreadStatus[i]; LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL; SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize; LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1; LPVOID lpParameter=&threadStatus; DWORD dwCreationFlags=0; LPDWORD lpThreadId=0; threadStatus.m_userPtr=0; sprintf(threadStatus.m_eventStartHandleName,"es%.8s%d%d",threadConstructionInfo.m_uniqueName,uniqueId,i); threadStatus.m_eventStartHandle = CreateEventA (0,false,false,threadStatus.m_eventStartHandleName); sprintf(threadStatus.m_eventCompletetHandleName,"ec%.8s%d%d",threadConstructionInfo.m_uniqueName,uniqueId,i); threadStatus.m_eventCompletetHandle = CreateEventA (0,false,false,threadStatus.m_eventCompletetHandleName); m_completeHandles[i] = threadStatus.m_eventCompletetHandle; HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId); switch(threadConstructionInfo.m_priority) { case 0: { SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST); break; } case 1: { SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL); break; } case 2: { SetThreadPriority(handle,THREAD_PRIORITY_BELOW_NORMAL); break; } default: { } } DWORD mask = 1; mask = 1<<mask; SetThreadAffinityMask(handle, mask); threadStatus.m_taskId = i; threadStatus.m_commandId = 0; threadStatus.m_status = 0; threadStatus.m_threadHandle = handle; threadStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; printf("started %s thread %d with threadHandle %p\n",threadConstructionInfo.m_uniqueName,i,handle); } }
int wthread_set_affinity_mask( wthread_t h, CPU_AFFINITY_SET* dwThreadAffinityMask) { return (int) SetThreadAffinityMask( ((threadContext*) h)->mThread, (DWORD_PTR) dwThreadAffinityMask ); }
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) { SetThreadAffinityMask (GetCurrentThread(), affinityMask); }
void jsInit() { #ifdef DEBUG_OUTPUT g_pDebugLog = fopen("JS_DEBUG.log", "w"); #endif //find number of cores SYSTEM_INFO sysInfo = { 0 }; GetSystemInfo(&sysInfo); g_numProcessors = sysInfo.dwNumberOfProcessors; //spawn fibers for (int i = 0; i < NUM_FIBERS; ++i) { g_fibers[i].fiber = CreateFiber(FIBER_STACK_SIZE, fiberRoutine, g_fibers + i); g_fibers[i].pNextInWaitList = NULL; g_fibers[i].status = UNUSED; g_pFiberPool[NUM_FIBERS - 1 - i] = g_fibers + i; } //init waiting fibers memset(g_waitingFibers, 0, sizeof(g_waitingFibers)); g_waitingFiberHead = 0; g_waitListTail.pFiber = NULL; g_waitListTail.pNextWaitingFiber = NULL; g_waitListTail.time = 0; //get performance frequency QueryPerformanceFrequency((LARGE_INTEGER*)&g_performanceFrequency); //init jobs for (int i = 2; i < MAX_JOBS; ++i) { g_jobs[i - 1].pNextJob = g_jobs + i; } g_pFreeJob = g_jobs + 1; g_pJobQueueHead = g_jobs; g_dummyJob.threadId = 0x0; g_dummyJob.pNextJob = g_pJobQueueHead; g_dummyJob.pName = "__dummy"; //spawn threads g_threadData = TlsAlloc(); for (int i = 0; i < g_numProcessors; ++i) { //create thread if (i == 0) { g_threads[0].handle = GetCurrentThread(); } else { g_threads[i].handle = CreateThread(NULL, 0, threadStart, g_threads + i, 0, NULL); } g_threads[i].id = 0x1 << i; g_threads[i].ppJobQueueTail = &(g_dummyJob.pNextJob); //lock thread to specific cpu SetThreadAffinityMask(g_threads[i].handle, 1 << i); } TlsSetValue(g_threadData, g_threads + 0); initCounterAllocator(); #ifdef DEBUG_OUTPUT fprintf(g_pDebugLog, "%lld \t jobsystem started\n", time(NULL)); #endif }
bool MScheduler::Init( uint32 numThreads ) { static const uint32 cProcessors = GetCPUThreadCount(); AX_ASSERT( cProcessors > 0 ); const uint32 cDesiredThreads = numThreads > 0 ? numThreads : cProcessors; const uint32 cThreads = cDesiredThreads >= kMaxWorkers ? kMaxWorkers : cDesiredThreads; for( uint32 i = 0; i < cThreads; ++i ) { #ifdef _MSC_VER # pragma warning( push ) # pragma warning( disable:4316 ) //object allocated on the heap may not be aligned 64 #endif m_pWorkers[ i ] = new LWorker( *this, i ); #ifdef _MSC_VER # pragma warning( pop ) #endif if( !AX_VERIFY_NOT_NULL( m_pWorkers[ i ] ) ) { while( i > 0 ) { delete m_pWorkers[ i - 1 ]; --i; } return false; } } #ifdef _WIN32 // Peg the main thread to one specific processor core for QueryPerformanceCounter() improvement SetThreadAffinityMask( GetCurrentThread(), 1<<0 ); #endif m_pThreads[ 0 ] = nullptr; for( uint32 i = 1; i < cThreads; ++i ) { m_pThreads[ i ] = new LWorkerThread( *m_pWorkers[ i ] ); if( !AX_VERIFY_NOT_NULL( m_pThreads[ i ] ) ) { while( i > 0 ) { delete m_pThreads[ i - 1 ]; --i; } for( i = 0; i < cThreads; ++i ) { delete m_pWorkers[ i ]; } return false; } #if AX_THREAD_MODEL == AX_THREAD_MODEL_WINDOWS const HANDLE hThread = m_pThreads[ i ]->GetNative_MSWin(); SetThreadAffinityMask( hThread, DWORD_PTR( 1 )<<i ); #endif } m_cWorkers = cThreads; m_cSleepingWorkers = 0; m_bIsQuitting = false; m_cFrameChains = 0; m_cFrameTasks = 0; #if !AX_ASYNC_LOCAL_WORK_ENABLED m_cSubmittedChains = 0; #endif #if !AX_ASYNC_PER_WORKER_IDLE_FLAG_ENABLED m_cIdleWorkers = m_cWorkers; #endif AX_MEMORY_BARRIER(); //must be set before threads start (this is just paranoia) for( uint32 i = 1; i < cThreads; ++i ) { m_pThreads[ i ]->Start(); } return true; }
void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) { SetThreadAffinityMask (GetCurrentThread(), affinityMask); }
DWORD get_affinity() { DWORD mask = SetThreadAffinityMask(GetCurrentThread(), 1); SetThreadAffinityMask(GetCurrentThread(), mask); return mask != 0 ? mask : -1; }
/* ================== WinMain ================== */ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) ); Sys_SetPhysicalWorkMemory( 192 << 20, 1024 << 20 ); Sys_GetCurrentMemoryStatus( exeLaunchMemoryStats ); #if 0 DWORD handler = (DWORD)_except_handler; __asm { // Build EXCEPTION_REGISTRATION record: push handler // Address of handler function push FS:[0] // Address of previous handler mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION } #endif win32.hInstance = hInstance; idStr::Copynz( sys_cmdline, lpCmdLine, sizeof( sys_cmdline ) ); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); for ( int i = 0; i < MAX_CRITICAL_SECTIONS; i++ ) { InitializeCriticalSection( &win32.criticalSections[i] ); } // make sure the timer is high precision, otherwise // NT gets 18ms resolution timeBeginPeriod( 1 ); // get the initial time base Sys_Milliseconds(); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag( 0 ); #endif // Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); Sys_FPU_SetPrecision( FPU_PRECISION_DOUBLE_EXTENDED ); common->Init( 0, NULL, lpCmdLine ); #if TEST_FPU_EXCEPTIONS != 0 common->Printf( Sys_FPU_GetState() ); #endif if ( win32.win_notaskkeys.GetInteger() ) { DisableTaskKeys( TRUE, FALSE, /*( win32.win_notaskkeys.GetInteger() == 2 )*/ FALSE ); } // hide or show the early console as necessary if ( win32.win_viewlog.GetInteger() ) { Sys_ShowConsole( 1, true ); } else { Sys_ShowConsole( 0, false ); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask( GetCurrentThread(), 1 ); #endif ::SetCursor( hcurSave ); ::SetFocus( win32.hWnd ); // main game loop while( 1 ) { Win_Frame(); #ifdef DEBUG Sys_MemFrame(); #endif // set exceptions, even if some crappy syscall changes them! Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); // run the game common->Frame(); } // never gets here return 0; }
Application::Application(const std::vector<CL_String> &args, lua_State *luaState) : mUpdated(false), mCompanyName(""), mApplicationName("bmgui"), mApplicationVersion(""), mQuit(false) { GAME_ASSERT(!args.empty()); #ifdef WIN32 // bind main thread to the first core for correct timings on some multicore systems SetThreadAffinityMask(GetCurrentThread(), 0x01); #endif // parse the command line arguments std::vector<char *> argv; for (std::vector<CL_String>::const_iterator it = args.begin(); it != args.end(); ++it) argv.push_back(const_cast<char *>(it->c_str())); CL_CommandLine commandLine; commandLine.set_help_indent(40); commandLine.add_doc("Graphical interface for Sibek balance machines"); commandLine.add_usage("[OPTION...]\n"); commandLine.add_option('g', "gateway", "ADDR", "Default gateway address"); commandLine.add_option('a', "local_addr", "ADDR", "Local address"); commandLine.add_option('m', "netmask", "ADDR", "Subnet mask"); commandLine.add_option('d', "dns", "ADDR", "DNS server address"); commandLine.add_option('i', "input_dev", "TYPE", "Input device type"); commandLine.add_option('s', "server_status", "FLAG", "Server status"); commandLine.add_option('u', "available_update_version", "VERSION", "Available update version"); commandLine.add_option('U', "updated", "FLAG", "Software update flag"); commandLine.add_option('W', "updatedfw", "FLAG", "Firmware update flag"); commandLine.add_option('D', "datadir", "PATH", "Path to the data directory"); commandLine.add_option('h', "help", "", "Show this help"); commandLine.parse_args(argv.size(), &argv[0]); #if defined(WIN32) || defined(__APPLE__) mDataDirectory = CL_Directory::get_resourcedata("bmgui", "data"); #else mDataDirectory = CL_PathHelp::add_trailing_slash(GAME_DATA_DIR); #endif while (commandLine.next()) { switch (commandLine.get_key()) { case 'g': mGateway = commandLine.get_argument(); break; case 'a': mLocalAddr = commandLine.get_argument(); break; case 'm': mNetmask = commandLine.get_argument(); break; case 'd': mDNS = commandLine.get_argument(); break; case 'i': mInputDev = commandLine.get_argument(); break; case 's': mServerStatus = commandLine.get_argument(); break; case 'u': mAvailableUpdateVersion = commandLine.get_argument(); break; case 'U': mUpdated = CL_StringHelp::text_to_bool(commandLine.get_argument()); break; case 'W': mFirmwareUpdated = commandLine.get_argument(); break; case 'D': mDataDirectory = CL_PathHelp::add_trailing_slash(commandLine.get_argument()); break; case 'h': commandLine.print_help(); quit(); return; } } /*CL_Console::write_line(cl_format("mGateway = %1", mGateway)); CL_Console::write_line(cl_format("mLocalAddr = %1", mLocalAddr)); CL_Console::write_line(cl_format("mNetmask = %1", mNetmask)); CL_Console::write_line(cl_format("mDNS = %1", mDNS)); CL_Console::write_line(cl_format("mInputDev = %1", mInputDev)); CL_Console::write_line(cl_format("mServerStatus = %1", mServerStatus)); CL_Console::write_line(cl_format("mAvailableUpdateVersion = %1", mAvailableUpdateVersion)); CL_Console::write_line(cl_format("mDataDirectory = %1", mDataDirectory));*/ // load the system profile Profile profile(""); CL_Console::write_line(cl_format("gateway = %1", profile.getString("gateway"))); CL_Console::write_line(cl_format("local_addr = %1", profile.getString("local_addr"))); CL_Console::write_line(cl_format("netmask = %1", profile.getString("netmask"))); CL_Console::write_line(cl_format("dns = %1", profile.getString("dns"))); CL_Console::write_line(cl_format("input_dev = %1", profile.getInt("input_dev"))); CL_Console::write_line(cl_format("server_status = %1", profile.getBool("server_status"))); CL_Console::write_line(cl_format("available_update_version = %1", profile.getString("available_update_version"))); CL_Console::write_line(cl_format("server_addr = %1", profile.getString("server_addr"))); CL_Console::write_line(cl_format("remote_control = %1", profile.getBool("remote_control"))); CL_Console::write_line(cl_format("ignored_update_version = %1", profile.getString("ignored_update_version"))); CL_Console::write_line(cl_format("cal_command = %1", profile.getString("cal_command"))); CL_Console::write_line(cl_format("language = %1", profile.getInt("language"))); CL_Console::write_line(cl_format("fullscreen = %1", profile.getBool("fullscreen"))); CL_Console::write_line(cl_format("width = %1", profile.getInt("width"))); CL_Console::write_line(cl_format("height = %1", profile.getInt("height"))); CL_Console::write_line(cl_format("sound_level = %1", profile.getInt("sound_level"))); // initialize all game subsystems mBalance = CL_SharedPtr<Balance>(new Balance(profile)); mDatabase = CL_SharedPtr<Database>(new Database(getConfigDirectory() + getApplicationName() + ".db")); mResourceManager = CL_SharedPtr<ResourceManager>(new ResourceManager()); mResourceQueue = CL_SharedPtr<ResourceQueue>(new ResourceQueue()); mGraphics = CL_SharedPtr<Graphics>(new Graphics(profile)); mKeyboard = CL_SharedPtr<Keyboard>(new Keyboard()); mMouse = CL_SharedPtr<Mouse>(new Mouse()); mSoundOutput = CL_SoundOutput(44100); mLuaScript = CL_SharedPtr<LuaScript>(new LuaScript("main.lua", luaState)); }
void CLIENT_STATE::start_cpu_benchmarks() { int i; if (benchmarks_running) { msg_printf(0, MSG_INFO, "Can't start benchmarks - they're already running" ); return; } if (config.skip_cpu_benchmarks) { if (log_flags.benchmark_debug) { msg_printf(0, MSG_INFO, "[benchmark] start_cpu_benchmarks(): Skipping CPU benchmarks" ); } cpu_benchmarks_set_defaults(); return; } msg_printf(NULL, MSG_INFO, "Running CPU benchmarks"); cpu_benchmarks_pending = false; bm_state = BM_FP_INIT; remove_benchmark_file(BM_TYPE_FP); remove_benchmark_file(BM_TYPE_INT); cpu_benchmarks_start = dtime(); if (benchmark_descs) { free(benchmark_descs); } bm_ncpus = ncpus; benchmark_descs = (BENCHMARK_DESC*)calloc(bm_ncpus, sizeof(BENCHMARK_DESC)); benchmarks_running = true; for (i=0; i<bm_ncpus; i++) { benchmark_descs[i].ordinal = i; benchmark_descs[i].done = false; benchmark_descs[i].error = false; #ifdef _WIN32 benchmark_descs[i].handle = CreateThread( NULL, 0, win_cpu_benchmarks, benchmark_descs+i, 0, &benchmark_descs[i].pid ); SetThreadAffinityMask(benchmark_descs[i].handle, 1<<i); SetThreadPriority(benchmark_descs[i].handle, THREAD_PRIORITY_IDLE); #else sprintf(benchmark_descs[i].filename, "%s_%d.xml", CPU_BENCHMARKS_FILE_NAME, i); PROCESS_ID pid = fork(); if (pid == 0) { #if HAVE_SETPRIORITY if (setpriority(PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY)) { perror("setpriority"); } #endif int retval = cpu_benchmarks(benchmark_descs+i); fflush(NULL); _exit(retval); } else { benchmark_descs[i].pid = pid; } #endif } }
void CannBallNetworkManager::EstablishPeerConnection(int playerNum) { UDPBroadcast broadcast; broadcast.SetMessage(to_string(CONNECT_MAGIC_NUM) + (playerNum == 1 ? "-PLAY1" : "-PLAY2")); broadcast.SetBroadcastPort(playerNum == 1 ? BROADCAST_PORT_P1 : BROADCAST_PORT_P2); SocketStream& peer = (playerNum == 1 ? m_player1 : m_player2); // TODO: REFACTOR THIS SHIT! broadcast.start(); while(true) // Not needed? Just call broadcast.waitForFinish()??? { if(!broadcast.isRunning()) { broadcast.waitForFinish(); cout << "OffworldNetManager P" << playerNum << ": Broadcast finished." << endl; SocketAddr peerAddr; if(!broadcast.GetPeerAddr(peerAddr)) { cout << "OffworldNetManager P" << playerNum << ": Broadcast failed to find peer." << endl; break; } cout << "OffworldNetManager P" << playerNum << ": Broadcast found peer. Attempting to connect" << endl; SocketAddr peerAddrStreamPort(peerAddr.GetIpAddr(), STREAM_PORT); Sleep(20); // Sleep gives peer time to setup their end. SetThreadAffinityMask(GetHandle(), 2); if(peer.Open(peerAddrStreamPort, 0)) { // managed to connect. cout << "Connection to peer [" << peer.GetPeerAddr().ToString() << "]" << endl; char recvBuffer[100000]; memset(recvBuffer, 0, 100000); if (peer.Recv(recvBuffer, 100000, 0) > 0) { std::stringstream ssBuffer(recvBuffer); std::string head; ssBuffer >> head; if(!head.compare("INIT")) { // Now read in entities. while(!ssBuffer.eof()) { std::string entityId; ssBuffer >> head; if(!head.compare("ENT")) { // Load in entity data. ssBuffer >> entityId; entityId =/* "P" + to_string(playerNum) + */entityId; // What is it? Circle, Square? std::string entityType; ssBuffer >> entityType; if(!entityType.compare("CIRC")) { LoadCircle(ssBuffer, entityId); // Update circle to follow if it matches the player we're following. if (playerNum == m_playerNum) { m_followBallStr = entityId; } // m_followBall = m_scene->GetEntitySafe(entityId); } else if(!entityType.compare("SQR")) { LoadSquare(ssBuffer, entityId); } else if (!entityType.compare("CAN")) { LoadCannon(ssBuffer, entityId); } } } int sentBytes = 0; //while(sentBytes < 3) //{ // Keep trying until sent all the data. Should send straight away without issues though. // NOTE: Probably best to put something like this within the Send buffer. sentBytes = peer.Send("ACK", 3, 0); //} } }
/* ================== WinMain ================== */ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { const HCURSOR hcurSave = ::SetCursor(LoadCursor(0, IDC_WAIT)); Sys_SetPhysicalWorkMemory(192 << 20, 1024 << 20); Sys_GetCurrentMemoryStatus(exeLaunchMemoryStats); #if 0 DWORD handler = (DWORD)_except_handler; __asm { // Build EXCEPTION_REGISTRATION record: push handler // Address of handler function push FS:[0] // Address of previous handler mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION } #endif win32.hInstance = hInstance; idStr::Copynz(sys_cmdline, lpCmdLine, sizeof(sys_cmdline)); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode(SEM_FAILCRITICALERRORS); for (int i = 0; i < MAX_CRITICAL_SECTIONS; i++) { InitializeCriticalSection(&win32.criticalSections[i]); } // get the initial time base Sys_Milliseconds(); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag(0); #endif // Sys_FPU_EnableExceptions( TEST_FPU_EXCEPTIONS ); Sys_FPU_SetPrecision(FPU_PRECISION_DOUBLE_EXTENDED); common->Init(0, NULL, lpCmdLine); #if TEST_FPU_EXCEPTIONS != 0 common->Printf(Sys_FPU_GetState()); #endif #ifndef ID_DEDICATED if (win32.win_notaskkeys.GetInteger()) { DisableTaskKeys(TRUE, FALSE, /*( win32.win_notaskkeys.GetInteger() == 2 )*/ FALSE); } #endif Sys_StartAsyncThread(); // hide or show the early console as necessary if (win32.win_viewlog.GetInteger() || com_skipRenderer.GetBool() || idAsyncNetwork::serverDedicated.GetInteger()) { Sys_ShowConsole(1, true); } else { Sys_ShowConsole(0, false); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask(GetCurrentThread(), 1); #endif ::SetCursor(hcurSave); // Launch the script debugger if (strstr(lpCmdLine, "+debugger")) { // DebuggerClientInit( lpCmdLine ); return 0; } ::SetFocus(win32.hWnd); // main game loop while (1) { Win_Frame(); #ifdef DEBUG Sys_MemFrame(); #endif // set exceptions, even if some crappy syscall changes them! Sys_FPU_EnableExceptions(TEST_FPU_EXCEPTIONS); #ifdef ID_ALLOW_TOOLS if (com_editors) { if (com_editors & EDITOR_GUI) { // GUI editor GUIEditorRun(); } else if (com_editors & EDITOR_RADIANT) { // Level Editor RadiantRun(); } else if (com_editors & EDITOR_MATERIAL) { //BSM Nerve: Add support for the material editor MaterialEditorRun(); } else { if (com_editors & EDITOR_LIGHT) { // in-game Light Editor LightEditorRun(); } if (com_editors & EDITOR_SOUND) { // in-game Sound Editor SoundEditorRun(); } if (com_editors & EDITOR_DECL) { // in-game Declaration Browser DeclBrowserRun(); } if (com_editors & EDITOR_AF) { // in-game Articulated Figure Editor AFEditorRun(); } if (com_editors & EDITOR_PARTICLE) { // in-game Particle Editor ParticleEditorRun(); } if (com_editors & EDITOR_SCRIPT) { // in-game Script Editor ScriptEditorRun(); } if (com_editors & EDITOR_PDA) { // in-game PDA Editor PDAEditorRun(); } } } #endif // run the game common->Frame(); } // never gets here return 0; }
int thread_bind_native(__unused_variable struct cpuid_state_t *state, __unused_variable uint32_t id) { #ifdef TARGET_OS_WINDOWS BOOL ret; HANDLE hThread = GetCurrentThread(); #if _WIN32_WINNT >= 0x0601 GROUP_AFFINITY affinity; ZeroMemory(&affinity, sizeof(GROUP_AFFINITY)); affinity.Group = id / 64; affinity.Mask = 1 << (id % 64); ret = SetThreadGroupAffinity(hThread, &affinity, NULL); #else DWORD mask; if (id > 32) return 1; mask = (1 << id); ret = SetThreadAffinityMask(hThread, mask); #endif return (ret != FALSE) ? 0 : 1; #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_FREEBSD) int ret; #ifdef CPU_SET_S size_t setsize = CPU_ALLOC_SIZE(MAX_CPUS); CPUSET_T *set = CPU_ALLOC(MAX_CPUS); pthread_t pth; pth = pthread_self(); CPU_ZERO_S(setsize, set); CPU_SET_S(id, setsize, set); ret = pthread_setaffinity_np(pth, setsize, set); CPU_FREE(set); #else size_t bits_per_set = sizeof(CPUSET_T) * 8; size_t bits_per_subset = sizeof(CPUSET_MASK_T) * 8; size_t setsize = sizeof(CPUSET_T) * (MAX_CPUS / bits_per_set); size_t set_id, subset_id; unsigned long long mask; CPUSET_T *set = malloc(setsize); pthread_t pth; pth = pthread_self(); for (set_id = 0; set_id < (MAX_CPUS / bits_per_set); set_id++) CPU_ZERO(&set[set_id]); set_id = id / bits_per_set; id %= bits_per_set; subset_id = id / bits_per_subset; id %= bits_per_subset; mask = 1ULL << (unsigned long long)id; ((unsigned long *)set[set_id].__bits)[subset_id] |= mask; ret = pthread_setaffinity_np(pth, setsize, set); free(set); #endif return (ret == 0) ? 0 : 1; #elif defined(TARGET_OS_MACOSX) #ifdef USE_CHUD return (utilBindThreadToCPU(id) == 0) ? 0 : 1; #else return 1; #endif #else #error "thread_bind_native() not defined for this platform" #endif }
static void bind_to_processor(int child_num) { /* This routine will bind the calling process to a particular */ /* processor. We are not choosy as to which processor, so it will be */ /* the process id mod the number of processors - shifted by one for */ /* those systems which name processor starting from one instead of */ /* zero. on those systems where I do not yet know how to bind a */ /* process to a processor, this routine will be a no-op raj 10/95 */ /* just as a reminder, this is *only* for the looper processes, not */ /* the actual measurement processes. those will, should, MUST float */ /* or not float from CPU to CPU as controlled by the operating */ /* system defaults. raj 12/95 */ #ifdef __hpux #include <sys/syscall.h> #include <sys/mp.h> int old_cpu = -2; if (debug) { fprintf(where, "child %d asking for CPU %d as pid %d with %d CPUs\n", child_num, (child_num % lib_num_loc_cpus), getpid(), lib_num_loc_cpus); fflush(where); } SETPROCESS((child_num % lib_num_loc_cpus), getpid()); return; #else #if defined(__sun) && defined(__SVR4) /* should only be Solaris */ #include <sys/processor.h> #include <sys/procset.h> int old_binding; if (debug) { fprintf(where, "bind_to_processor: child %d asking for CPU %d as pid %d with %d CPUs\n", child_num, (child_num % lib_num_loc_cpus), getpid(), lib_num_loc_cpus); fflush(where); } if (processor_bind(P_PID, getpid(), (child_num % lib_num_loc_cpus), &old_binding) != 0) { fprintf(where,"bind_to_processor: unable to perform processor binding\n"); fprintf(where," errno %d\n",errno); fflush(where); } return; #else #ifdef WIN32 if (!SetThreadAffinityMask(GetCurrentThread(), (ULONG_PTR)1 << (child_num % lib_num_loc_cpus))) { perror("SetThreadAffinityMask failed"); fflush(stderr); } if (debug) { fprintf(where, "bind_to_processor: child %d asking for CPU %d of %d CPUs\n", child_num, (child_num % lib_num_loc_cpus), lib_num_loc_cpus); fflush(where); } #endif return; #endif /* __sun && _SVR4 */ #endif /* __hpux */ }
void* LqThreadBase::BeginThreadHelper(void* ProcData) #endif { LqThreadBase* This = (LqThreadBase*)ProcData; This->IsStarted = true; This->StartThreadLocker.LockWrite(); // #if defined(LQPLATFORM_WINDOWS) pthread_setname_np(This->ThreadId(), This->Name); #elif defined(LQPLATFORM_LINUX) || defined(LQPLATFORM_ANDROID) pthread_setname_np(pthread_self(), This->Name); #elif defined(LQPLATFORM_FREEBSD) pthread_setname_np(pthread_self(), This->Name, nullptr); #elif defined(LQPLATFORM_APPLE) pthread_setname_np(This->Name); #endif if(This->Priority == LQTHREAD_PRIOR_NONE) { #if defined(LQPLATFORM_WINDOWS) This->Priority = __GetPrior(GetThreadPriority(GetCurrentThread())); #else sched_param schedparams; pthread_getschedparam(pthread_self(), LqDfltPtr(), &schedparams); This->Priority = __GetPrior(schedparams.sched_priority); #endif } else { #if defined(LQPLATFORM_WINDOWS) SetThreadPriority(GetCurrentThread(), __GetRealPrior(This->Priority)); #else sched_param schedparams; schedparams.sched_priority = __GetRealPrior(This->Priority); pthread_setschedparam(pthread_self(), SCHED_OTHER, &schedparams); #endif } if(This->AffinMask == 0) { #if defined(LQPLATFORM_WINDOWS) GROUP_AFFINITY ga = {0}; GetThreadGroupAffinity(GetCurrentThread(), &ga); This->AffinMask = ga.Mask; #elif !defined(LQPLATFORM_ANDROID) pthread_getaffinity_np(pthread_self(), sizeof(This->AffinMask), (cpu_set_t*)&This->AffinMask); #endif } else { #if defined(LQPLATFORM_WINDOWS) SetThreadAffinityMask(GetCurrentThread(), This->AffinMask); #elif !defined(LQPLATFORM_ANDROID) pthread_setaffinity_np(pthread_self(), sizeof(This->AffinMask), (const cpu_set_t*)&This->AffinMask); #endif } This->StartThreadLocker.UnlockWrite(); This->EnterHandler(This->UserData); //Call user defined handler //Enter main func This->BeginThread(); #ifdef LQPLATFORM_WINDOWS if(NameThread != nullptr) { free(NameThread); NameThread = nullptr; } #endif This->ExitHandler(This->UserData); This->StartThreadLocker.LockWrite(); #ifdef LQPLATFORM_WINDOWS CloseHandle((HANDLE)This->ThreadHandler); #endif This->CurThreadId = -((intptr_t)1); This->ThreadHandler = 0; This->StartThreadLocker.UnlockWrite(); #ifdef LQPLATFORM_WINDOWS return 0; #else return NULL; #endif }
virtual void Run() { SetName("ZLibCompressor"); #if defined (DURANGO) SetThreadAffinityMask(GetCurrentThread(), BIT(3)); #endif while(!m_bCancelled || !m_files.empty()) { m_event.Wait(); uint8* pZLibCompressedBuffer = AllocateBlock(); while(!m_files.empty()) { CFile* pFile = m_files.pop(); assert(pFile); PREFAST_ASSUME(pFile); while(!pFile->Closed() || !pFile->m_blocks.empty()) { if( pFile->m_blocks.empty() ) { CrySleep(1); // yield to give other threads a chance to do some work } while(!pFile->m_blocks.empty()) { SZLibBlock* block = pFile->m_blocks.pop(); assert(block); PREFAST_ASSUME(block); if(pFile->m_pCompressor->m_bUseZLibCompression) { size_t compressedLength = XMLCPB_ZLIB_BUFFER_SIZE; bool compressionOk = gEnv->pSystem->CompressDataBlock( block->m_pZLibBuffer, block->m_ZLibBufferSizeUsed, pZLibCompressedBuffer, compressedLength ); SZLibBlockHeader zlibHeader; zlibHeader.m_compressedSize = compressionOk ? compressedLength : SZLibBlockHeader::NO_ZLIB_USED; zlibHeader.m_uncompressedSize = block->m_ZLibBufferSizeUsed; pFile->m_bytesWrittenIntoFileUncompressed += block->m_ZLibBufferSizeUsed; pFile->Write( &zlibHeader, sizeof(SZLibBlockHeader) ); if (compressionOk) pFile->Write( pZLibCompressedBuffer, compressedLength ); else pFile->Write( block->m_pZLibBuffer, block->m_ZLibBufferSizeUsed ); } else { pFile->Write(block->m_pZLibBuffer, block->m_ZLibBufferSizeUsed); } delete block; } } pFile->Finish(); delete pFile; } FreeBlock(pZLibCompressedBuffer); } }
void PsychGetPrecisionTimerSeconds(double *secs) { double ss, ticks, diff; static LARGE_INTEGER counterFreq; LARGE_INTEGER count; static double oss; static double oldticks; static double lastSlowcheckTimeSecs; static double lastSlowcheckTimeTicks; psych_uint32 tick1, tick2, hangcount; psych_uint64 curRawticks; // First time init of timeglue: Set up system for high precision timing, // and enable workarounds for broken systems: if (firstTime) { // Init state to defaults: oss=0.0; oldticks=0.0; lastSlowcheckTimeSecs = -1; lastSlowcheckTimeTicks = -1; // Switch the system into high resolution timing mode, i.e., // 1 khZ timer interrupts aka 1 msec timer resolution, for both, // the Sleep() command and TimeGetTime() queries. This way, our hybrid // sleep-waiting algorithm for PsychWaitUntilSeconds() can work with // tight busy-wait transition thresholds and doesn't burn too much // CPU time. The timeGetTime() function then gets sufficient granularity - // 1 msecs - to be a good reference for our correctness/consistency // checks on the high precision timer, and it is a sufficient fallback // in case of broken timers. // The drawback is increased general interrupt load due to the 1 kHZ IRQ's... if ((timeBeginPeriod(1)!=TIMERR_NOERROR) && (schedulingtrouble == FALSE)) { // High precision mode failed! Output warning on first failed invocation... schedulingtrouble = TRUE; printf("PTBCRITICAL -ERROR: PsychTimeGlue - Win32 syscall timeBeginPeriod(1) failed!!! Timing will be inaccurate.\n"); printf("PTBCRITICAL -ERROR: Time measurement may be highly unreliable - or even false!!!\n"); printf("PTBCRITICAL -ERROR: FIX YOUR SYSTEM! In its current state its not useable for conduction of studies!!!\n"); printf("PTBCRITICAL -ERROR: Check the FAQ section of the Psychtoolbox Wiki for more information.\n"); // Increase switching threshold to 10 msecs to take low timer resolution into account: sleepwait_threshold = 0.010; } // This command timeEndPeriod(1); should be used when flushing the MEX file, but // we don't do it. Once a PsychTimeGlue function was called, we leave Matlab at // high timing precision mode and rely on the OS to revert to standard Windoze // behaviour, once the Matlab application is quit/terminated. // Next step for broken systems: Bind our Matlab interpreter/PTB main thread to the // first cpu core in the system. The only known way to make sure we don't get time // readings from different TSCs due to our thread jumping between cpu's. TSC's on // a multi-core system are not guaranteed to be synchronized, so if TSC is our timebase, // this could lead to time inconsistencies - even time going backwards between queries!!! // Drawback: We may not make optimal use of a multi-core system. On Vista and later, we assume // everything will be fine, but still perform consistency checks at each call to PsychGetPrecisionTimerSeconds(): if (!PsychIsMSVista()) { if (SetThreadAffinityMask(GetCurrentThread(), 1)==0) { // Binding failed! Output warning on first failed invocation... schedulingtrouble = TRUE; printf("PTBCRITICAL -ERROR: PsychTimeGlue - Win32 syscall SetThreadAffinityMask() failed!!! Timing could be inaccurate.\n"); printf("PTBCRITICAL -ERROR: Time measurement may be highly unreliable - or even false!!!\n"); printf("PTBCRITICAL -ERROR: FIX YOUR SYSTEM! In its current state its not useable for conduction of studies!!!\n"); printf("PTBCRITICAL -ERROR: Check the FAQ section of the Psychtoolbox Wiki for more information.\n"); } } // Sleep us at least 10 msecs, so the system will reschedule us, with the // thread affinity mask above applied. Don't know if this is needed, but // better safe than sorry: Sleep(10); // Spin-Wait until timeGetTime() has switched to 1 msec resolution: hangcount = 0; while(hangcount < 100) { tick1 = (psych_uint32) timeGetTime(); while((tick2=(psych_uint32) timeGetTime()) == tick1); if ((tick2 > tick1) && (tick2 - tick1 == 1)) break; hangcount++; } if (hangcount >= 100) { // Totally foobared system! Output another warning but try to go on. Checks further below in code // will trigger and provide counter measures - as far as this is possible with such a screwed system :-( printf("PTB-CRITICAL WARNING! Timing code detected problems with the low precision TIMER in your system hardware!\n"); printf("PTB-CRITICAL WARNING! It doesn't run at the requested rate of 1 tick per millisecond. Interrupt problems?!?\n"); printf("PTB-CRITICAL WARNING! Your system is somewhat screwed up wrt. timing!\n"); printf("PTB-CRITICAL WARNING! It is NOT RECOMMENDED to continue using this machine for studies that require high\n"); printf("PTB-CRITICAL WARNING! timing precision in stimulus onset or response collection. No guarantees can be made\n"); printf("PTB-CRITICAL WARNING! wrt. to timing or correctness of any timestamps or stimulus onsets!\n"); printf("PTB-CRITICAL WARNING! Check the FAQ section of the Psychtoolbox Wiki for more information.\n\n"); } // Ok, now timeGetTime() should have the requested 1 msec increment rate. // Ok, this is a dumb solution, but at least sort of robust. The // proper solution will have to wait for the next 'beta' release cycle. // We don't allow to use any timing function on a Windoze system that // has more than 48 days of uptime. Rationale: At 49.8 days, the 32 bit // tick counter will wrap around and leave our fallback- and reference // timebase in an undefined state. Implementing proper wraparound handling // for inifinite uptimes is not simple, due to PTB's modular nature and // some special flaws of Windoze. Anyway, 48 days uptime is unlikely // anyway, unless the user doesn't perform regular system updates... if (((double) timeGetTime() * 0.001) > (3600 * 24 * 48)) { // Uptime exceeds 48 days. Say user this is a no no: printf("PTB-ERROR: Your system is running since over 48 days without a reboot. Due to some\n"); printf("PTB-ERROR: pretty disgusting design flaws in the Windows operating system, timing\n"); printf("PTB-ERROR: will become unreliable or wrong at uptimes of more than 49 days.\n"); printf("PTB-ERROR: Therefore PTB will not continue executing any time related function unless\n"); printf("PTB-ERROR: you reboot your machine now.\n\n"); PsychErrorExitMsg(PsychError_user, "Maximum allowable uptime for Windows exceeded. Please reboot your system."); } // Is the high-precision timer supported? counterExists = QueryPerformanceFrequency(&counterFreq); if (counterExists) { // Initialize old counter values to now: if (0 == QueryPerformanceCounter(&count)) { Timertrouble = TRUE; counterExists = FALSE; oss = 0; printf("PTB-CRITICAL WARNING! Timing code detected problems with the high precision TIMER in your system hardware!\n"); printf("PTB-CRITICAL WARNING! Initial call to QueryPerformanceCounter() failed!\n"); printf("PTB-CRITICAL WARNING! Will switch back to lower precision/resolution timer (only +/-1 millisecond accuracy at best).\n"); printf("PTB-CRITICAL WARNING! This can cause a cascade of errors, failures and problems in any timing related functions!!\n\n"); printf("PTB-CRITICAL WARNING! It is NOT RECOMMENDED to continue using this machine for studies that require any\n"); printf("PTB-CRITICAL WARNING! timing precision in stimulus onset or response collection. No guarantees can be made\n"); printf("PTB-CRITICAL WARNING! wrt. to timing or correctness of any timestamps or stimulus onsets!\n"); printf("PTB-CRITICAL WARNING! Read 'help GetSecsTest' and run GetSecsTest for further diagnosis and troubleshooting.\n"); printf("PTB-CRITICAL WARNING! It may also help to restart the machine to see if the problem is transient.\n"); printf("PTB-CRITICAL WARNING! Also check the FAQ section of the Psychtoolbox Wiki for more information.\n\n"); } else { oss = ((double)count.QuadPart)/((double)counterFreq.QuadPart); } } // Sleep us another 10 msecs to make sure there is a significant difference between // first invocation and successive invocations: Sleep(10); } // Need to acquire our timelock before we continue, for atomic timestamping and as we will soon access shared data structures: EnterCriticalSection(&time_lock); // Query system time of low resolution counter: curRawticks = timeGetTime(); // Query Performance counter if it is supported: if ((counterExists) && (0 == QueryPerformanceCounter(&count))) { Timertrouble = TRUE; printf("PTB-CRITICAL WARNING! Timing code detected problems with the high precision TIMER in your system hardware!\n"); printf("PTB-CRITICAL WARNING! A call to QueryPerformanceCounter() failed!\n"); printf("PTB-CRITICAL WARNING! Will switch back to lower precision/resolution timer (only +/-1 millisecond accuracy at best).\n"); printf("PTB-CRITICAL WARNING! It is NOT RECOMMENDED to continue using this machine for studies that require high\n"); printf("PTB-CRITICAL WARNING! timing precision in stimulus onset or response collection. No guarantees can be made\n"); printf("PTB-CRITICAL WARNING! wrt. to timing or correctness of any timestamps or stimulus onsets!\n"); printf("PTB-CRITICAL WARNING! Read 'help GetSecsTest' and run GetSecsTest for further diagnosis and troubleshooting.\n"); printf("PTB-CRITICAL WARNING! It may also help to restart the machine to see if the problem is transient.\n"); printf("PTB-CRITICAL WARNING! Also check the FAQ section of the Psychtoolbox Wiki for more information.\n\n"); } // Convert to ticks in seconds for further processing: ticks = ((double) (psych_int64) curRawticks) * 0.001; tickInSecsAtLastQuery = ticks; // Start actual processing of result of QueryPerformanceCounter(). We do this here, // deferred under protection of the time_lock lock. The Query has been done above, // outside of the critical section, so multiple threads can't collide on a contended // time_lock and get delayed needlessly: if (counterExists) { ss = ((double)count.QuadPart)/((double)counterFreq.QuadPart); timeInSecsAtLastQuery = ss; // Initialize base time for slow consistency checks at first invocation: if (firstTime) { lastSlowcheckTimeSecs = ss; lastSlowcheckTimeTicks = ticks; } // Compute difference (disagreement over elapsed time since last call) between high-precision // timer and low-precision timer: diff = ((ss - oss) - (ticks - oldticks)); // We don't perform the inter-timer agreement check at first invokation - Thread scheduling etc. needs to settle, // as well as the timeBeginPeriod(1) call above... if (!Timertrouble && !firstTime) { // No timer problems yet. Perform checks: // Time running backwards? // We allow for a slack of 10 nanoseconds. Not sure if this is a good idea, as it weakens the test // to avoid aggressive fallback on flaky but sort of still useable hardware. Some modern cpu's showed // this effect, but the fallback would have been worse... if (ss < (oss - 1e-8)) { Timertrouble = TRUE; printf("PTB-CRITICAL WARNING! Timing code detected problems with the high precision TIMER in your system hardware!\n"); printf("PTB-CRITICAL WARNING! Apparently time is reported as RUNNING BACKWARDS. (Timewarp Delta: %0.30f secs.)\n", ss - oss); printf("PTB-CRITICAL WARNING! One reason could be a multi-core system with unsynchronized TSC's and buggy platform drivers.\n"); printf("PTB-CRITICAL WARNING! Will switch back to lower precision/resolution timer (only +/-1 millisecond accuracy at best).\n"); } // The old and new high res. timer should not // disagree in their increment since last call by more than 250 msecs. If they do, // this means that the high precision timer leaped forward, which indicates a faulty // Southbridge controller in the machines host chipset - Not a good basis for high precision timing. // See Microsoft Knowledge base article Nr. 274323 for further explanation and a list of known bad // chipsets. // We actually allow for an additional slack of 0.000200 seconds or 200 ppm for each // elapsed second of the test interval. This to account for clock drift of up to 200 ppm // between both clocks. According to some docs, 200 ppm drift are possible under MS-Windows! if ( diff > ( 0.25 + ((ticks - oldticks) * 0.000200 ) ) ) { // Mismatch between performance counter and tick counter detected! // Performance counter is faulty! Report this to user, then continue // by use of the older tick counter as a band-aid. Timertrouble = TRUE; printf("PTB-CRITICAL WARNING! Timing code detected a FAULTY high precision TIMER in your system hardware!(Delta %0.30f secs).\n", diff); printf("PTB-CRITICAL WARNING! Seems the timer sometimes randomly jumps forward in time by over 250 msecs!"); printf("PTB-CRITICAL WARNING! Will switch back to lower precision/resolution timer (only +/-1 millisecond accuracy at best).\n"); printf("PTB-CRITICAL WARNING! For more information see Microsoft knowledge base article Nr. 274323.\n"); printf("PTB-CRITICAL WARNING! http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q274323&\n\n"); } // We check for lags of QPC() wrt. to tick count at intervals of greater than 1 second, ie. only if // this query and the last one are at least 1 second spaced apart in time. This is kind of a low-pass // filter to account for the fact that the tick counter itself can sometimes lose a bit of time due // to lost timer interrupts, and then jump forward in time by a couple of milliseconds when some // system service detects the lost interrupts and accounts for them by incrementing time by multiple // ticks at a single IRQ. Here we check over a longer period to make it less likely that such transients // show up. We apply a much more generous lag threshold as well, so we can compensate for transient timer // jumps of up to 50 msecs. if ((ticks - lastSlowcheckTimeTicks) >= 1.0) { // Check for lags: A lag of multiple msec is normal and expected due to the measurement method. diff = ((ss - lastSlowcheckTimeSecs) - (ticks - lastSlowcheckTimeTicks)); // Let's check for a lag exceeding 5% of the duration of the check interval, so we have a bit of headroom to the expected lag: if (diff < -0.05 * (ticks - lastSlowcheckTimeTicks)) { // Mismatch between performance counter and tick counter detected! // Performance counter is lagging behind realtime! Report this to user, then continue // by use of the older tick counter as a band-aid. Timertrouble = TRUE; printf("PTB-CRITICAL WARNING! Timing code detected a LAGGING high precision TIMER in your system hardware! (Delta %0.30f secs).\n", diff); printf("PTB-CRITICAL WARNING! Seems that the timer sometimes stops or slows down! This can happen on systems with\n"); printf("PTB-CRITICAL WARNING! processor power management (cpu throttling) and defective platform drivers.\n"); printf("PTB-CRITICAL WARNING! Will switch back to lower precision/resolution timer (only +/-1 millisecond accuracy at best).\n"); printf("PTB-CRITICAL WARNING! Please try if disabling all power management features of your system helps...\n"); } // Update timestamps of last check: lastSlowcheckTimeSecs = ss; lastSlowcheckTimeTicks = ticks; } if (Timertrouble) { // Faulty high precision clock detected. We switch to the low-res clock for the rest of the session, in the hope that // the low-res clock is less broken than the high-res clock. // // We need to make the switch as seamless as possible. As the low-res and high-res clocks have different "zero seconds" // reference points, we need to compute the absolute offset between both and then apply that offset to the reported low // res clock time to compensate for it. This should reduce any jumps or jerks in the monotonic system time as perceived // by clients of this function, especially the PsychWaitUntilSeconds() and PsychWaitIntervalSeconds() functions, which // could hang for a very long time if the switch between high-res and low-res clock happens at the wrong moment. lowToHiBiasSecs = ss - ticks; // More info for user at first detection of trouble: printf("PTB-CRITICAL WARNING! It is NOT RECOMMENDED to continue using this machine for studies that require high\n"); printf("PTB-CRITICAL WARNING! timing precision in stimulus onset or response collection. No guarantees can be made\n"); printf("PTB-CRITICAL WARNING! wrt. to timing or correctness of any timestamps or stimulus onsets!\n"); printf("PTB-CRITICAL WARNING! Read 'help GetSecsTest' and run GetSecsTest for further diagnosis and troubleshooting.\n"); printf("PTB-CRITICAL WARNING! It may also help to restart the machine to see if the problem is transient.\n"); printf("PTB-CRITICAL WARNING! Also check the FAQ section of the Psychtoolbox Wiki for more information.\n\n"); } } // All checks done: Prepare old values for new iteration: oss = ss; oldticks = ticks; // Ok, is the timer finally considered safe to use? if (!Timertrouble) { // All checks passed: ss is the valid return value: ss = ss; } else { // Performance counter works unreliably: Fall back to result of timeGetTime(). // This only has 1 msec resolution at best, but at least it works (somewhat...). // // Correct for time bias between low-res clock and high-res clock to fake a time // that looks to clients as if it comes from the high-res clock, albeit with a lower // resolution of only 1 msec at best: ss = ticks + lowToHiBiasSecs; } // ========= End of high precision timestamping. ========= } else { // ========= Low precision fallback path for ancient machines: 1 khz tick counter: ========= ss = ticks; timeInSecsAtLastQuery = -1; } // Finally assign time value: *secs= ss; // Clear the firstTime flag - this was the first time, maybe. firstTime = FALSE; // Need to release our timelock - Done with access to shared data: LeaveCriticalSection(&time_lock); return; }
bool set_affinity(DWORD mask) { return SetThreadAffinityMask(GetCurrentThread(), mask) != 0; }
void TBag::run() { for (int i = 0; i < _num_proc; ++i) { _events[i]._offset=i; _tasks[i] = createTask(); _tasks[i]->offset=i; _bids.push(_tasks[i]); } Evt *e; Task *task; double duration; _busy=false; _curr_time = 0.0; _user_time=0.0; _event._type = MASTER; plan(&_event, 0.0); ///////// установка привязки if(!SetThreadAffinityMask(GetCurrentThread(),0x1)){ printf("\nSetThreadAffinityMask FAILED\n");return; } ///////// установка приоритета if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST)){ printf("\nTHREAD_PRIORITY_ABOVE_NORMAL FAILED\n");return; } LARGE_INTEGER frequency; LARGE_INTEGER t1,t2; QueryPerformanceFrequency(&frequency); QueryPerformanceCounter(&t1); while(!_calendar.empty()) { e=_calendar.top(); _calendar.pop(); assert(_curr_time <= e->_plan_time); _curr_time=e->_plan_time; e->_planed=false; switch(e->_type) { case MASTER: if (!_results.empty()) { _busy=true; task = _results.front(); _results.pop(); put(task,duration); _user_time+=duration; _events[task->offset]._type=PUT; plan(&_events[task->offset],duration); } else if(!_bids.empty()) { _busy=true; task = _bids.front(); _bids.pop(); _events[task->offset]._if_job=if_job(duration); _user_time+=duration; _events[task->offset]._type=IF_JOB; plan(&_events[task->offset],duration); } e->_type=DEFAULT; break; case IF_JOB: if(e->_if_job){ get(_tasks[e->_offset],duration); _user_time+=duration; e->_type=GET; plan(e,duration); } else{ _bids.push(_tasks[e->_offset]); e->_type=DEFAULT; _busy=false; } break; case PUT: e->_if_job=if_job(duration); _user_time+=duration; e->_type=IF_JOB; plan(e,duration); break; case GET: proc(_tasks[e->_offset],duration); _user_time+=duration; e->_type=PROC; plan(e,duration); _event._type=MASTER; plan(&_event,0); _busy=false; break; case PROC: _results.push(_tasks[e->_offset]); e->_type=DEFAULT; if(!_busy && _event._type==DEFAULT){ _event._type=MASTER; plan(&_event,0); } break; case DEFAULT: assert(0); break; } } QueryPerformanceCounter(&t2); _duration=(double)(t2.QuadPart-t1.QuadPart)/frequency.QuadPart; for (int i = 0; i < _num_proc; ++i) delete _tasks[i]; }
portBASE_TYPE xPortStartScheduler( void ) { void *pvHandle; long lSuccess = pdPASS; xThreadState *pxThreadState; /* Install the interrupt handlers used by the scheduler itself. */ vPortSetInterruptHandler( portINTERRUPT_YIELD, prvProcessYieldInterrupt ); vPortSetInterruptHandler( portINTERRUPT_TICK, prvProcessTickInterrupt ); vPortSetInterruptHandler( portINTERRUPT_DELETE_THREAD, prvProcessDeleteThreadInterrupt ); /* Create the events and mutexes that are used to synchronise all the threads. */ pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL ); pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) ) { lSuccess = pdFAIL; } /* Set the priority of this thread such that it is above the priority of the threads that run tasks. This higher priority is required to ensure simulated interrupts take priority over tasks. */ pvHandle = GetCurrentThread(); if( pvHandle == NULL ) { lSuccess = pdFAIL; } if( lSuccess == pdPASS ) { if( SetThreadPriority( pvHandle, THREAD_PRIORITY_NORMAL ) == 0 ) { lSuccess = pdFAIL; } SetThreadPriorityBoost( pvHandle, TRUE ); SetThreadAffinityMask( pvHandle, 0x01 ); } if( lSuccess == pdPASS ) { /* Start the thread that simulates the timer peripheral to generate tick interrupts. The priority is set below that of the simulated interrupt handler so the interrupt event mutex is used for the handshake / overrun protection. */ pvHandle = CreateThread( NULL, 0, prvSimulatedPeripheralTimer, NULL, 0, NULL ); if( pvHandle != NULL ) { SetThreadPriority( pvHandle, THREAD_PRIORITY_BELOW_NORMAL ); SetThreadPriorityBoost( pvHandle, TRUE ); SetThreadAffinityMask( pvHandle, 0x01 ); } /* Start the highest priority task by obtaining its associated thread state structure, in which is stored the thread handle. */ pxThreadState = ( xThreadState * ) *( ( unsigned long * ) pxCurrentTCB ); ulCriticalNesting = portNO_CRITICAL_NESTING; /* Bump up the priority of the thread that is going to run, in the hope that this will asist in getting the Windows thread scheduler to behave as an embedded engineer might expect. */ ResumeThread( pxThreadState->pvThread ); /* Handle all simulated interrupts - including yield requests and simulated ticks. */ prvProcessSimulatedInterrupts(); } /* Would not expect to return from prvProcessSimulatedInterrupts(), so should not get here. */ return 0; }
/* ================== WinMain ================== */ int main(int argc, char *argv[]) { const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) ); Sys_SetPhysicalWorkMemory( 192 << 20, 1024 << 20 ); win32.hInstance = GetModuleHandle(NULL); // done before Com/Sys_Init since we need this for error output Sys_CreateConsole(); // no abort/retry/fail errors SetErrorMode( SEM_FAILCRITICALERRORS ); #ifdef DEBUG // disable the painfully slow MS heap check every 1024 allocs _CrtSetDbgFlag( 0 ); #endif if ( argc > 1 ) { common->Init( argc-1, &argv[1] ); } else { common->Init( 0, NULL ); } // hide or show the early console as necessary if ( win32.win_viewlog.GetInteger() || com_skipRenderer.GetBool() || idAsyncNetwork::serverDedicated.GetInteger() ) { Sys_ShowConsole( 1, true ); } else { Sys_ShowConsole( 0, false ); } #ifdef SET_THREAD_AFFINITY // give the main thread an affinity for the first cpu SetThreadAffinityMask( GetCurrentThread(), 1 ); #endif ::SetCursor( hcurSave ); // Launch the script debugger if ( strstr( GetCommandLine(), "+debugger" ) ) { // DebuggerClientInit( lpCmdLine ); return 0; } ::SetFocus( win32.hWnd ); // main game loop while( 1 ) { Win_Frame(); #ifdef ID_ALLOW_TOOLS if ( com_editors ) { if ( com_editors & EDITOR_GUI ) { // GUI editor GUIEditorRun(); } else if ( com_editors & EDITOR_RADIANT ) { // Level Editor RadiantRun(); } else if (com_editors & EDITOR_MATERIAL ) { //BSM Nerve: Add support for the material editor MaterialEditorRun(); } else { if ( com_editors & EDITOR_LIGHT ) { // in-game Light Editor LightEditorRun(); } if ( com_editors & EDITOR_SOUND ) { // in-game Sound Editor SoundEditorRun(); } if ( com_editors & EDITOR_DECL ) { // in-game Declaration Browser DeclBrowserRun(); } if ( com_editors & EDITOR_AF ) { // in-game Articulated Figure Editor AFEditorRun(); } if ( com_editors & EDITOR_PARTICLE ) { // in-game Particle Editor ParticleEditorRun(); } if ( com_editors & EDITOR_SCRIPT ) { // in-game Script Editor ScriptEditorRun(); } if ( com_editors & EDITOR_PDA ) { // in-game PDA Editor PDAEditorRun(); } } } #endif // run the game common->Frame(); } // never gets here return 0; }