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