[USP10_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / kmtests / ntos_ex / ExInterlocked.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Interlocked function test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <stddef.h>
9
10 /* missing prototypes >:| */
11 __declspec(dllimport) long __fastcall InterlockedCompareExchange(volatile long *, long, long);
12 __declspec(dllimport) __int64 __fastcall ExInterlockedCompareExchange64(volatile __int64 *, __int64 *, __int64 *, void *);
13 __declspec(dllimport) __int64 __fastcall ExfInterlockedCompareExchange64(volatile __int64 *, __int64 *, __int64 *);
14 __declspec(dllimport) long __fastcall InterlockedExchange(volatile long *, long);
15 __declspec(dllimport) unsigned long __stdcall ExInterlockedExchangeUlong(unsigned long *, unsigned long, void *);
16 __declspec(dllimport) long __fastcall InterlockedExchangeAdd(volatile long *, long);
17 #ifdef _X86_
18 __declspec(dllimport) unsigned long __stdcall ExInterlockedAddUlong(unsigned long *, unsigned long, unsigned long *);
19 #endif
20 __declspec(dllimport) unsigned long __stdcall Exi386InterlockedExchangeUlong(unsigned long *, unsigned long);
21 __declspec(dllimport) long __fastcall InterlockedIncrement(long *);
22 __declspec(dllimport) long __fastcall InterlockedDecrement(long *);
23 __declspec(dllimport) int __stdcall ExInterlockedIncrementLong(long *, void *);
24 __declspec(dllimport) int __stdcall ExInterlockedDecrementLong(long *, void *);
25 __declspec(dllimport) int __stdcall Exi386InterlockedIncrementLong(long *);
26 __declspec(dllimport) int __stdcall Exi386InterlockedDecrementLong(long *);
27
28 #include <kmt_test.h>
29
30 /* TODO: There are quite some changes needed for other architectures!
31 ExInterlockedAddLargeInteger, ExInterlockedAddUlong are the only two
32 functions actually exported by my win7/x64 kernel! */
33
34 /* TODO: stress-testing */
35
36 static KSPIN_LOCK SpinLock;
37
38 #ifdef _M_IX86
39 typedef struct
40 {
41 unsigned long esi, edi, ebx, ebp, esp;
42 } PROCESSOR_STATE;
43 #elif defined(_M_AMD64)
44 typedef struct
45 {
46 unsigned long long rsi, rdi, rbx, rbp, rsp, r12, r13, r14, r15;
47 } PROCESSOR_STATE;
48 #else
49 // dummy
50 typedef int PROCESSOR_STATE;
51 #endif
52
53 /* TODO: these need to be rewritten in proper assembly to account for registers
54 * saved by the caller */
55 #if defined(_MSC_VER) && defined(_M_IX86)
56 #define SaveState(State) do \
57 { \
58 __asm lea ecx, [State] \
59 __asm mov [ecx], esi \
60 __asm mov [ecx+4], edi \
61 __asm mov [ecx+8], ebx \
62 __asm mov [ecx+12], ebp \
63 __asm mov [ecx+16], esp \
64 } while (0)
65
66 #define CheckState(OldState, NewState) do \
67 { \
68 /* TODO: MSVC uses esi and saves it before, so this is okay */ \
69 /*ok_eq_hex((OldState)->esi, (NewState)->esi);*/ \
70 ok_eq_hex((OldState)->edi, (NewState)->edi); \
71 ok_eq_hex((OldState)->ebx, (NewState)->ebx); \
72 ok_eq_hex((OldState)->ebp, (NewState)->ebp); \
73 ok_eq_hex((OldState)->esp, (NewState)->esp); \
74 } while (0)
75
76 #elif defined(__GNUC__) && defined(_M_IX86)
77 #define SaveState(State) \
78 asm volatile( \
79 "movl\t%%esi, (%%ecx)\n\t" \
80 "movl\t%%edi, 4(%%ecx)\n\t" \
81 "movl\t%%ebx, 8(%%ecx)\n\t" \
82 "movl\t%%ebp, 12(%%ecx)\n\t" \
83 "movl\t%%esp, 16(%%ecx)" \
84 : : "c" (&State) : "memory" \
85 );
86
87 #define CheckState(OldState, NewState) do \
88 { \
89 /* TODO: GCC 4.7 uses esi and saves it before, so this is okay */ \
90 /*ok_eq_hex((OldState)->esi, (NewState)->esi);*/ \
91 ok_eq_hex((OldState)->edi, (NewState)->edi); \
92 /* TODO: GCC 4.4 uses ebx and saves it before, so this is okay */ \
93 /*ok_eq_hex((OldState)->ebx, (NewState)->ebx);*/ \
94 ok_eq_hex((OldState)->ebp, (NewState)->ebp); \
95 ok_eq_hex((OldState)->esp, (NewState)->esp); \
96 } while (0)
97 #elif defined(__GNUC__) && defined(_M_AMD64)
98 #define SaveState(State) \
99 asm volatile( \
100 "mov\t%%rsi, (%%rcx)\n\t" \
101 "mov\t%%rdi, 8(%%rcx)\n\t" \
102 "mov\t%%rbx, 16(%%rcx)\n\t" \
103 "mov\t%%rbp, 24(%%rcx)\n\t" \
104 "mov\t%%rsp, 32(%%rcx)\n\t" \
105 "mov\t%%r12, 40(%%rcx)\n\t" \
106 "mov\t%%r13, 48(%%rcx)\n\t" \
107 "mov\t%%r14, 56(%%rcx)\n\t" \
108 "mov\t%%r15, 64(%%rcx)" \
109 : : "c" (&State) : "memory" \
110 );
111
112 #define CheckState(OldState, NewState) do \
113 { \
114 ok_eq_hex((OldState)->rsi, (NewState)->rsi); \
115 ok_eq_hex((OldState)->rdi, (NewState)->rdi); \
116 ok_eq_hex((OldState)->rbx, (NewState)->rbx); \
117 ok_eq_hex((OldState)->rbp, (NewState)->rbp); \
118 ok_eq_hex((OldState)->rsp, (NewState)->rsp); \
119 ok_eq_hex((OldState)->r12, (NewState)->r12); \
120 ok_eq_hex((OldState)->r13, (NewState)->r13); \
121 ok_eq_hex((OldState)->r14, (NewState)->r14); \
122 ok_eq_hex((OldState)->r15, (NewState)->r15); \
123 } while (0)
124 #else
125 #define SaveState(State)
126 #define CheckState(OldState, NewState) do \
127 { \
128 (void)OldState; \
129 (void)NewState; \
130 } while (0)
131 #endif
132
133 static
134 LARGE_INTEGER
135 Large(
136 ULONGLONG Value)
137 {
138 LARGE_INTEGER Ret;
139 Ret.QuadPart = Value;
140 return Ret;
141 }
142
143 #define CheckInterlockedCmpXchg(Function, Type, Print, Val, Cmp, Xchg, \
144 ExpectedValue, ExpectedRet) do \
145 { \
146 Type Ret##Type = 0; \
147 Type Value##Type = Val; \
148 Status = STATUS_SUCCESS; \
149 _SEH2_TRY { \
150 SaveState(OldState); \
151 Ret##Type = Function(&Value##Type, Xchg, Cmp); \
152 SaveState(NewState); \
153 CheckState(&OldState, &NewState); \
154 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
155 Status = _SEH2_GetExceptionCode(); \
156 } _SEH2_END; \
157 ok_eq_hex(Status, STATUS_SUCCESS); \
158 ok_eq_print(Ret##Type, ExpectedRet, Print); \
159 ok_eq_print(Value##Type, ExpectedValue, Print); \
160 } while (0)
161
162 #define CheckInterlockedCmpXchgI(Function, Type, Print, Val, Cmp, Xchg, \
163 ExpectedValue, ExpectedRet, ...) do \
164 { \
165 Type Ret##Type = 0; \
166 Type Value##Type = Val; \
167 Type Compare##Type = Cmp; \
168 Type Exchange##Type = Xchg; \
169 Status = STATUS_SUCCESS; \
170 _SEH2_TRY { \
171 SaveState(OldState); \
172 Ret##Type = Function(&Value##Type, &Exchange##Type, \
173 &Compare##Type, ##__VA_ARGS__); \
174 SaveState(NewState); \
175 CheckState(&OldState, &NewState); \
176 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
177 Status = _SEH2_GetExceptionCode(); \
178 } _SEH2_END; \
179 ok_eq_hex(Status, STATUS_SUCCESS); \
180 ok_eq_print(Ret##Type, ExpectedRet, Print); \
181 ok_eq_print(Value##Type, ExpectedValue, Print); \
182 ok_eq_print(Exchange##Type, Xchg, Print); \
183 ok_eq_print(Compare##Type, Cmp, Print); \
184 } while(0)
185
186 #define CheckInterlockedOp(Function, Type, Print, Val, Op, \
187 ExpectedValue, ExpectedRet, ...) do \
188 { \
189 Type Ret##Type = 0; \
190 Type Value##Type = Val; \
191 Status = STATUS_SUCCESS; \
192 _SEH2_TRY { \
193 SaveState(OldState); \
194 Ret##Type = Function(&Value##Type, Op, ##__VA_ARGS__); \
195 SaveState(NewState); \
196 CheckState(&OldState, &NewState); \
197 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
198 Status = _SEH2_GetExceptionCode(); \
199 } _SEH2_END; \
200 ok_eq_hex(Status, STATUS_SUCCESS); \
201 ok_eq_print(Ret##Type, ExpectedRet, Print); \
202 ok_eq_print(Value##Type, ExpectedValue, Print); \
203 } while (0)
204
205 #define CheckInterlockedOpNoArg(Function, Type, Print, Val, \
206 ExpectedValue, ExpectedRet, ...) do \
207 { \
208 Type Ret##Type = 0; \
209 Type Value##Type = Val; \
210 Status = STATUS_SUCCESS; \
211 _SEH2_TRY { \
212 SaveState(OldState); \
213 Ret##Type = Function(&Value##Type, ##__VA_ARGS__); \
214 SaveState(NewState); \
215 CheckState(&OldState, &NewState); \
216 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
217 Status = _SEH2_GetExceptionCode(); \
218 } _SEH2_END; \
219 ok_eq_hex(Status, STATUS_SUCCESS); \
220 ok_eq_print(Ret##Type, ExpectedRet, Print); \
221 ok_eq_print(Value##Type, ExpectedValue, Print); \
222 } while (0)
223
224 #define CheckInterlockedOpLarge(Function, Type, Print, Val, Op, \
225 ExpectedValue, ExpectedRet, ...) do \
226 { \
227 Type Ret##Type = Large(0); \
228 Type Value##Type = Val; \
229 Status = STATUS_SUCCESS; \
230 _SEH2_TRY { \
231 SaveState(OldState); \
232 Ret##Type = Function(&Value##Type, Op, ##__VA_ARGS__); \
233 SaveState(NewState); \
234 CheckState(&OldState, &NewState); \
235 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
236 Status = _SEH2_GetExceptionCode(); \
237 } _SEH2_END; \
238 ok_eq_hex(Status, STATUS_SUCCESS); \
239 ok_eq_print(Ret##Type.QuadPart, ExpectedRet, Print); \
240 ok_eq_print(Value##Type.QuadPart, ExpectedValue, Print); \
241 } while (0)
242
243 #define CheckInterlockedOpLargeNoRet(Function, Type, Print, Val, Op, \
244 ExpectedValue) do \
245 { \
246 Type Value##Type = Val; \
247 Status = STATUS_SUCCESS; \
248 _SEH2_TRY { \
249 SaveState(OldState); \
250 Function(&Value##Type, Op); \
251 SaveState(NewState); \
252 CheckState(&OldState, &NewState); \
253 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
254 Status = _SEH2_GetExceptionCode(); \
255 } _SEH2_END; \
256 ok_eq_hex(Status, STATUS_SUCCESS); \
257 ok_eq_print(Value##Type.QuadPart, ExpectedValue, Print); \
258 } while (0)
259
260 static
261 VOID
262 TestInterlockedFunctional(VOID)
263 {
264 NTSTATUS Status;
265 PKSPIN_LOCK pSpinLock = &SpinLock;
266 PROCESSOR_STATE OldState, NewState;
267
268 /* on x86, most of these are supported intrinsically and don't need a spinlock! */
269 #if defined _M_IX86 || defined _M_AMD64
270 pSpinLock = NULL;
271 #endif
272
273 /* CompareExchange */
274 /* macro version */
275 CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 6, 8, 5L, 5L);
276 CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 5, 9, 9L, 5L);
277 /* these only exist as macros on x86 */
278 CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, "%ld", 16, 9, 12, 16L, 16L);
279 CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, "%ld", 16, 16, 4, 4L, 16L);
280 CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, "%ld", 27, 123, 38, 27L, 27L);
281 CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, "%ld", 27, 27, 39, 39L, 27L);
282 /* exported function */
283 #undef InterlockedCompareExchange
284 #ifdef _M_IX86
285 CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 6, 8, 5L, 5L);
286 CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 5, 9, 9L, 5L);
287 #endif
288 /* only exists as a macro */
289 CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, "%p", (PVOID)117, (PVOID)711, (PVOID)12, (PVOID)117, (PVOID)117);
290 CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, "%p", (PVOID)117, (PVOID)117, (PVOID)228, (PVOID)228, (PVOID)117);
291 /* macro version */
292 CheckInterlockedCmpXchgI(ExInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL, pSpinLock);
293 CheckInterlockedCmpXchgI(ExInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL, pSpinLock);
294 #ifdef _M_IX86
295 /* exported function */
296 CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL, pSpinLock);
297 CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL, pSpinLock);
298 /* fastcall version */
299 CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL);
300 CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL);
301 #endif
302
303 /* Exchange */
304 CheckInterlockedOp(InterlockedExchange, LONG, "%ld", 5, 8, 8L, 5L);
305 CheckInterlockedOpNoArg(InterlockedExchangePointer, PVOID, "%p", (PVOID)700, (PVOID)93, (PVOID)700, (PVOID)93);
306 #undef InterlockedExchange
307 #ifdef _M_IX86
308 CheckInterlockedOp(InterlockedExchange, LONG, "%ld", 5, 8, 8L, 5L);
309 CheckInterlockedOp(ExInterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU, pSpinLock);
310 CheckInterlockedOp((ExInterlockedExchangeUlong), ULONG, "%lu", 212, 121, 121LU, 212LU, pSpinLock);
311 CheckInterlockedOp(Exi386InterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU);
312 CheckInterlockedOp(Exfi386InterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU);
313 #endif
314
315 /* ExchangeAdd */
316 /* TODO: ExInterlockedExchangeAddLargeInteger? */
317 CheckInterlockedOp(InterlockedExchangeAdd, LONG, "%ld", 312, 7, 319L, 312L);
318 #undef InterlockedExchangeAdd
319 #ifdef _M_IX86
320 CheckInterlockedOp(InterlockedExchangeAdd, LONG, "%ld", 312, 7, 319L, 312L);
321 #endif
322
323 /* Add */
324 /* these DO need a valid spinlock even on x86 */
325 CheckInterlockedOpLarge(ExInterlockedAddLargeInteger, LARGE_INTEGER, "%I64d", Large(23), Large(7), 30LL, 23LL, &SpinLock);
326 CheckInterlockedOpLargeNoRet(ExInterlockedAddLargeStatistic, LARGE_INTEGER, "%I64d", Large(15), 17LL, 32LL);
327 CheckInterlockedOp(ExInterlockedAddUlong, ULONG, "%lu", 239, 44, 283LU, 239LU, &SpinLock);
328 #undef ExInterlockedAddUlong
329 CheckInterlockedOp(ExInterlockedAddUlong, ULONG, "%lu", 239, 44, 283LU, 239LU, &SpinLock);
330
331 /* Increment */
332 CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", 2341L, 2342L, 2342L);
333 CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)MINLONG);
334 CheckInterlockedOpNoArg(InterlockedIncrementAcquire, LONG, "%ld", 2341L, 2342L, 2342L);
335 CheckInterlockedOpNoArg(InterlockedIncrementRelease, LONG, "%ld", 2341L, 2342L, 2342L);
336 #undef InterlockedIncrement
337 #ifdef _M_IX86
338 CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", 2341L, 2342L, 2342L);
339 CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)MINLONG);
340 CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock);
341 CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock);
342 CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock);
343 CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock);
344 CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock);
345 CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock);
346 CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock);
347 CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock);
348 CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", -2L, -1L, (LONG)ResultNegative);
349 CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", -1L, 0L, (LONG)ResultZero);
350 CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", 0L, 1L, (LONG)ResultPositive);
351 CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative);
352 #endif
353
354 /* Decrement */
355 CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", 1745L, 1744L, 1744L);
356 CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)MAXLONG);
357 CheckInterlockedOpNoArg(InterlockedDecrementAcquire, LONG, "%ld", 1745L, 1744L, 1744L);
358 CheckInterlockedOpNoArg(InterlockedDecrementRelease, LONG, "%ld", 1745L, 1744L, 1744L);
359 #undef InterlockedDecrement
360 #ifdef _M_IX86
361 CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", 1745L, 1744L, 1744L);
362 CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)MAXLONG);
363 CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock);
364 CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock);
365 CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock);
366 CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock);
367 CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock);
368 CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock);
369 CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock);
370 CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock);
371 CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive);
372 CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 0L, -1L, (LONG)ResultNegative);
373 CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 1L, 0L, (LONG)ResultZero);
374 CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 2L, 1L, (LONG)ResultPositive);
375 #endif
376
377 /* And, Or, Xor */
378 CheckInterlockedOp(InterlockedAnd, LONG, "0x%lx", 0x1234L, 0x1111L, 0x1010L, 0x1234L);
379 CheckInterlockedOp(InterlockedOr, LONG, "0x%lx", 0x1234L, 0x1111L, 0x1335L, 0x1234L);
380 CheckInterlockedOp(InterlockedXor, LONG, "0x%lx", 0x1234L, 0x1111L, 0x0325L, 0x1234L);
381 #ifdef _WIN64
382 CheckInterlockedOp(InterlockedXor64, LONGLONG, "0x%I64x", 0x200001234LL, 0x100001111LL, 0x300000325LL, 0x200001234LL);
383 #endif
384 }
385
386 START_TEST(ExInterlocked)
387 {
388 KIRQL Irql;
389 KeInitializeSpinLock(&SpinLock);
390
391 /* functional testing */
392 TestInterlockedFunctional();
393 KeRaiseIrql(HIGH_LEVEL, &Irql);
394 TestInterlockedFunctional();
395 KeLowerIrql(Irql);
396 }