1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Doubly-linked list test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 struct _LIST_ENTRY;
9 #ifdef _X86_
10 struct _LIST_ENTRY *__stdcall ExInterlockedInsertHeadList(struct _LIST_ENTRY *, struct _LIST_ENTRY *, unsigned long *);
11 struct _LIST_ENTRY *__stdcall ExInterlockedInsertTailList(struct _LIST_ENTRY *, struct _LIST_ENTRY *, unsigned long *);
12 struct _LIST_ENTRY *__stdcall ExInterlockedRemoveHeadList(struct _LIST_ENTRY *, unsigned long *);
13 #endif
14 
15 #include <kmt_test.h>
16 
17 LIST_ENTRY Entries[5];
18 
19 #define ok_eq_free(Value, Expected) do              \
20 {                                                   \
21     if (KmtIsCheckedBuild)                          \
22         ok_eq_pointer(Value, (PVOID)0x0BADD0FF);    \
23     else                                            \
24         ok_eq_pointer(Value, Expected);             \
25 } while (0)
26 
27 #define ok_eq_free2(Value, Expected) do              \
28 {                                                   \
29     if (KmtIsCheckedBuild)                          \
30         ok_eq_pointer(Value, (PVOID)(ULONG_PTR)0xBADDD0FFBADDD0FFULL);    \
31     else                                            \
32         ok_eq_pointer(Value, Expected);             \
33 } while (0)
34 
35 START_TEST(ExDoubleList)
36 {
37     KSPIN_LOCK SpinLock;
38     LIST_ENTRY ListHead;
39     PLIST_ENTRY Ret;
40 
41     KeInitializeSpinLock(&SpinLock);
42 
43     memset(&ListHead, 0x55, sizeof ListHead);
44     InitializeListHead(&ListHead);
45     ok_eq_pointer(ListHead.Flink, &ListHead);
46     ok_eq_pointer(ListHead.Blink, &ListHead);
47     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
48     ok_irql(PASSIVE_LEVEL);
49 
50     Ret = ExInterlockedInsertHeadList(&ListHead, &Entries[0], &SpinLock);
51     ok_eq_pointer(Ret, NULL);
52     ok_eq_pointer(ListHead.Flink, &Entries[0]);
53     ok_eq_pointer(ListHead.Blink, &Entries[0]);
54     ok_eq_pointer(Entries[0].Flink, &ListHead);
55     ok_eq_pointer(Entries[0].Blink, &ListHead);
56     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
57     ok_irql(PASSIVE_LEVEL);
58 
59     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
60     ok_eq_pointer(Ret, &Entries[0]);
61     ok_eq_pointer(ListHead.Flink, &ListHead);
62     ok_eq_pointer(ListHead.Blink, &ListHead);
63     ok_eq_free(Entries[0].Flink, &ListHead);
64     ok_eq_free(Entries[0].Blink, &ListHead);
65     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
66     ok_irql(PASSIVE_LEVEL);
67 
68     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
69     ok_eq_pointer(Ret, NULL);
70     ok_eq_pointer(ListHead.Flink, &ListHead);
71     ok_eq_pointer(ListHead.Blink, &ListHead);
72     ok_eq_free(Entries[0].Flink, &ListHead);
73     ok_eq_free(Entries[0].Blink, &ListHead);
74     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
75     ok_irql(PASSIVE_LEVEL);
76 
77     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[0], &SpinLock);
78     ok_eq_pointer(Ret, NULL);
79     ok_eq_pointer(ListHead.Flink, &Entries[0]);
80     ok_eq_pointer(ListHead.Blink, &Entries[0]);
81     ok_eq_pointer(Entries[0].Flink, &ListHead);
82     ok_eq_pointer(Entries[0].Blink, &ListHead);
83     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
84     ok_irql(PASSIVE_LEVEL);
85 
86     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
87     ok_eq_pointer(Ret, &Entries[0]);
88     ok_eq_pointer(ListHead.Flink, &ListHead);
89     ok_eq_pointer(ListHead.Blink, &ListHead);
90     ok_eq_free(Entries[0].Flink, &ListHead);
91     ok_eq_free(Entries[0].Blink, &ListHead);
92     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
93     ok_irql(PASSIVE_LEVEL);
94 
95     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
96     ok_eq_pointer(Ret, NULL);
97     ok_eq_pointer(ListHead.Flink, &ListHead);
98     ok_eq_pointer(ListHead.Blink, &ListHead);
99     ok_eq_free(Entries[0].Flink, &ListHead);
100     ok_eq_free(Entries[0].Blink, &ListHead);
101     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
102     ok_irql(PASSIVE_LEVEL);
103 
104     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[0], &SpinLock);
105     ok_eq_pointer(Ret, NULL);
106     ok_eq_pointer(ListHead.Flink, &Entries[0]);
107     ok_eq_pointer(ListHead.Blink, &Entries[0]);
108     ok_eq_pointer(Entries[0].Flink, &ListHead);
109     ok_eq_pointer(Entries[0].Blink, &ListHead);
110     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
111     ok_irql(PASSIVE_LEVEL);
112 
113     Ret = ExInterlockedInsertHeadList(&ListHead, &Entries[1], &SpinLock);
114     ok_eq_pointer(Ret, &Entries[0]);
115     ok_eq_pointer(ListHead.Flink, &Entries[1]);
116     ok_eq_pointer(ListHead.Blink, &Entries[0]);
117     ok_eq_pointer(Entries[0].Flink, &ListHead);
118     ok_eq_pointer(Entries[0].Blink, &Entries[1]);
119     ok_eq_pointer(Entries[1].Flink, &Entries[0]);
120     ok_eq_pointer(Entries[1].Blink, &ListHead);
121     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
122     ok_irql(PASSIVE_LEVEL);
123 
124     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[2], &SpinLock);
125     ok_eq_pointer(Ret, &Entries[0]);
126     ok_eq_pointer(ListHead.Flink, &Entries[1]);
127     ok_eq_pointer(ListHead.Blink, &Entries[2]);
128     ok_eq_pointer(Entries[0].Flink, &Entries[2]);
129     ok_eq_pointer(Entries[0].Blink, &Entries[1]);
130     ok_eq_pointer(Entries[1].Flink, &Entries[0]);
131     ok_eq_pointer(Entries[1].Blink, &ListHead);
132     ok_eq_pointer(Entries[2].Flink, &ListHead);
133     ok_eq_pointer(Entries[2].Blink, &Entries[0]);
134     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
135     ok_irql(PASSIVE_LEVEL);
136 
137     memset(Entries, 0x55, sizeof Entries);
138 #undef ExInterlockedInsertHeadList
139 #undef ExInterlockedInsertTailList
140 #undef ExInterlockedRemoveHeadList
141 
142     memset(&ListHead, 0x55, sizeof ListHead);
143     InitializeListHead(&ListHead);
144     ok_eq_pointer(ListHead.Flink, &ListHead);
145     ok_eq_pointer(ListHead.Blink, &ListHead);
146     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
147     ok_irql(PASSIVE_LEVEL);
148 
149     Ret = ExInterlockedInsertHeadList(&ListHead, &Entries[0], &SpinLock);
150     ok_eq_pointer(Ret, NULL);
151     ok_eq_pointer(ListHead.Flink, &Entries[0]);
152     ok_eq_pointer(ListHead.Blink, &Entries[0]);
153     ok_eq_pointer(Entries[0].Flink, &ListHead);
154     ok_eq_pointer(Entries[0].Blink, &ListHead);
155     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
156     ok_irql(PASSIVE_LEVEL);
157 
158     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
159     ok_eq_pointer(Ret, &Entries[0]);
160     ok_eq_pointer(ListHead.Flink, &ListHead);
161     ok_eq_pointer(ListHead.Blink, &ListHead);
162     ok_eq_free2(Entries[0].Flink, &ListHead);
163     ok_eq_free2(Entries[0].Blink, &ListHead);
164     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
165     ok_irql(PASSIVE_LEVEL);
166 
167     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
168     ok_eq_pointer(Ret, NULL);
169     ok_eq_pointer(ListHead.Flink, &ListHead);
170     ok_eq_pointer(ListHead.Blink, &ListHead);
171     ok_eq_free2(Entries[0].Flink, &ListHead);
172     ok_eq_free2(Entries[0].Blink, &ListHead);
173     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
174     ok_irql(PASSIVE_LEVEL);
175 
176     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[0], &SpinLock);
177     ok_eq_pointer(Ret, NULL);
178     ok_eq_pointer(ListHead.Flink, &Entries[0]);
179     ok_eq_pointer(ListHead.Blink, &Entries[0]);
180     ok_eq_pointer(Entries[0].Flink, &ListHead);
181     ok_eq_pointer(Entries[0].Blink, &ListHead);
182     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
183     ok_irql(PASSIVE_LEVEL);
184 
185     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
186     ok_eq_pointer(Ret, &Entries[0]);
187     ok_eq_pointer(ListHead.Flink, &ListHead);
188     ok_eq_pointer(ListHead.Blink, &ListHead);
189     ok_eq_free2(Entries[0].Flink, &ListHead);
190     ok_eq_free2(Entries[0].Blink, &ListHead);
191     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
192     ok_irql(PASSIVE_LEVEL);
193 
194     Ret = ExInterlockedRemoveHeadList(&ListHead, &SpinLock);
195     ok_eq_pointer(Ret, NULL);
196     ok_eq_pointer(ListHead.Flink, &ListHead);
197     ok_eq_pointer(ListHead.Blink, &ListHead);
198     ok_eq_free2(Entries[0].Flink, &ListHead);
199     ok_eq_free2(Entries[0].Blink, &ListHead);
200     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
201     ok_irql(PASSIVE_LEVEL);
202 
203     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[0], &SpinLock);
204     ok_eq_pointer(Ret, NULL);
205     ok_eq_pointer(ListHead.Flink, &Entries[0]);
206     ok_eq_pointer(ListHead.Blink, &Entries[0]);
207     ok_eq_pointer(Entries[0].Flink, &ListHead);
208     ok_eq_pointer(Entries[0].Blink, &ListHead);
209     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
210     ok_irql(PASSIVE_LEVEL);
211 
212     Ret = ExInterlockedInsertHeadList(&ListHead, &Entries[1], &SpinLock);
213     ok_eq_pointer(Ret, &Entries[0]);
214     ok_eq_pointer(ListHead.Flink, &Entries[1]);
215     ok_eq_pointer(ListHead.Blink, &Entries[0]);
216     ok_eq_pointer(Entries[0].Flink, &ListHead);
217     ok_eq_pointer(Entries[0].Blink, &Entries[1]);
218     ok_eq_pointer(Entries[1].Flink, &Entries[0]);
219     ok_eq_pointer(Entries[1].Blink, &ListHead);
220     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
221     ok_irql(PASSIVE_LEVEL);
222 
223     Ret = ExInterlockedInsertTailList(&ListHead, &Entries[2], &SpinLock);
224     ok_eq_pointer(Ret, &Entries[0]);
225     ok_eq_pointer(ListHead.Flink, &Entries[1]);
226     ok_eq_pointer(ListHead.Blink, &Entries[2]);
227     ok_eq_pointer(Entries[0].Flink, &Entries[2]);
228     ok_eq_pointer(Entries[0].Blink, &Entries[1]);
229     ok_eq_pointer(Entries[1].Flink, &Entries[0]);
230     ok_eq_pointer(Entries[1].Blink, &ListHead);
231     ok_eq_pointer(Entries[2].Flink, &ListHead);
232     ok_eq_pointer(Entries[2].Blink, &Entries[0]);
233     ok_bool_true(KmtAreInterruptsEnabled(), "Interrupts enabled:");
234     ok_irql(PASSIVE_LEVEL);
235 
236     KmtSetIrql(PASSIVE_LEVEL);
237 }
238