Author: akhaldi Date: Tue Nov 24 20:35:58 2015 New Revision: 70100
URL: http://svn.reactos.org/svn/reactos?rev=70100&view=rev Log: [RTL] Partially sync some timer queue related functions with Wine Staging 1.7.55. Brought to you by Samuel Serapión and Thomas Faber. CORE-10574 CORE-10536
Modified: trunk/reactos/lib/rtl/timerqueue.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/lib/rtl/timerqueue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/timerqueue.c?rev=70... ============================================================================== --- trunk/reactos/lib/rtl/timerqueue.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/timerqueue.c [iso-8859-1] Tue Nov 24 20:35:58 2015 @@ -47,20 +47,22 @@ DWORD period; ULONG flags; ULONGLONG expire; - BOOL destroy; /* timer should be deleted; once set, never unset */ - HANDLE event; /* removal event */ + BOOL destroy; /* timer should be deleted; once set, never unset */ + HANDLE event; /* removal event */ };
struct timer_queue { + DWORD magic; RTL_CRITICAL_SECTION cs; - struct list timers; /* sorted by expiration time */ - BOOL quit; /* queue should be deleted; once set, never unset */ + struct list timers; /* sorted by expiration time */ + BOOL quit; /* queue should be deleted; once set, never unset */ HANDLE event; HANDLE thread; };
#define EXPIRE_NEVER (~(ULONGLONG) 0) +#define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */
static void queue_remove_timer(struct queue_timer *t) { @@ -77,7 +79,7 @@ NtSetEvent(t->event, NULL); RtlFreeHeap(RtlGetProcessHeap(), 0, t);
- if (q->quit && list_count(&q->timers) == 0) + if (q->quit && list_empty(&q->timers)) NtSetEvent(q->event, NULL); }
@@ -95,19 +97,18 @@ RtlLeaveCriticalSection(&q->cs); }
-static DWORD WINAPI timer_callback_wrapper(LPVOID p) +static VOID WINAPI timer_callback_wrapper(LPVOID p) { struct queue_timer *t = p; t->callback(t->param, TRUE); timer_cleanup_callback(t); - return 0; }
static inline ULONGLONG queue_current_time(void) { - LARGE_INTEGER now; - NtQuerySystemTime(&now); - return now.QuadPart / 10000; + LARGE_INTEGER now, freq; + NtQueryPerformanceCounter(&now, &freq); + return now.QuadPart * 1000 / freq.QuadPart; }
static void queue_add_timer(struct queue_timer *t, ULONGLONG time, @@ -151,13 +152,21 @@ RtlEnterCriticalSection(&q->cs); if (list_head(&q->timers)) { + ULONGLONG now, next; t = LIST_ENTRY(list_head(&q->timers), struct queue_timer, entry); - if (!t->destroy && t->expire <= queue_current_time()) + if (!t->destroy && t->expire <= ((now = queue_current_time()))) { ++t->runcount; - queue_move_timer( - t, t->period ? queue_current_time() + t->period : EXPIRE_NEVER, - FALSE); + if (t->period) + { + next = t->expire + t->period; + /* avoid trigger cascade if overloaded / hibernated */ + if (next < now) + next = now + t->period; + } + else + next = EXPIRE_NEVER; + queue_move_timer(t, next, FALSE); } else t = NULL; @@ -174,7 +183,7 @@ = (t->flags & (WT_EXECUTEINIOTHREAD | WT_EXECUTEINPERSISTENTTHREAD | WT_EXECUTELONGFUNCTION | WT_TRANSFER_IMPERSONATION)); - NTSTATUS status = RtlQueueWorkItem((WORKERCALLBACKFUNC)timer_callback_wrapper, t, flags); + NTSTATUS status = RtlQueueWorkItem(timer_callback_wrapper, t, flags); if (status != STATUS_SUCCESS) timer_cleanup_callback(t); } @@ -203,7 +212,7 @@ return timeout; }
-static void WINAPI timer_queue_thread_proc(LPVOID p) +static DWORD WINAPI timer_queue_thread_proc(LPVOID p) { struct timer_queue *q = p; ULONG timeout_ms; @@ -225,7 +234,7 @@ timer got put at the head of the list so we need to adjust our timeout. */ RtlEnterCriticalSection(&q->cs); - if (q->quit && list_count(&q->timers) == 0) + if (q->quit && list_empty(&q->timers)) done = TRUE; RtlLeaveCriticalSection(&q->cs); } @@ -240,8 +249,10 @@
NtClose(q->event); RtlDeleteCriticalSection(&q->cs); + q->magic = 0; RtlFreeHeap(RtlGetProcessHeap(), 0, q); RtlpExitThreadFunc(STATUS_SUCCESS); + return 0; }
static void queue_destroy_timer(struct queue_timer *t) @@ -281,13 +292,14 @@ RtlInitializeCriticalSection(&q->cs); list_init(&q->timers); q->quit = FALSE; - status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); + q->magic = TIMER_QUEUE_MAGIC; + status = NtCreateEvent(&q->event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (status != STATUS_SUCCESS) { RtlFreeHeap(RtlGetProcessHeap(), 0, q); return status; } - status = RtlpStartThreadFunc((PVOID)timer_queue_thread_proc, q, &q->thread); + status = RtlpStartThreadFunc(timer_queue_thread_proc, q, &q->thread); if (status != STATUS_SUCCESS) { NtClose(q->event); @@ -323,7 +335,7 @@ HANDLE thread; NTSTATUS status;
- if (!q) + if (!q || q->magic != TIMER_QUEUE_MAGIC) return STATUS_INVALID_HANDLE;
thread = q->thread; @@ -360,10 +372,10 @@ return status; }
-static struct timer_queue *default_timer_queue; - static struct timer_queue *get_timer_queue(HANDLE TimerQueue) { + static struct timer_queue *default_timer_queue; + if (TimerQueue) return TimerQueue; else @@ -378,7 +390,7 @@ (void **) &default_timer_queue, q, NULL); if (p) /* Got beat to the punch. */ - RtlDeleteTimerQueueEx(p, NULL); + RtlDeleteTimerQueueEx(q, NULL); } } return default_timer_queue; @@ -401,7 +413,7 @@ * after the first callback. If zero, the timer will only * fire once. It still needs to be deleted with * RtlDeleteTimer. - * Flags [I] Flags controling the execution of the callback. In + * Flags [I] Flags controlling the execution of the callback. In * addition to the WT_* thread pool flags (see * RtlQueueWorkItem), WT_EXECUTEINTIMERTHREAD and * WT_EXECUTEONLYONCE are supported. @@ -418,8 +430,9 @@ NTSTATUS status; struct queue_timer *t; struct timer_queue *q = get_timer_queue(TimerQueue); - if (!q) - return STATUS_NO_MEMORY; + + if (!q) return STATUS_NO_MEMORY; + if (q->magic != TIMER_QUEUE_MAGIC) return STATUS_INVALID_HANDLE;
t = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof *t); if (!t) @@ -516,7 +529,11 @@ return STATUS_INVALID_PARAMETER_1; q = t->q; if (CompletionEvent == INVALID_HANDLE_VALUE) - status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); + { + status = NtCreateEvent(&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); + if (status == STATUS_SUCCESS) + status = STATUS_PENDING; + } else if (CompletionEvent) event = CompletionEvent;
@@ -530,7 +547,10 @@ if (CompletionEvent == INVALID_HANDLE_VALUE && event) { if (status == STATUS_PENDING) + { NtWaitForSingleObject(event, FALSE, NULL); + status = STATUS_SUCCESS; + } NtClose(event); }
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=7... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Tue Nov 24 20:35:58 2015 @@ -253,6 +253,7 @@ reactos/lib/3rdparty/strmbase # Synced to WineStaging-1.7.47
reactos/lib/rtl/actctx.c # Partly synced with WineStaging-1.7.37 +reactos/lib/rtl/timerqueue.c # Partly synced with WineStaging-1.7.55
advapi32 - reactos/dll/win32/advapi32/wine/cred.c # Synced to WineStaging-1.7.37