int main(int argc, char *argv[]) { HANDLE hThread; DWORD IDThread; LARGE_INTEGER due; ZeroMemory(&due, sizeof(LARGE_INTEGER)); due.QuadPart = -20000000; // 2 - секунды перед стартом таймера hTimer = CreateWaitableTimer(NULL, FALSE, L"MyTimer"); if (hTimer == NULL) { cout << "error CreateWaitableTimer" << endl; return GetLastError(); } if (!SetWaitableTimer(hTimer, &due, 1000, NULL, NULL, 0)) { // дальше повтор с интервалов 1 -сек cout << "error SetWaitableTimer" << endl; return GetLastError(); } hThread = CreateThread(NULL, 0, Thread, NULL, 0, &IDThread); if (hThread == NULL) return GetLastError(); while (!GetAsyncKeyState(VK_ESCAPE)); // чтобы не завершилась приложение пускай ждёт ESC aborts = FALSE; // пускаем сброс цикла в поток для завершения CloseHandle(hThread); CancelWaitableTimer(hTimer); CloseHandle(hTimer); return 0; }
void CWASAPIRenderFilter::CancelDataEvent() { if (!m_pSettings->m_bWASAPIUseEventMode) { CancelWaitableTimer(m_hDataEvent); if (CancelWaitableTimer(m_hDataEvent) == 0) { DWORD error = GetLastError(); Log("WASAPIRenderFilter::CancelDataEvent - CancelWaitableTimer failed: %d", error); } } }
ULONG CALLBACK PerfWorkItem( IN PVOID Context ) { ULONG Status; HANDLE TimerHandle; LARGE_INTEGER DueTime; HANDLE WaitHandle[2]; TimerHandle = CreateWaitableTimer(NULL, FALSE, NULL); // // N.B. DueTime is set at 100ns granularity, check // MSDN for further details. // DueTime.QuadPart = -10000 * 1000; Status = SetWaitableTimer(TimerHandle, &DueTime, 1000, NULL, NULL, FALSE); ASSERT(Status); if (Status != TRUE) { Status = GetLastError(); CancelWaitableTimer(TimerHandle); CloseHandle(TimerHandle); return Status; } WaitHandle[0] = TimerHandle; WaitHandle[1] = PerfStopEvent; __try { while (TRUE) { Status = WaitForMultipleObjects(2, WaitHandle, FALSE, INFINITE); if (Status == WAIT_OBJECT_0) { PerfUpdateInformation(); } if (Status == WAIT_OBJECT_0 + 1) { break; } } } __except(EXCEPTION_EXECUTE_HANDLER) { } CancelWaitableTimer(TimerHandle); CloseHandle(TimerHandle); return 0; }
void StopLong(sDIALOG_long * sd) { IMLOG("*Stop Long" , longReference); // if (sd->flag & DLONG_BLOCKING) { longReference--; if (longReference<=0) CancelWaitableTimer(timerLong); // } if (sd->timeoutProc) { CancelWaitableTimer(sd->timeoutHandle); CloseHandle(sd->timeoutHandle); sd->timeoutProc(TIMEOUTT_END , sd); } }
void COverlayRenderer::CancelTimers() { if (m_hOverlayTimerIG != NULL && CancelWaitableTimer(m_hOverlayTimerIG) == 0) { DWORD error = GetLastError(); LogDebug("COverlayRenderer::CancelTimers - CancelWaitableTimer failed: %d", error); } if (m_hOverlayTimerPG != NULL && CancelWaitableTimer(m_hOverlayTimerPG) == 0) { DWORD error = GetLastError(); LogDebug("COverlayRenderer::CancelTimers - CancelWaitableTimer failed: %d", error); } }
static void do_replay(void) { HDC dc; struct timeval delay; LARGE_INTEGER del; again: if (play_state!=2) { set_buttons(0); CancelWaitableTimer(timer); return; } EnterCriticalSection(&vt_mutex); replay_play(&delay); draw_size(); dc=GetDC(termwnd); draw_vt(dc, chx*vt->sx, chy*vt->sy, vt); ReleaseDC(termwnd, dc); LeaveCriticalSection(&vt_mutex); set_prog(); if (play_state!=2) { set_buttons(1); // finished return; } del.QuadPart=delay.tv_sec; del.QuadPart*=1000000; del.QuadPart+=delay.tv_usec; if (del.QuadPart<=0) goto again; del.QuadPart*=-10; SetWaitableTimer(timer, &del, 0, 0, 0, 0); set_buttons(0); }
HOOKFUNC BOOL WINAPI MyCancelWaitableTimer(HANDLE hTimer) { ENTER(); BOOL rv = CancelWaitableTimer(hTimer); LEAVE(rv); return rv; }
//--------------------------------------------------------------------------- void __TROPICALL BTP_Tempo::AlterarAtivo(bool temp) throw(BTP_Excecao*) { if(temp) { LARGE_INTEGER Preset; Preset.QuadPart=-(intervalo*10000); int temp1=0; if(!manual)temp1=intervalo; if(!SetWaitableTimer(htimer,&Preset,temp1,NULL,NULL,false)) { throw new BTP_Excecao(this, "Erro iniciar o Temporizador"); } ativo=true; } else { if(!CancelWaitableTimer(htimer)) { throw new BTP_Excecao(this, "Erro ao parar o temporizador"); } ativo=false; } }
static void VGA_DeinstallTimer(void) { if (VGA_timer_thread) { /* * Make sure the update thread is not holding * system resources when we kill it. * * Now, we only need to worry about update thread * getting terminated while in EnterCriticalSection * or WaitForMultipleObjectsEx. * * FIXME: Is this a problem? */ EnterCriticalSection(&vga_lock); CancelWaitableTimer( VGA_timer ); CloseHandle( VGA_timer ); TerminateThread( VGA_timer_thread, 0 ); CloseHandle( VGA_timer_thread ); VGA_timer_thread = 0; LeaveCriticalSection(&vga_lock); /* * Synchronize display. This makes sure that * changes to display become visible even if program * terminates before update thread had time to run. */ VGA_Poll( 0, 0, 0 ); } }
void P_SEND_Timer_IMPL(PRT_MACHINEINST *context, PRT_VALUE *evnt, PRT_VALUE *payload, PRT_BOOLEAN doTransfer) { printf("Entering P_SEND_Timer_IMPL\n"); PRT_VALUE *ev; BOOL success; TimerContext *timerContext = (TimerContext *)context->extContext; if (!inStart && evnt->valueUnion.ev == P_EVENT_START) { printf("Timer received START\n"); LARGE_INTEGER liDueTime; liDueTime.QuadPart = -10000 * payload->valueUnion.nt; success = SetWaitableTimer(timerContext->timer, &liDueTime, 0, Callback, context, FALSE); inStart = TRUE; PrtAssert(success, "SetWaitableTimer failed"); } else if (evnt->valueUnion.ev == P_EVENT_CANCEL) { printf("Timer received CANCEL\n"); inStart = FALSE; success = CancelWaitableTimer(timerContext->timer); if (success) { ev = PrtMkEventValue(P_EVENT_CANCEL_SUCCESS); PrtSend(context, PrtGetMachine(context->process, timerContext->client), ev, context->id, PRT_FALSE); } else { ev = PrtMkEventValue(P_EVENT_CANCEL_FAILURE); PrtSend(context, PrtGetMachine(context->process, timerContext->client), ev, context->id, PRT_FALSE); } PrtFreeValue(ev); } else { PrtAssert(FALSE, "Illegal event"); } }
/* Custom code called right before the plugin is unloaded */ void ts3plugin_shutdown() { // Stop the plugin threads pluginRunning = false; // Close settings database ts3Settings.CloseDatabase(); // Cancel PTT delay timer CancelWaitableTimer(hPttDelayTimer); // Wait for the thread to stop WaitForSingleObject(hMailslotThread, PLUGIN_THREAD_TIMEOUT); /* * Note: * If your plugin implements a settings dialog, it must be closed and deleted here, else the * TeamSpeak client will most likely crash (DLL removed but dialog from DLL code still open). */ /* Free pluginID if we registered it */ if(pluginID) { free(pluginID); pluginID = NULL; } }
static int start_file(char *name) { char buf[MAXFILENAME+20]; int fd; if (play_f!=-1) { replay_abort(); close(play_f); play_f=-1; CancelWaitableTimer(timer); replay_pause(); set_buttons(0); } fd=open_stream(-1, name, SM_READ, 0); if (fd==-1) return 0; play_f=fd; play_format=ttyrec_r_find_format(0, name, "baudrate"); play_filename=name; replay_start(); snprintf(buf, sizeof(buf), "Termplay: %s (%s)", filename, play_format); SetWindowText(wndMain, buf); set_toolbar_state(1); play_state=2; do_replay(); return 1; }
void newfunc_newhandler08_close(void) { funcbit_smp_disable(intsoundcontrol,INTSOUND_DECODER); if(int08_thread_handle){ newfunc_newhandler08_waitfor_threadend(); SuspendThread(int08_thread_handle); } if(handle_maincycle1) SuspendThread(handle_maincycle1); if(handle_maincycle2) SuspendThread(handle_maincycle2); mpxplay_timer_close(); if(int08_thread_handle) TerminateThread(int08_thread_handle,0); if(handle_maincycle1) TerminateThread(handle_maincycle1,0); if(handle_maincycle2) TerminateThread(handle_maincycle2,0); if(int08_timer_handle){ CancelWaitableTimer(int08_timer_handle); CloseHandle(int08_timer_handle); int08_timer_handle=NULL; } if(int08_timer_thread_handle) TerminateThread(int08_timer_thread_handle,0); if(int08_thread_handle) CloseHandle(int08_thread_handle); if(handle_maincycle1) CloseHandle(handle_maincycle1); if(handle_maincycle2) CloseHandle(handle_maincycle2); if(int08_timer_thread_handle) CloseHandle(int08_timer_thread_handle); timeEndPeriod(int08_timer_period); }
static void newhandler_08_timer_thread(void) { LARGE_INTEGER DueTime; //char sout[100]; if(!int08_timer_handle){ int08_timer_handle=CreateWaitableTimer(NULL,0,NULL); if(int08_timer_handle){ DueTime.QuadPart=-(int08_timer_period*10000); SetWaitableTimer(int08_timer_handle,&DueTime,(int08_timer_period+1)/2,NULL,NULL,0); }else{ } } do{ funcbit_smp_value_increment(int08counter); //sprintf(sout,"c:%5d tp:%d",int08counter,int08_timer_period); //display_message(1,0,sout); WaitForSingleObject(int08_timer_handle,int08_timer_period); }while(mpxplay_timed_functions); if(int08_timer_handle){ CancelWaitableTimer(int08_timer_handle); CloseHandle(int08_timer_handle); int08_timer_handle=NULL; } }
static int ktimer_delete(struct filter *filt, struct knote *kn) { if (kn->data.handle == NULL || kn->kn_event_whandle == NULL) return (0); if(!UnregisterWaitEx(kn->kn_event_whandle, INVALID_HANDLE_VALUE)) { dbg_lasterror("UnregisterWait()"); return (-1); } if (!CancelWaitableTimer(kn->data.handle)) { dbg_lasterror("CancelWaitableTimer()"); return (-1); } if (!CloseHandle(kn->data.handle)) { dbg_lasterror("CloseHandle()"); return (-1); } if( !(kn->kev.flags & EV_ONESHOT) ) knote_release(kn); kn->data.handle = NULL; return (0); }
void WTimer::Close() { if (m_Timer != NULL) { CancelWaitableTimer(m_Timer); CloseHandle(m_Timer); m_Timer = NULL; } }
HRESULT AgentConfigurationEx::CResetThread::Execute (DWORD_PTR dwParam, HANDLE hObject) { static char name[] = "CResetThread::Execute"; AgentConfigurationEx *agent = (AgentConfigurationEx *) dwParam; CancelWaitableTimer(hObject); // DebugBreak(); try { PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof( pi ) ); STARTUPINFO si; ZeroMemory(&si, sizeof( si ) ); si.cb = sizeof( si ); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // set the window display to HIDE // SCM reset command of this service #ifndef RESETTEST std::string cmd = StdStringFormat("cmd /c net stop \"%s\" & net start \"%s\"", Globals.ServerName.c_str( ), Globals.ServerName.c_str( ) ); // Command line #else // This works when you run in from a command console as NikonAgent.exe debug, it will restart in the current DOS console. TCHAR buf[1000]; GetModuleFileName(NULL, buf, 1000); std::string exepath = File.ExeDirectory(); std::string exe = ExtractFilename(std::string(buf)); //GLogger.Fatal(StdStringFormat("start Agent /d \"%s\" /b \"%s\" debug\n", exepath.c_str(), buf ) ); std::string cmd = StdStringFormat("cmd /c taskkill /IM \"%s\" & \"%s\" debug", exe.c_str(), buf ); // Command line #endif if ( !::CreateProcess(NULL, // No module name (use command line) const_cast<char *>( cmd.c_str( ) ), NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi) ) // Pointer to PROCESS_INFORMATION structure { AtlTrace("CreateProcess FAIL "); } ::Sleep(5000); // make sure process has spawned before killing thread } catch ( ... ) { agent->AbortMsg("Exception - ResetAtMidnightThread(void *oObject"); } return S_OK; }
FtpConnecter::~FtpConnecter(void) { if (m_FtpInfo._hWaitableTimer != NULL) { CancelWaitableTimer(m_FtpInfo._hWaitableTimer); CloseHandle(m_FtpInfo._hWaitableTimer); } if (m_hWorkThread) CloseHandle(m_hWorkThread); }
/** winTimer() * * The classic Rexx external function, WinTimer() was documented prior to 4.0.0 * and therefore needs to be retained for backward compatibility. * * The original implementation was poor, using SetTimer() / KillTimer(). For * the wait mode, it used this loop: * * else if ( stricmp("WAIT", mode) == 0 ) * { * while ( !PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE) * { * ; // do nothing * } * return 0; * } * * PeekMessage() returns immediately if there are no messages. Since there * were probably no windows on the thread, the WAIT function spun in a busy * loop consuming 100% of the CPU. * * svn revision 8968 and previous contains the original implementation if there * is a need to review that code. * * The original implmentation was replaced in ooDialog 4.2.2 with this * implementation using waitable timers instead. It is backwards compatible * with the original implementation, and needs to remain that way. * * For very small periods, SetTimer replaces the specified time with * USER_TIMER_MINIMUM. So when Rexx programmers specified 1 or 2 or 6 * milliseconds, the got USER_TIMER_MINIMUM instead. We mimic that behaviour * here, otherwise programs using a delay of 1 millisecond do not work the * same. We actually use 1.5 times USER_TIMER_MINIMUM because it seems to work * the best. * * @param mode Keyword for what is to be done. START creates the timer and * starts it. WAIT waits on the timer. STOP destroys the * timer. * * @param msOrId Either the period of the timer, in miliseconds, if mode is * START, or the timer ID for the other modes. * * @return The timer ID for the START mode, or success / error return code for * the other modes. * * @notes Sets the .SystemErrorCode. For the STOP and WAIT modes the system * error code value is returned in addition to setting the * .SystemErrorCode. * * @remarks If this routine was being implemented from scratch, it would be * done differently. However since it is being used to preserve * backwards compatibility, this implementation serves best. An * enhancement creating a new Waitable object class would be nice. */ RexxRoutine2(uintptr_t, winTimer_rtn, CSTRING, mode, uintptr_t, msOrId) { oodResetSysErrCode(context->threadContext); if ( stricmp("START", mode) == 0 ) { HANDLE hTimer = NULL; LARGE_INTEGER liDueTime; if ( msOrId < USER_TIMER_MINIMUM + 5 ) { msOrId = USER_TIMER_MINIMUM + 5; } liDueTime.QuadPart = msOrId * -10000; hTimer = CreateWaitableTimer(NULL, FALSE, NULL); if ( hTimer == NULL ) { oodSetSysErrCode(context->threadContext); return 0; } if ( ! SetWaitableTimer(hTimer, &liDueTime, (int32_t)msOrId, NULL, NULL, FALSE) ) { oodSetSysErrCode(context->threadContext); return 0; } return (uintptr_t)hTimer; } else if ( stricmp("STOP", mode) == 0 ) { if ( CancelWaitableTimer((HANDLE)msOrId) == 0 ) { uint32_t rc = GetLastError(); oodSetSysErrCode(context->threadContext, rc); return rc; } return 0; } else if ( stricmp("WAIT", mode) == 0 ) { if ( WaitForSingleObject((HANDLE)msOrId, INFINITE) != WAIT_OBJECT_0 ) { uint32_t rc = GetLastError(); oodSetSysErrCode(context->threadContext, rc); return rc; } return 0; } wrongArgValueException(context->threadContext, 1, "START, STOP, WAIT", mode); return 0; }
VOID InitTimer() { CancelWaitableTimer(Timer); if (UpdateOnPeriod) { LONG interval = PeriodToMilliseconds(Period, PeriodMeasure); _int64 qwDueTime = -10000i64 * interval; LARGE_INTEGER li = { 0 }; li.LowPart = (DWORD)(qwDueTime & 0xFFFFFFFF); li.HighPart = (LONG)(qwDueTime >> 32); SetWaitableTimer(Timer, &li, interval, TimerAPCProc, NULL, 0); } }
bool ChighPerformanceTimer::Stop() { g_Error=0; if (g_TimerHandle==NULL) { g_Result=g_WaitableTimer_NotValid; return false; } g_Set=false; if (! CancelWaitableTimer(g_TimerHandle)) { g_Error=GetLastError(); g_Result=g_WaitableTimer_TickError; return false; } return true; }
HRESULT AgentConfigurationEx::CResetThread::Execute (DWORD_PTR dwParam, HANDLE hObject) { static char name[] = "CResetThread::Execute"; AgentConfigurationEx *agent = (AgentConfigurationEx *) dwParam; CancelWaitableTimer(hObject); // DebugBreak(); try { PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof( pi ) ); STARTUPINFO si; ZeroMemory(&si, sizeof( si ) ); si.cb = sizeof( si ); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // set the window display to HIDE // SCM reset command of this service std::string cmd = StdStringFormat("cmd /c net stop \"%s\" & net start \"%s\"", Globals.ServerName.c_str( ), Globals.ServerName.c_str( ) ); // Command line if ( !::CreateProcess(NULL, // No module name (use command line) const_cast<char *>( cmd.c_str( ) ), NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi) ) // Pointer to PROCESS_INFORMATION structure { AtlTrace("CreateProcess FAIL "); } ::Sleep(5000); // make sure process has spawned before killing thread } catch ( ... ) { agent->AbortMsg("Exception - ResetAtMidnightThread(void *oObject"); } return S_OK; }
VOID CALLBACK TimeoutTimerProc(void * arg,DWORD dwTimerLowValue,DWORD dwTimerHighValue) { sDIALOG_long * sd = (sDIALOG_long *)arg; if (!K_CHECK_PTR(sd) || !K_CHECK_PTR(sd->timeoutProc)) { IMDEBUG(DBG_ERROR, "Bad dLong timer pointer %x", sd); return; } if (sd->timeoutProc(TIMEOUTT_CHECK , sd)) { sd->timeoutPassed+=TIMEOUT_INTERVAL; // IMLOG("TIMEOUT Passed %d / %d" , sd->timeoutPassed , sd->timeout); if (sd->timeout && sd->timeoutPassed>=sd->timeout) { CancelWaitableTimer(sd->timeoutHandle); sd->timeoutProc(TIMEOUTT_TIMEOUT , sd); return; } } else { sd->timeoutPassed=0; /*IMLOG("TIMEOUT Cancel");*/ } }
BOOL freespace_private_discoveryStatusChanged() { if ( freespace_instance_->needToRescanDevicesFlag_ || WaitForSingleObject(freespace_instance_->discoveryEvent_, 0) == WAIT_OBJECT_0) { // Race condition note: the flags need to be reset before the scan takes // place. If device status changes again between when this thread is notified // and the flags get reset, we're ok, since the scan happens afterwards. If the // change occurs after the reset of the flags, the flags will be set again, and // we'll scan next trip around the event loop. freespace_instance_->needToRescanDevicesFlag_ = FALSE; // Force the timer to unsignaled by restarting and then cancelling. freespace_private_requestDeviceRescan(); CancelWaitableTimer(freespace_instance_->discoveryEvent_); return TRUE; } else { return FALSE; } }
HRESULT MtcOpcAdapter::CResetThread::Execute(DWORD_PTR dwParam, HANDLE hObject) { static char name[] = "CResetThread::Execute"; MtcOpcAdapter * adapter = (MtcOpcAdapter*) dwParam; CancelWaitableTimer(hObject); try { GLogger << ENTRY << "MTConnect adapter Service Start Resetting " << std::endl; PROCESS_INFORMATION pi; ZeroMemory( &pi, sizeof(pi) ); STARTUPINFO si; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; // set the window display to HIDE // SCM reset command of this service std::string cmd = StdStringFormat("cmd /c net stop \"%s\" & net start \"%s\"", adapter->name(), adapter->name()); // Command line ::CreateProcess( NULL, // No module name (use command line) const_cast<char *>(cmd.c_str()), NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ); // Pointer to PROCESS_INFORMATION structure ::Sleep(5000); // make sure process has spawned before killing thread } catch(...) { GLogger << FATAL << "Exception - ResetAtMidnightThread(void *oObject)" << std::endl; } return S_OK; }
//------------------------------------------------------------------------------ tOplkError hrestimer_deleteTimer(tTimerHdl* pTimerHdl_p) { tOplkError ret = kErrorOk; UINT index; tHresTimerInfo* pTimerInfo; HANDLE hTimer; DEBUG_LVL_TIMERH_TRACE("%s() Deleting timer: %lx\n", __func__, *pTimerHdl_p); if (pTimerHdl_p == NULL) return kErrorTimerInvalidHandle; if (*pTimerHdl_p == 0) { // no timer created yet return ret; } else { index = (UINT)HDL_TO_IDX(*pTimerHdl_p); if (index >= TIMER_COUNT) { // invalid handle return kErrorTimerInvalidHandle; } pTimerInfo = &hresTimerInstance_l.aTimerInfo[index]; if (pTimerInfo->eventArg.timerHdl.handle != *pTimerHdl_p) { // invalid handle return ret; } } pTimerInfo->pfnCallback = NULL; *pTimerHdl_p = 0; // Cancel timer hTimer = hresTimerInstance_l.aHandle[index + HRTIMER_HDL_TIMER0]; CancelWaitableTimer(hTimer); return ret; }
HOOKFUNC BOOL WINAPI MyCancelWaitableTimer(HANDLE hTimer) { BOOL rv = CancelWaitableTimer(hTimer); debuglog(LCF_SYNCOBJ|LCF_DESYNC|LCF_UNTESTED|LCF_TODO, __FUNCTION__ " returned %d.\n", rv); return rv; }
INT OnPreShutdown(WPARAM, LPARAM) { CancelWaitableTimer(Timer); CloseHandle(Timer); return 0; }
RTR3DECL(int) RTTimerDestroy(PRTTIMER pTimer) { /* NULL is ok. */ if (!pTimer) return VINF_SUCCESS; /* * Validate handle first. */ int rc; if ( VALID_PTR(pTimer) && pTimer->u32Magic == RTTIMER_MAGIC) { #ifdef USE_WINMM /* * Kill the timer and exit. */ rc = timeKillEvent(pTimer->TimerId); AssertMsg(rc == TIMERR_NOERROR, ("timeKillEvent -> %d\n", rc)); ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); RTThreadSleep(1); #else /* !USE_WINMM */ /* * Signal that we want the thread to exit. */ ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); #ifdef USE_APC SetEvent(pTimer->hevWait); CloseHandle(pTimer->hevWait); rc = CancelWaitableTimer(pTimer->hTimer); AssertMsg(rc, ("CancelWaitableTimer lasterr=%d\n", GetLastError())); #else LARGE_INTEGER ll = {0}; ll.LowPart = 100; rc = SetWaitableTimer(pTimer->hTimer, &ll, 0, NULL, NULL, FALSE); AssertMsg(rc, ("CancelWaitableTimer lasterr=%d\n", GetLastError())); #endif /* * Wait for the thread to exit. * And if it don't wanna exit, we'll get kill it. */ rc = RTThreadWait(pTimer->Thread, 1000, NULL); if (RT_FAILURE(rc)) TerminateThread((HANDLE)RTThreadGetNative(pTimer->Thread), UINT32_MAX); /* * Free resource. */ rc = CloseHandle(pTimer->hTimer); AssertMsg(rc, ("CloseHandle lasterr=%d\n", GetLastError())); #endif /* !USE_WINMM */ RTMemFree(pTimer); return rc; } rc = VERR_INVALID_HANDLE; AssertMsgFailed(("Failed to destroy timer %p. rc=%d\n", pTimer, rc)); return rc; }
RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser) { #ifndef USE_WINMM /* * On windows we'll have to set the timer resolution before * we start the timer. */ ULONG ulMax = UINT32_MAX; ULONG ulMin = UINT32_MAX; ULONG ulCur = UINT32_MAX; NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); if (ulCur > ulMin && ulCur > 10000 /* = 1ms */) { if (NtSetTimerResolution(10000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 1ms.\n")); else if (NtSetTimerResolution(20000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 2ms.\n")); else if (NtSetTimerResolution(40000, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to 4ms.\n")); else if (ulMin <= 50000 && NtSetTimerResolution(ulMin, TRUE, &ulCur) >= 0) Log(("Changed timer resolution to %lu *100ns.\n", ulMin)); else { AssertMsgFailed(("Failed to configure timer resolution!\n")); return VERR_INTERNAL_ERROR; } } #endif /* !USE_WINN */ /* * Create new timer. */ int rc = VERR_IPE_UNINITIALIZED_STATUS; PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); if (pTimer) { pTimer->u32Magic = RTTIMER_MAGIC; pTimer->pvUser = pvUser; pTimer->pfnTimer = pfnTimer; pTimer->iTick = 0; pTimer->uMilliesInterval = uMilliesInterval; #ifdef USE_WINMM /* sync kill doesn't work. */ pTimer->TimerId = timeSetEvent(uMilliesInterval, 0, rttimerCallback, (DWORD_PTR)pTimer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); if (pTimer->TimerId) { ULONG ulMax = UINT32_MAX; ULONG ulMin = UINT32_MAX; ULONG ulCur = UINT32_MAX; NtQueryTimerResolution(&ulMax, &ulMin, &ulCur); Log(("NtQueryTimerResolution -> ulMax=%lu00ns ulMin=%lu00ns ulCur=%lu00ns\n", ulMax, ulMin, ulCur)); *ppTimer = pTimer; return VINF_SUCCESS; } rc = VERR_INVALID_PARAMETER; #else /* !USE_WINMM */ /* * Create Win32 event semaphore. */ pTimer->iError = 0; pTimer->hTimer = CreateWaitableTimer(NULL, TRUE, NULL); if (pTimer->hTimer) { #ifdef USE_APC /* * Create wait semaphore. */ pTimer->hevWait = CreateEvent(NULL, FALSE, FALSE, NULL); if (pTimer->hevWait) #endif { /* * Kick off the timer thread. */ rc = RTThreadCreate(&pTimer->Thread, rttimerCallback, pTimer, 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "Timer"); if (RT_SUCCESS(rc)) { /* * Wait for the timer to successfully create the timer * If we don't get a response in 10 secs, then we assume we're screwed. */ rc = RTThreadUserWait(pTimer->Thread, 10000); if (RT_SUCCESS(rc)) { rc = pTimer->iError; if (RT_SUCCESS(rc)) { *ppTimer = pTimer; return VINF_SUCCESS; } } ASMAtomicXchgU32(&pTimer->u32Magic, RTTIMER_MAGIC + 1); RTThreadWait(pTimer->Thread, 250, NULL); CancelWaitableTimer(pTimer->hTimer); } #ifdef USE_APC CloseHandle(pTimer->hevWait); #endif } CloseHandle(pTimer->hTimer); } #endif /* !USE_WINMM */ AssertMsgFailed(("Failed to create timer uMilliesInterval=%d. rc=%d\n", uMilliesInterval, rc)); RTMemFree(pTimer); } else rc = VERR_NO_MEMORY; return rc; }