From bbe7ec53c56604c66a179bde98be05743a35edb4 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Wed, 26 May 2010 02:04:09 +0000 Subject: [PATCH] [win32k] - Implement DestroyTimersForWindow and call it instead of MsqRemoveTimersWindow when destroying a window. - Fire NewMessages event when cleaning up thread so that threads dont wait for new messages that will never be received. Fixes a problem where some application that use timers dont completly exit. - IntSetTimer: Dont try to raise a timer from the dead. Once the TMRF_DELETEPENDING flag is set, let it be destroyed. - co_MsqWaitForNewMessages: Call the wait without a timeout value as now when the timer expires the NewMessages event will be set to exit the wait. - Message Queue specific timer code and old time queuing code is now dead. It will be removed later when we are happy with new timer implementation. svn path=/trunk/; revision=47358 --- .../subsystems/win32/win32k/include/timer.h | 1 + .../subsystems/win32/win32k/main/dllmain.c | 1 + .../subsystems/win32/win32k/ntuser/defwnd.c | 4 +- .../subsystems/win32/win32k/ntuser/msgqueue.c | 15 +------ .../subsystems/win32/win32k/ntuser/timer.c | 40 +++++++++++++++---- .../subsystems/win32/win32k/ntuser/window.c | 2 +- 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/reactos/subsystems/win32/win32k/include/timer.h b/reactos/subsystems/win32/win32k/include/timer.h index a41b8c30dbe..8e5bce67c15 100644 --- a/reactos/subsystems/win32/win32k/include/timer.h +++ b/reactos/subsystems/win32/win32k/include/timer.h @@ -29,6 +29,7 @@ extern PKTIMER MasterTimer; NTSTATUS FASTCALL InitTimerImpl(VOID); BOOL FASTCALL DestroyTimersForThread(PTHREADINFO pti); +BOOL FASTCALL DestroyTimersForWindow(PTHREADINFO pti, PWINDOW_OBJECT Window); BOOL FASTCALL IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer); UINT_PTR FASTCALL IntSetTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, INT Type); PTIMER FASTCALL FindSystemTimer(PMSG); diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index 3eb5753d231..88684b6cf80 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -292,6 +292,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread, HOOK_DestroyThreadHooks(Thread); /* Cleanup timers */ DestroyTimersForThread(Win32Thread); + KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); UnregisterThreadHotKeys(Thread); /* what if this co_ func crash in umode? what will clean us up then? */ co_DestroyThreadWindows(Thread); diff --git a/reactos/subsystems/win32/win32k/ntuser/defwnd.c b/reactos/subsystems/win32/win32k/ntuser/defwnd.c index f5e2bd1fc1d..6cf4fd010c6 100644 --- a/reactos/subsystems/win32/win32k/ntuser/defwnd.c +++ b/reactos/subsystems/win32/win32k/ntuser/defwnd.c @@ -67,7 +67,7 @@ IntClientShutdown( co_IntSendMessage(WndChild->hSelf, WM_ENDSESSION, KillTimers, lParams); if (KillTimers) { - MsqRemoveTimersWindow(WndChild->pti->MessageQueue, WndChild->hSelf); + DestroyTimersForWindow(WndChild->pti, WndChild); } lResult = MCSR_SHUTDOWNFINISHED; } @@ -90,7 +90,7 @@ IntClientShutdown( co_IntSendMessage(pWindow->hSelf, WM_ENDSESSION, KillTimers, lParams); if (KillTimers) { - MsqRemoveTimersWindow(pWindow->pti->MessageQueue, pWindow->hSelf); + DestroyTimersForWindow(pWindow->pti, pWindow); } lResult = MCSR_SHUTDOWNFINISHED; } diff --git a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c index e71de5475d7..fe1d9a80af7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c @@ -1366,19 +1366,8 @@ co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWINDOW_OBJECT WndFil UINT MsgFilterMin, UINT MsgFilterMax) { PVOID WaitObjects[2] = {MessageQueue->NewMessages, &HardwareMessageEvent}; - LARGE_INTEGER TimerExpiry; - PLARGE_INTEGER Timeout; NTSTATUS ret; - if (MsqGetFirstTimerExpiry(MessageQueue, WndFilter, MsgFilterMin, MsgFilterMax, &TimerExpiry)) - { - Timeout = &TimerExpiry; - } - else - { - Timeout = NULL; - } - IdlePing(); // Going to wait so send Idle ping. UserLeaveCo(); @@ -1389,11 +1378,9 @@ co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWINDOW_OBJECT WndFil Executive, UserMode, FALSE, - Timeout, + NULL, NULL); - UserEnterCo(); - return ret; } diff --git a/reactos/subsystems/win32/win32k/ntuser/timer.c b/reactos/subsystems/win32/win32k/ntuser/timer.c index 2d7b8d003d7..e178241f1ea 100644 --- a/reactos/subsystems/win32/win32k/ntuser/timer.c +++ b/reactos/subsystems/win32/win32k/ntuser/timer.c @@ -216,7 +216,7 @@ IntSetTimer( PWINDOW_OBJECT Window, } pTmr = FindTimer(Window, IDEvent, Type, FALSE); - if (!pTmr) + if ((!pTmr) || (pTmr->flags & TMRF_DELETEPENDING)) { pTmr = CreateTimer(); if (!pTmr) return 0; @@ -240,10 +240,6 @@ IntSetTimer( PWINDOW_OBJECT Window, pTmr->cmsCountdown = Elapse; pTmr->cmsRate = Elapse; - if (pTmr->flags & TMRF_DELETEPENDING) - { - pTmr->flags &= ~TMRF_DELETEPENDING; - } ASSERT(MasterTimer != NULL); // Start the timer thread! @@ -342,6 +338,7 @@ ProcessTimers(VOID) LONG Time; PLIST_ENTRY pLE; PTIMER pTmr = FirstpTmr; + LONG TimerCount = 0; if (!pTmr) return; @@ -354,6 +351,7 @@ ProcessTimers(VOID) do { + TimerCount++; if (pTmr->flags & TMRF_WAITING) { pLE = pTmr->ptmrList.Flink; @@ -426,6 +424,7 @@ ProcessTimers(VOID) TimeLast = Time; UserLeave(); + DPRINT("TimerCount = %d\n", TimerCount); } // @@ -524,6 +523,35 @@ if (Ret == 0) ASSERT(FALSE); return Ret; } +BOOL FASTCALL +DestroyTimersForWindow(PTHREADINFO pti, PWINDOW_OBJECT Window) +{ + PLIST_ENTRY pLE; + PTIMER pTmr = FirstpTmr; + BOOL TimersRemoved = FALSE; + + if ((FirstpTmr == NULL) || (Window == NULL)) + return FALSE; + + KeEnterCriticalRegion(); + + do + { + if ((pTmr) && (pTmr->pti == pti) && (pTmr->pWnd == Window)) + { + pTmr->flags &= ~TMRF_READY; + pTmr->flags |= TMRF_DELETEPENDING; + TimersRemoved = TRUE; + } + pLE = pTmr->ptmrList.Flink; + pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); + } while (pTmr != FirstpTmr); + + KeLeaveCriticalRegion(); + + return TimersRemoved; +} + BOOL FASTCALL DestroyTimersForThread(PTHREADINFO pti) { @@ -553,7 +581,6 @@ DestroyTimersForThread(PTHREADINFO pti) return TimersRemoved; } - BOOL FASTCALL IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer) { @@ -568,7 +595,6 @@ IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer) return pTmr ? TRUE : FALSE; } - // // // Old Kill Timer diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index 409770d891a..6c17e8cb931 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -424,7 +424,7 @@ static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window, if(BelongsToThreadData) co_IntSendMessage(Window->hSelf, WM_NCDESTROY, 0, 0); } - MsqRemoveTimersWindow(ThreadData->MessageQueue, Window->hSelf); + DestroyTimersForWindow(ThreadData, Window); HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too! /* flush the message queue */