1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Timer test
5  * PROGRAMMER:      Rafal Harabien <rafalh@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 
10 #define CheckTimer(Timer, ExpectedType, State, ExpectedWaitNext,                \
11                             Irql, ThreadList, ThreadCount) do                   \
12 {                                                                               \
13     INT TheIndex;                                                               \
14     PLIST_ENTRY TheEntry;                                                       \
15     PKTHREAD TheThread;                                                         \
16     ok_eq_uint((Timer)->Header.Type, ExpectedType);                             \
17     ok_eq_uint((Timer)->Header.Hand, sizeof *(Timer) / sizeof(ULONG));          \
18     ok_eq_hex((Timer)->Header.Lock & 0xFF00FF00L, 0x00005500L);                 \
19     ok_eq_long((Timer)->Header.SignalState, State);                             \
20     TheEntry = (Timer)->Header.WaitListHead.Flink;                              \
21     for (TheIndex = 0; TheIndex < (ThreadCount); ++TheIndex)                    \
22     {                                                                           \
23         TheThread = CONTAINING_RECORD(TheEntry, KTHREAD,                        \
24                                         WaitBlock[0].WaitListEntry);            \
25         ok_eq_pointer(TheThread, (ThreadList)[TheIndex]);                       \
26         ok_eq_pointer(TheEntry->Flink->Blink, TheEntry);                        \
27         TheEntry = TheEntry->Flink;                                             \
28     }                                                                           \
29     ok_eq_pointer(TheEntry, &(Timer)->Header.WaitListHead);                     \
30     ok_eq_pointer(TheEntry->Flink->Blink, TheEntry);                            \
31     ok_eq_long(KeReadStateTimer(Timer), State);                                 \
32     ok_eq_bool(Thread->WaitNext, ExpectedWaitNext);                             \
33     ok_irql(Irql);                                                              \
34 } while (0)
35 
36 static
37 VOID
38 TestTimerFunctional(
39     IN PKTIMER Timer,
40     IN TIMER_TYPE Type,
41     IN KIRQL OriginalIrql)
42 {
43     PKTHREAD Thread = KeGetCurrentThread();
44 
45     memset(Timer, 0x55, sizeof *Timer);
46     KeInitializeTimerEx(Timer, Type);
47     CheckTimer(Timer, TimerNotificationObject + Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
48 }
49 
50 START_TEST(KeTimer)
51 {
52     KTIMER Timer;
53     KIRQL Irql;
54     KIRQL Irqls[] = { PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL, HIGH_LEVEL };
55     INT i;
56 
57     for (i = 0; i < sizeof Irqls / sizeof Irqls[0]; ++i)
58     {
59         /* DRIVER_IRQL_NOT_LESS_OR_EQUAL (TODO: on MP only?) */
60         if (Irqls[i] > DISPATCH_LEVEL && KmtIsCheckedBuild)
61             return;
62         KeRaiseIrql(Irqls[i], &Irql);
63         TestTimerFunctional(&Timer, NotificationTimer, Irqls[i]);
64         TestTimerFunctional(&Timer, SynchronizationTimer, Irqls[i]);
65         KeLowerIrql(Irql);
66     }
67 
68     ok_irql(PASSIVE_LEVEL);
69     KmtSetIrql(PASSIVE_LEVEL);
70 }
71