Index: kmtests/CMakeLists.txt =================================================================== --- kmtests/CMakeLists.txt (Revision 57099) +++ kmtests/CMakeLists.txt (Arbeitskopie) @@ -56,6 +56,12 @@ kmtest_drv/kmtest_drv.rc) +if (ARCH STREQUAL "i386") + list(APPEND KMTEST_DRV_SOURCE kmtest_drv/asmtools-i386.S) +else() + list(APPEND KMTEST_DRV_SOURCE kmtest_drv/asmtools-amd64.S) +endif() + add_library(kmtest_drv SHARED ${KMTEST_DRV_SOURCE}) set_module_type(kmtest_drv kernelmodedriver) @@ -91,6 +97,7 @@ kmtest/kmtest.rc) + add_executable(kmtest ${KMTEST_SOURCE}) set_module_type(kmtest win32cui) target_link_libraries(kmtest ${PSEH_LIB}) Index: kmtests/include/kmt_test.h =================================================================== --- kmtests/include/kmt_test.h (Revision 57099) +++ kmtests/include/kmt_test.h (Arbeitskopie) @@ -187,6 +187,96 @@ } _SEH2_END; \ ok_eq_hex(ExceptionStatus, ExpectedStatus) +ULONGLONG +__cdecl +KmtCallWrapper( + PCONTEXT PreState, + PCONTEXT PostState, + PVOID Function, + BOOLEAN FastCall, + ULONG NumberParameters, + ...); + +/* The following bits (flags) must be kept: + 1, 3, 5, 8 (TF), 9 (IF), 10 (DF), 12-13 (IOPL), 14 (NT), 15, 16-31: + binary 11111111111111111111011100101010 */ +#define EFLAGS_NONVOLATILE 0xFFFFF72A + +#if defined (_M_IX86) + +#define CheckContext(OldContext, NewContext) \ +do { \ + ok_eq_hex((NewContext)->Ebx, (OldContext)->Ebx); \ + ok_eq_hex((NewContext)->Esi, (OldContext)->Esi); \ + ok_eq_hex((NewContext)->Edi, (OldContext)->Edi); \ + ok_eq_hex((NewContext)->Esp, (OldContext)->Esp); \ + ok_eq_hex((NewContext)->Ebp, (OldContext)->Ebp); \ + ok_eq_hex((NewContext)->EFlags & EFLAGS_NONVOLATILE, (OldContext)->EFlags & EFLAGS_NONVOLATILE); \ +} while (0) + +#elif defined(_M_AMD64) + +#define CheckContext(OldContext, NewContext) do \ +{ \ + ok_eq_hex((NewContext)->Rbx, (OldContext)->Rbx); \ + ok_eq_hex((NewContext)->Rsi, (OldContext)->Rsi); \ + ok_eq_hex((NewContext)->Rdi, (OldContext)->Rdi); \ + ok_eq_hex((NewContext)->Rsp, (OldContext)->Rsp); \ + ok_eq_hex((NewContext)->Rbp, (OldContext)->Rbp); \ + ok_eq_hex((NewContext)->R12, (OldContext)->R12); \ + ok_eq_hex((NewContext)->R13, (OldContext)->R13); \ + ok_eq_hex((NewContext)->R14, (OldContext)->R14); \ + ok_eq_hex((NewContext)->R15, (OldContext)->R15); \ + ok_eq_hex((NewContext)->EFlags & EFLAGS_NONVOLATILE, (OldContext)->EFlags & EFLAGS_NONVOLATILE); \ +} while (0) + +#else +#error unsupported architecture +#endif + +FORCEINLINE +LARGE_INTEGER +Large( + ULONGLONG Value) +{ + LARGE_INTEGER Ret; + Ret.QuadPart = Value; + return Ret; +} + +#define _Convert(Value, Type) _ConvertTo_##Type(Value) +#define _ConvertTo_ULONG(Value) ((ULONG)(Value)) +#define _ConvertTo_LONG(Value) ((LONG)(ULONG)(Value)) +#define _ConvertTo_LONGLONG(Value) ((LONGLONG)(Value)) +#define _ConvertTo_USHORT(Value) ((USHORT)(Value)) +#define _ConvertTo_UCHAR(Value) ((UCHAR)(Value)) +#define _ConvertTo_PVOID(Value) ((PVOID)(ULONG_PTR)(Value)) +#define _ConvertTo_LARGE_INTEGER(Value) Large(Value) + +// This works for stdcall and fastcall, for cdecl we need to take into account +// that the function returns with a modified stack pointer, so we would need +// a seperate macro +#define CALL_WRAPPER(Ret, RetType, FastCall, Function, ...) \ +do { \ + NTSTATUS Status = STATUS_SUCCESS; \ + ULONGLONG _Ret; \ + _SEH2_TRY { \ + _Ret = KmtCallWrapper(&PreContext, &PostContext, Function, \ + FastCall, PP_NARGS(__VA_ARGS__), __VA_ARGS__); \ + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ + Status = _SEH2_GetExceptionCode(); \ + } _SEH2_END; \ + ok_eq_hex(Status, STATUS_SUCCESS); \ + CheckContext(&PreContext, &PostContext); \ + *(Ret) = _Convert(_Ret, RetType); \ +} while (0) + +/* Helper to count number of parameters in variadic macro */ +#define EXPAND(x) x +#define PP_NARGS(...) \ + EXPAND(_xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) +#define _xPP_NARGS_IMPL(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,N,...) N + #if defined KMT_DEFINE_TEST_FUNCTIONS #if defined KMT_KERNEL_MODE Index: kmtests/kmtest_drv/asmtools-i386.S =================================================================== --- kmtests/kmtest_drv/asmtools-i386.S (Revision 0) +++ kmtests/kmtest_drv/asmtools-i386.S (Arbeitskopie) @@ -0,0 +1,130 @@ + + +#include +#include + +.code + +EXTERN _ExRaiseStatus@4:PROC +STATUS_BAD_STACK = HEX(C0000028) + +STACK_COOKIE = HEX(1337babe) + +InternalGetContext: + mov dword ptr [ecx + CONTEXT_FLAGS], CONTEXT_FULL + mov dword ptr [ecx + CONTEXT_EDI], edi + mov dword ptr [ecx + CONTEXT_ESI], esi + mov dword ptr [ecx + CONTEXT_EBX], ebx + mov dword ptr [ecx + CONTEXT_EDX], edx + mov dword ptr [ecx + CONTEXT_ECX], ecx + mov dword ptr [ecx + CONTEXT_EAX], eax + mov dword ptr [ecx + CONTEXT_EBP], ebp + mov eax, [esp] + mov dword ptr [ecx + CONTEXT_EIP], eax + mov dword ptr [ecx + CONTEXT_SEGCS], KGDT_R0_CODE + pushfd + pop eax + mov dword ptr [ecx + CONTEXT_EFLAGS], eax + mov dword ptr [ecx + CONTEXT_ESP], esp + mov dword ptr [ecx + CONTEXT_SEGSS], KGDT_R0_DATA + mov eax, ds + mov dword ptr [ecx + CONTEXT_SEGDS], eax + mov eax, es + mov dword ptr [ecx + CONTEXT_SEGES], eax + mov eax, fs + mov dword ptr [ecx + CONTEXT_SEGFS], eax + mov eax, gs + mov dword ptr [ecx + CONTEXT_SEGGS], eax + + /* Restore eax */ + mov eax, dword ptr [ecx + CONTEXT_EAX] + ret + +/* +ULONGLONG +__cdecl +KmtCallWrapper( + PCONTEXT PreState, + PCONTEXT PostState, + PVOID Function, + BOOLEAN FastCall, + ULONG NumberParameters, + ...); +*/ +P_PreState = 8 +P_PostState = 12 +P_Function = 16 +P_FastCall = 20 +P_NumberParameters = 24 +P_Parameters = 28 + +PUBLIC _KmtCallWrapper +_KmtCallWrapper: +//int 3 + push ebp + mov ebp, esp + + /* Push a "stack cookie" */ + push STACK_COOKIE + + /* Save the PreState */ + mov ecx, dword ptr [ebp + P_PreState] + call InternalGetContext + + /* Make room for the parameters on the stack */ + mov ecx, dword ptr [ebp + P_NumberParameters] + shl ecx, 2 + sub esp, ecx + + /* Copy the parameters to the the stack */ + push esi + push edi + lea esi, dword ptr [ebp + P_Parameters] + lea edi, [esp + 8] + mov ecx, dword ptr [ebp + P_NumberParameters] + rep movsd + pop edi + pop esi + + /* Check if this is a fastcall function */ + cmp byte ptr [ebp + P_FastCall], 0 + je DoTheCall + + /* Check if we have 0 parameters */ + cmp dword ptr [ebp + P_NumberParameters], 0 + je DoTheCall + + /* Pop the first argument from the stack */ + pop ecx + + /* Check if we have only 1 parameter */ + cmp dword ptr [ebp + P_NumberParameters], 1 + je DoTheCall + + /* Pop the second argument from the stack */ + pop edx + +DoTheCall: + + /* Call the function */ + call dword ptr [ebp + P_Function] + + /* Check if we still have the stack cookie where it should be (rel to ebp) */ + cmp dword ptr [ebp - 4], STACK_COOKIE + jne stackfailure + + /* Save the PostState */ + mov ecx, dword ptr [ebp + P_PostState] + call InternalGetContext + + /* Cleanup stack and return */ + mov esp, ebp + pop ebp + ret + +stackfailure: + /* This is bad */ + push STATUS_BAD_STACK + call _ExRaiseStatus@4 + +END Index: kmtests/ntos_ex/ExInterlocked.c =================================================================== --- kmtests/ntos_ex/ExInterlocked.c (Revision 57099) +++ kmtests/ntos_ex/ExInterlocked.c (Arbeitskopie) @@ -3,10 +3,29 @@ * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Kernel-Mode Test Suite Interlocked function test * PROGRAMMER: Thomas Faber + * Timo Kreuzer */ #include +#include +#undef InterlockedCompareExchange +#undef ExInterlockedCompareExchange64 +#undef ExfInterlockedCompareExchange64 +#undef InterlockedExchange +#undef ExInterlockedExchangeUlong +#undef InterlockedExchangeAdd +#undef ExInterlockedAddUlong +#undef Exi386InterlockedExchangeUlong +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef ExInterlockedIncrementLong +#undef ExInterlockedDecrementLong +#undef Exi386InterlockedIncrementLong +#undef Exi386InterlockedDecrementLong +#undef InterlockedXor +#undef ExInterlockedAddLargeStatistic + /* missing prototypes >:| */ __declspec(dllimport) long __fastcall InterlockedCompareExchange(volatile long *, long, long); __declspec(dllimport) __int64 __fastcall ExInterlockedCompareExchange64(volatile __int64 *, __int64 *, __int64 *, void *); @@ -24,8 +43,8 @@ __declspec(dllimport) int __stdcall ExInterlockedDecrementLong(long *, void *); __declspec(dllimport) int __stdcall Exi386InterlockedIncrementLong(long *); __declspec(dllimport) int __stdcall Exi386InterlockedDecrementLong(long *); +__declspec(dllimport) void __fastcall ExInterlockedAddLargeStatistic(LARGE_INTEGER *, ULONG); -#include /* TODO: There are quite some changes needed for other architectures! ExInterlockedAddLargeInteger, ExInterlockedAddUlong are the only two @@ -35,230 +54,75 @@ static KSPIN_LOCK SpinLock; -#ifdef _M_IX86 -typedef struct -{ - unsigned long esi, edi, ebx, ebp, esp; -} PROCESSOR_STATE; -#elif defined(_M_AMD64) -typedef struct -{ - unsigned long long rsi, rdi, rbx, rbp, rsp, r12, r13, r14, r15; -} PROCESSOR_STATE; -#else -// dummy -typedef int PROCESSOR_STATE; -#endif - -#if defined(_MSC_VER) && defined(_M_IX86) -#define SaveState(State) do \ -{ \ - __asm lea ecx, [State] \ - __asm mov [ecx], esi \ - __asm mov [ecx+4], edi \ - __asm mov [ecx+8], ebx \ - __asm mov [ecx+12], ebp \ - __asm mov [ecx+16], esp \ -} while (0) - -#define CheckState(OldState, NewState) do \ -{ \ - /* TODO: MSVC uses esi and saves it before, so this is okay */ \ - /*ok_eq_hex((OldState)->esi, (NewState)->esi);*/ \ - ok_eq_hex((OldState)->edi, (NewState)->edi); \ - ok_eq_hex((OldState)->ebx, (NewState)->ebx); \ - ok_eq_hex((OldState)->ebp, (NewState)->ebp); \ - ok_eq_hex((OldState)->esp, (NewState)->esp); \ -} while (0) - -#elif defined(__GNUC__) && defined(_M_IX86) -#define SaveState(State) \ - asm volatile( \ - "movl\t%%esi, (%%ecx)\n\t" \ - "movl\t%%edi, 4(%%ecx)\n\t" \ - "movl\t%%ebx, 8(%%ecx)\n\t" \ - "movl\t%%ebp, 12(%%ecx)\n\t" \ - "movl\t%%esp, 16(%%ecx)" \ - : : "c" (&State) : "memory" \ - ); - -#define CheckState(OldState, NewState) do \ -{ \ - ok_eq_hex((OldState)->esi, (NewState)->esi); \ - ok_eq_hex((OldState)->edi, (NewState)->edi); \ - /* TODO: GCC uses ebx and saves it before, so this is okay */ \ - /*ok_eq_hex((OldState)->ebx, (NewState)->ebx);*/ \ - ok_eq_hex((OldState)->ebp, (NewState)->ebp); \ - ok_eq_hex((OldState)->esp, (NewState)->esp); \ -} while (0) -#elif defined(__GNUC__) && defined(_M_AMD64) -#define SaveState(State) \ - asm volatile( \ - "mov\t%%rsi, (%%rcx)\n\t" \ - "mov\t%%rdi, 8(%%rcx)\n\t" \ - "mov\t%%rbx, 16(%%rcx)\n\t" \ - "mov\t%%rbp, 24(%%rcx)\n\t" \ - "mov\t%%rsp, 32(%%rcx)\n\t" \ - "mov\t%%r12, 40(%%rcx)\n\t" \ - "mov\t%%r13, 48(%%rcx)\n\t" \ - "mov\t%%r14, 56(%%rcx)\n\t" \ - "mov\t%%r15, 64(%%rcx)" \ - : : "c" (&State) : "memory" \ - ); - -#define CheckState(OldState, NewState) do \ -{ \ - ok_eq_hex((OldState)->rsi, (NewState)->rsi); \ - ok_eq_hex((OldState)->rdi, (NewState)->rdi); \ - ok_eq_hex((OldState)->rbx, (NewState)->rbx); \ - ok_eq_hex((OldState)->rbp, (NewState)->rbp); \ - ok_eq_hex((OldState)->rsp, (NewState)->rsp); \ - ok_eq_hex((OldState)->r12, (NewState)->r12); \ - ok_eq_hex((OldState)->r13, (NewState)->r13); \ - ok_eq_hex((OldState)->r14, (NewState)->r14); \ - ok_eq_hex((OldState)->r15, (NewState)->r15); \ -} while (0) -#else -#define SaveState(State) -#define CheckState(OldState, NewState) do \ -{ \ - (void)OldState; \ - (void)NewState; \ -} while (0) -#endif - -static -LARGE_INTEGER -Large( - ULONGLONG Value) -{ - LARGE_INTEGER Ret; - Ret.QuadPart = Value; - return Ret; -} - -#define CheckInterlockedCmpXchg(Function, Type, Print, Val, Cmp, Xchg, \ +#define CheckInterlockedCmpXchg(Function, Type, Fc, Print, Val, Cmp, Xchg, \ ExpectedValue, ExpectedRet) do \ { \ Type Ret##Type = 0; \ Type Value##Type = Val; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Ret##Type = Function(&Value##Type, Xchg, Cmp); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, &Value##Type, Xchg, Cmp); \ ok_eq_print(Ret##Type, ExpectedRet, Print); \ ok_eq_print(Value##Type, ExpectedValue, Print); \ } while (0) -#define CheckInterlockedCmpXchgI(Function, Type, Print, Val, Cmp, Xchg, \ +#define CheckInterlockedCmpXchgI(Function, Type, Fc, Print, Val, Cmp, Xchg, \ ExpectedValue, ExpectedRet, ...) do \ { \ Type Ret##Type = 0; \ Type Value##Type = Val; \ Type Compare##Type = Cmp; \ Type Exchange##Type = Xchg; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Ret##Type = Function(&Value##Type, &Exchange##Type, \ - &Compare##Type, ##__VA_ARGS__); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, &Value##Type, \ + &Exchange##Type, &Compare##Type, ##__VA_ARGS__); \ ok_eq_print(Ret##Type, ExpectedRet, Print); \ ok_eq_print(Value##Type, ExpectedValue, Print); \ ok_eq_print(Exchange##Type, Xchg, Print); \ ok_eq_print(Compare##Type, Cmp, Print); \ } while(0) -#define CheckInterlockedOp(Function, Type, Print, Val, Op, \ +#define CheckInterlockedOp(Function, Type, Fc, Print, Val, Op, \ ExpectedValue, ExpectedRet, ...) do \ { \ Type Ret##Type = 0; \ Type Value##Type = Val; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Ret##Type = Function(&Value##Type, Op, ##__VA_ARGS__); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, \ + &Value##Type, Op, ##__VA_ARGS__); \ ok_eq_print(Ret##Type, ExpectedRet, Print); \ ok_eq_print(Value##Type, ExpectedValue, Print); \ } while (0) -#define CheckInterlockedOpNoArg(Function, Type, Print, Val, \ +#define CheckInterlockedOpNoArg(Function, Type, Fc, Print, Val, \ ExpectedValue, ExpectedRet, ...) do \ { \ Type Ret##Type = 0; \ Type Value##Type = Val; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Ret##Type = Function(&Value##Type, ##__VA_ARGS__); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, \ + &Value##Type, ##__VA_ARGS__); \ ok_eq_print(Ret##Type, ExpectedRet, Print); \ ok_eq_print(Value##Type, ExpectedValue, Print); \ } while (0) -#define CheckInterlockedOpLarge(Function, Type, Print, Val, Op, \ +#define CheckInterlockedOpLarge(Function, Type, Fc, Print, Val, Op, \ ExpectedValue, ExpectedRet, ...) do \ { \ Type Ret##Type = Large(0); \ Type Value##Type = Val; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Ret##Type = Function(&Value##Type, Op, ##__VA_ARGS__); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, \ + &Value##Type, Op, ##__VA_ARGS__); \ ok_eq_print(Ret##Type.QuadPart, ExpectedRet, Print); \ ok_eq_print(Value##Type.QuadPart, ExpectedValue, Print); \ } while (0) -#define CheckInterlockedOpLargeNoRet(Function, Type, Print, Val, Op, \ +#define CheckInterlockedOpLargeNoRet(Function, Type, Fc, Print, Val, Op, \ ExpectedValue) do \ { \ + Type Ret##Type; \ Type Value##Type = Val; \ - Status = STATUS_SUCCESS; \ - _SEH2_TRY { \ - SaveState(OldState); \ - Function(&Value##Type, Op); \ - SaveState(NewState); \ - CheckState(&OldState, &NewState); \ - } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \ - Status = _SEH2_GetExceptionCode(); \ - } _SEH2_END; \ - ok_eq_hex(Status, STATUS_SUCCESS); \ + CALL_WRAPPER(&Ret##Type, Type, Fc, Function, \ + &Value##Type, Op); \ ok_eq_print(Value##Type.QuadPart, ExpectedValue, Print); \ } while (0) /* TODO: missing in wdm.h! */ -#define InterlockedCompareExchangeAcquire InterlockedCompareExchange -#define InterlockedCompareExchangeRelease InterlockedCompareExchange -#define InterlockedIncrementAcquire InterlockedIncrement -#define InterlockedIncrementRelease InterlockedIncrement #define InterlockedDecrementAcquire InterlockedDecrement #define InterlockedDecrementRelease InterlockedDecrement @@ -266,9 +130,8 @@ VOID TestInterlockedFunctional(VOID) { - NTSTATUS Status; PKSPIN_LOCK pSpinLock = &SpinLock; - PROCESSOR_STATE OldState, NewState; + CONTEXT PreContext, PostContext; /* on x86, most of these are supported intrinsically and don't need a spinlock! */ #if defined _M_IX86 || defined _M_AMD64 @@ -276,118 +139,121 @@ #endif /* CompareExchange */ - /* macro version */ - CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 6, 8, 5L, 5L); - CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 5, 9, 9L, 5L); - /* these only exist as macros on x86 */ - CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, "%ld", 16, 9, 12, 16L, 16L); - CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, "%ld", 16, 16, 4, 4L, 16L); - CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, "%ld", 27, 123, 38, 27L, 27L); - CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, "%ld", 27, 27, 39, 39L, 27L); +#if 0 // whi implements these? + CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, 0, "%ld", 16, 9, 12, 16L, 16L); + CheckInterlockedCmpXchg(InterlockedCompareExchangeAcquire, LONG, 0, "%ld", 16, 16, 4, 4L, 16L); + CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, 0, "%ld", 27, 123, 38, 27L, 27L); + CheckInterlockedCmpXchg(InterlockedCompareExchangeRelease, LONG, 0, "%ld", 27, 27, 39, 39L, 27L); +#endif + /* exported function */ -#undef InterlockedCompareExchange #ifdef _M_IX86 - CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 6, 8, 5L, 5L); - CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, "%ld", 5, 5, 9, 9L, 5L); + CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, 1, "%ld", 5, 6, 8, 5L, 5L); + CheckInterlockedCmpXchg(InterlockedCompareExchange, LONG, 1, "%ld", 5, 5, 9, 9L, 5L); #endif +#ifndef _M_IX86 /* only exists as a macro */ - CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, "%p", (PVOID)117, (PVOID)711, (PVOID)12, (PVOID)117, (PVOID)117); - CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, "%p", (PVOID)117, (PVOID)117, (PVOID)228, (PVOID)228, (PVOID)117); - /* macro version */ - CheckInterlockedCmpXchgI(ExInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL, pSpinLock); - CheckInterlockedCmpXchgI(ExInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL, pSpinLock); + CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, 0, "%p", (PVOID)117, (PVOID)711, (PVOID)12, (PVOID)117, (PVOID)117); + CheckInterlockedCmpXchg(InterlockedCompareExchangePointer, PVOID, 0, "%p", (PVOID)117, (PVOID)117, (PVOID)228, (PVOID)228, (PVOID)117); +#endif #ifdef _M_IX86 /* exported function */ - CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL, pSpinLock); - CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL, pSpinLock); + CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, 1, "%I64d", 17, 4LL, 20LL, 17LL, 17LL, pSpinLock); + CheckInterlockedCmpXchgI((ExInterlockedCompareExchange64), LONGLONG, 1, "%I64d", 17, 17LL, 21LL, 21LL, 17LL, pSpinLock); /* fastcall version */ - CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 4LL, 20LL, 17LL, 17LL); - CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, "%I64d", 17, 17LL, 21LL, 21LL, 17LL); + CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, 1, "%I64d", 17, 4LL, 20LL, 17LL, 17LL); + CheckInterlockedCmpXchgI(ExfInterlockedCompareExchange64, LONGLONG, 1, "%I64d", 17, 17LL, 21LL, 21LL, 17LL); #endif /* Exchange */ - CheckInterlockedOp(InterlockedExchange, LONG, "%ld", 5, 8, 8L, 5L); - CheckInterlockedOpNoArg(InterlockedExchangePointer, PVOID, "%p", (PVOID)700, (PVOID)93, (PVOID)700, (PVOID)93); -#undef InterlockedExchange #ifdef _M_IX86 - CheckInterlockedOp(InterlockedExchange, LONG, "%ld", 5, 8, 8L, 5L); - CheckInterlockedOp(ExInterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU, pSpinLock); - CheckInterlockedOp((ExInterlockedExchangeUlong), ULONG, "%lu", 212, 121, 121LU, 212LU, pSpinLock); - CheckInterlockedOp(Exi386InterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU); - CheckInterlockedOp(Exfi386InterlockedExchangeUlong, ULONG, "%lu", 212, 121, 121LU, 212LU); + CheckInterlockedOp(InterlockedExchange, LONG, 1, "%ld", 5, 8, 8L, 5L); + CheckInterlockedOp(ExInterlockedExchangeUlong, ULONG, 0, "%lu", 212, 121, 121LU, 212LU, pSpinLock); + CheckInterlockedOp((ExInterlockedExchangeUlong), ULONG, 0, "%lu", 212, 121, 121LU, 212LU, pSpinLock); + CheckInterlockedOp(Exi386InterlockedExchangeUlong, ULONG, 0, "%lu", 212, 121, 121LU, 212LU); + CheckInterlockedOp(Exfi386InterlockedExchangeUlong, ULONG, 1, "%lu", 212, 121, 121LU, 212LU); #endif /* ExchangeAdd */ /* TODO: ExInterlockedExchangeAddLargeInteger? */ - CheckInterlockedOp(InterlockedExchangeAdd, LONG, "%ld", 312, 7, 319L, 312L); -#undef InterlockedExchangeAdd + CheckInterlockedOp(InterlockedExchangeAdd, LONG, 1, "%ld", 312, 7, 319L, 312L); #ifdef _M_IX86 - CheckInterlockedOp(InterlockedExchangeAdd, LONG, "%ld", 312, 7, 319L, 312L); + CheckInterlockedOp(InterlockedExchangeAdd, LONG, 1, "%ld", 312, 7, 319L, 312L); #endif /* Add */ /* these DO need a valid spinlock even on x86 */ - CheckInterlockedOpLarge(ExInterlockedAddLargeInteger, LARGE_INTEGER, "%I64d", Large(23), Large(7), 30LL, 23LL, &SpinLock); - CheckInterlockedOpLargeNoRet(ExInterlockedAddLargeStatistic, LARGE_INTEGER, "%I64d", Large(15), 17LL, 32LL); - CheckInterlockedOp(ExInterlockedAddUlong, ULONG, "%lu", 239, 44, 283LU, 239LU, &SpinLock); -#undef ExInterlockedAddUlong - CheckInterlockedOp(ExInterlockedAddUlong, ULONG, "%lu", 239, 44, 283LU, 239LU, &SpinLock); +#ifndef _WIN64 + /* Note the "trick", passing one additional parameter to the macro. + This is because we have a LARGE_INTEGER, which is 2 parameters on x86 */ + CheckInterlockedOpLarge(ExInterlockedAddLargeInteger, LARGE_INTEGER, 0, "%I64d", Large(23), Large(7), 30LL, 23LL, &SpinLock, 0); +#else + CheckInterlockedOpLarge(ExInterlockedAddLargeInteger, LARGE_INTEGER, 0, "%I64d", Large(23), Large(7), 30LL, 23LL, &SpinLock); +#endif + CheckInterlockedOpLargeNoRet(ExInterlockedAddLargeStatistic, LARGE_INTEGER, 1, "%I64d", Large(15), 17LL, 32LL); + CheckInterlockedOp(ExInterlockedAddUlong, ULONG, 0, "%lu", 239, 44, 283LU, 239LU, &SpinLock); /* Increment */ - CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", 2341L, 2342L, 2342L); - CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)MINLONG); - CheckInterlockedOpNoArg(InterlockedIncrementAcquire, LONG, "%ld", 2341L, 2342L, 2342L); - CheckInterlockedOpNoArg(InterlockedIncrementRelease, LONG, "%ld", 2341L, 2342L, 2342L); -#undef InterlockedIncrement +#if 0 + CheckInterlockedOpNoArg(InterlockedIncrementAcquire, LONG, 0, "%ld", 2341L, 2342L, 2342L); + CheckInterlockedOpNoArg(InterlockedIncrementRelease, LONG, 0, "%ld", 2341L, 2342L, 2342L); +#endif #ifdef _M_IX86 - CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", 2341L, 2342L, 2342L); - CheckInterlockedOpNoArg(InterlockedIncrement, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)MINLONG); - CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", -2L, -1L, (LONG)ResultNegative); - CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", -1L, 0L, (LONG)ResultZero); - CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", 0L, 1L, (LONG)ResultPositive); - CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative); + CheckInterlockedOpNoArg(InterlockedIncrement, LONG, 1, "%ld", 2341L, 2342L, 2342L); + CheckInterlockedOpNoArg(InterlockedIncrement, LONG, 1, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)MINLONG); + CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, 0, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, 0, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, 0, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedIncrementLong, LONG, 0, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, 0, "%ld", -2L, -1L, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, 0, "%ld", -1L, 0L, (LONG)ResultZero, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, 0, "%ld", 0L, 1L, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedIncrementLong), LONG, 0, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, 0, "%ld", -2L, -1L, (LONG)ResultNegative); + CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, 0, "%ld", -1L, 0L, (LONG)ResultZero); + CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, 0, "%ld", 0L, 1L, (LONG)ResultPositive); + CheckInterlockedOpNoArg(Exi386InterlockedIncrementLong, LONG, 0, "%ld", (LONG)MAXLONG, (LONG)MINLONG, (LONG)ResultNegative); #endif /* Decrement */ - CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", 1745L, 1744L, 1744L); - CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)MAXLONG); - CheckInterlockedOpNoArg(InterlockedDecrementAcquire, LONG, "%ld", 1745L, 1744L, 1744L); - CheckInterlockedOpNoArg(InterlockedDecrementRelease, LONG, "%ld", 1745L, 1744L, 1744L); -#undef InterlockedDecrement +#if 0 + CheckInterlockedOpNoArg(InterlockedDecrementAcquire, LONG, 0, "%ld", 1745L, 1744L, 1744L); + CheckInterlockedOpNoArg(InterlockedDecrementRelease, LONG, 0, "%ld", 1745L, 1744L, 1744L); +#endif #ifdef _M_IX86 - CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", 1745L, 1744L, 1744L); - CheckInterlockedOpNoArg(InterlockedDecrement, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)MAXLONG); - CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock); - CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock); - CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock); - CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive); - CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 0L, -1L, (LONG)ResultNegative); - CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 1L, 0L, (LONG)ResultZero); - CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, "%ld", 2L, 1L, (LONG)ResultPositive); + CheckInterlockedOpNoArg(InterlockedDecrement, LONG, 1, "%ld", 1745L, 1744L, 1744L); + CheckInterlockedOpNoArg(InterlockedDecrement, LONG, 1, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)MAXLONG); + CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, 0, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, 0, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, 0, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock); + CheckInterlockedOpNoArg(ExInterlockedDecrementLong, LONG, 0, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, 0, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, 0, "%ld", 0L, -1L, (LONG)ResultNegative, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, 0, "%ld", 1L, 0L, (LONG)ResultZero, pSpinLock); + CheckInterlockedOpNoArg((ExInterlockedDecrementLong), LONG, 0, "%ld", 2L, 1L, (LONG)ResultPositive, pSpinLock); + CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, 0, "%ld", (LONG)MINLONG, (LONG)MAXLONG, (LONG)ResultPositive); + CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, 0, "%ld", 0L, -1L, (LONG)ResultNegative); + CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, 0, "%ld", 1L, 0L, (LONG)ResultZero); + CheckInterlockedOpNoArg(Exi386InterlockedDecrementLong, LONG, 0, "%ld", 2L, 1L, (LONG)ResultPositive); #endif /* And, Or, Xor */ - CheckInterlockedOp(InterlockedAnd, LONG, "0x%lx", 0x1234L, 0x1111L, 0x1010L, 0x1234L); - CheckInterlockedOp(InterlockedOr, LONG, "0x%lx", 0x1234L, 0x1111L, 0x1335L, 0x1234L); - CheckInterlockedOp(InterlockedXor, LONG, "0x%lx", 0x1234L, 0x1111L, 0x0325L, 0x1234L); + //CheckInterlockedOp(InterlockedAnd, LONG, 0, "0x%lx", 0x1234L, 0x1111L, 0x1010L, 0x1234L); + //CheckInterlockedOp(InterlockedOr, LONG, 0, "0x%lx", 0x1234L, 0x1111L, 0x1335L, 0x1234L); + //CheckInterlockedOp(InterlockedXor, LONG, 0, "0x%lx", 0x1234L, 0x1111L, 0x0325L, 0x1234L); #ifdef _WIN64 - CheckInterlockedOp(InterlockedXor64, LONGLONG, "0x%I64x", 0x200001234LL, 0x100001111LL, 0x300000325LL, 0x200001234LL); + CheckInterlockedOp(InterlockedXor64, LONGLONG, 0, "0x%I64x", 0x200001234LL, 0x100001111LL, 0x300000325LL, 0x200001234LL); #endif } +#define MACRO1(...) PP_NARGS(__VA_ARGS__) +int g1, g2; +void GetCount() +{ + g1 = PP_NARGS(1,2,3,4); + g2 = MACRO1(1,2,3,4, 5); +} + START_TEST(ExInterlocked) { KIRQL Irql; Index: kmtests/ntos_ke/KeSpinLock.c =================================================================== --- kmtests/ntos_ke/KeSpinLock.c (Revision 57099) +++ kmtests/ntos_ke/KeSpinLock.c (Arbeitskopie) @@ -311,7 +311,9 @@ { CheckLock, DISPATCH_LEVEL, AcquireExp, ReleaseExp, NULL, AcquireExpNoRaise, ReleaseExpNoLower, NULL }, /* TODO: this one is just weird! { CheckLock, DISPATCH_LEVEL, AcquireNormal, ReleaseNormal, NULL, AcquireForDpc, ReleaseForDpc, NULL },*/ +#ifdef _M_IX86 { CheckLock, DISPATCH_LEVEL, AcquireNormal, ReleaseNormal, NULL, AcquireInt, ReleaseInt, NULL }, +#endif { CheckLock, SynchIrql, AcquireSynch, ReleaseNormal, NULL, NULL, NULL, NULL }, { CheckQueueHandle, DISPATCH_LEVEL, AcquireInStackQueued, ReleaseInStackQueued, NULL, AcquireInStackNoRaise, ReleaseInStackNoRaise, NULL }, { CheckQueueHandle, SynchIrql, AcquireInStackSynch, ReleaseInStackQueued, NULL, NULL, NULL, NULL },