ReactOS 0.4.16-dev-1537-g4e425b5
XStateSave.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Tests for extended state
5 * COPYRIGHT: Copyright 2025 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8#include "precomp.h"
9#include <windows.h>
10
12
13static
14VOID
16{
17 KAFFINITY OldAffinity, NewAffinity;
18
19 /* Set affinity to the current test processor */
20 NewAffinity = (KAFFINITY)1 << s_ProcessorNumber;
21 OldAffinity = SetThreadAffinityMask(GetCurrentThread(), NewAffinity);
22 ok(OldAffinity != 0, "SetThreadAffinityMask(0x%Ix) failed\n", NewAffinity);
23}
24
25typedef struct _DECLSPEC_INTRIN_TYPE _CRT_ALIGN(16) _M128U64
26{
27 unsigned __int64 u64[2];
29
30typedef struct _DECLSPEC_INTRIN_TYPE _CRT_ALIGN(32) _M256U64
31{
32 unsigned __int64 u64[4];
34
35typedef struct _DECLSPEC_INTRIN_TYPE _CRT_ALIGN(64) _M512U64
36{
37 unsigned __int64 u64[8];
39
40#ifdef _M_IX86
41#define REG_COUNT_SSE 8
42#define REG_COUNT_AVX 8
43#define REG_COUNT_AVX512 8
44#else
45#define REG_COUNT_SSE 16
46#define REG_COUNT_AVX 16
47#define REG_COUNT_AVX512 32
48#endif
49
52
55
58
59BOOL ok_eq_m128i_(M128U64 a, M128U64 b, const char* variable, unsigned int line)
60{
61 BOOL equal = !memcmp(&a, &b, sizeof(M128U64));
62 ok_(__FILE__, line)(equal, "Variable %s Expected %I64x %I64x, got %I64x %I64x\n",
63 variable, b.u64[1], b.u64[0], a.u64[1], a.u64[0]);
64 return TRUE;
65}
66#define ok_eq_m128i(a, b) ok_eq_m128i_(a, b, #a, __LINE__)
67
68BOOL ok_eq_m256i_(M256U64 a, M256U64 b, const char* variable, unsigned int line)
69{
70 BOOL equal = !memcmp(&a, &b, sizeof(M256U64));
71 ok_(__FILE__, line)(equal, "Variable %s Expected %I64x %I64x %I64x %I64x, got %I64x %I64x %I64x %I64x\n",
72 variable, b.u64[3], b.u64[2], b.u64[1], b.u64[0],
73 a.u64[3], a.u64[2], a.u64[1], a.u64[0]);
74 return TRUE;
75}
76#define ok_eq_m256i(a, b) ok_eq_m256i_(a, b, #a, __LINE__)
77
78BOOL ok_eq_m512i_(M512U64 a, M512U64 b, const char* variable, unsigned int line)
79{
80 BOOL equal = !memcmp(&a, &b, sizeof(M512U64));
81 ok_(__FILE__, line)(equal, "Variable %s Expected %I64x %I64x %I64x %I64x %I64x %I64x %I64x %I64x, got %I64x %I64x %I64x %I64x %I64x %I64x %I64x %I64x\n",
83 b.u64[7], b.u64[6], b.u64[5], b.u64[4],
84 b.u64[3], b.u64[2], b.u64[1], b.u64[0],
85 a.u64[7], a.u64[6], a.u64[5], a.u64[4],
86 a.u64[3], a.u64[2], a.u64[1], a.u64[0]);
87 return TRUE;
88}
89#define ok_eq_m512i(a, b) ok_eq_m512i_(a, b, #a, __LINE__)
90
91ULONG g_randomSeed = 0x12345678;
92
94{
96 ULONG High32 = RtlRandom(&g_randomSeed);
97 return ((ULONG64)High32 << 32) | Low32;
98}
99
101{
102 for (ULONG i = 0; i < Count; i++)
103 {
104 Data128[i].u64[0] = GenRandom64();
105 Data128[i].u64[1] = GenRandom64();
106 }
107}
108
110{
111 for (ULONG i = 0; i < Count; i++)
112 {
113 Data256[i].u64[0] = GenRandom64();
114 Data256[i].u64[1] = GenRandom64();
115 Data256[i].u64[2] = GenRandom64();
116 Data256[i].u64[3] = GenRandom64();
117 }
118}
119
121{
122 for (ULONG i = 0; i < Count; i++)
123 {
124 Data512[i].u64[0] = GenRandom64();
125 Data512[i].u64[1] = GenRandom64();
126 Data512[i].u64[2] = GenRandom64();
127 Data512[i].u64[3] = GenRandom64();
128 Data512[i].u64[4] = GenRandom64();
129 Data512[i].u64[5] = GenRandom64();
130 Data512[i].u64[6] = GenRandom64();
131 Data512[i].u64[7] = GenRandom64();
132 }
133}
134
136{
138
139 // Get the current (fresh) state
140 M128U64 SseState[REG_COUNT_SSE] = { 0 };
141 get_SSE_state(SseState);
142
143 // Make sure it's all zero
144 static const M128U64 Zero128 = { 0 };
145 for (ULONG i = 0; i < ARRAYSIZE(SseState); i++)
146 {
147 ok_eq_m128i(SseState[i], Zero128);
148 }
149
150 // Set a new "random" state
151 RandomFill128(SseState, ARRAYSIZE(SseState));
152 set_SSE_state(SseState);
153 return 0;
154}
155
156void Test_SSE(void)
157{
159 {
160 skip("SSE not supported\n");
161 return;
162 }
163
164 // Fill the array with random numbers
165 M128U64 InSseState[REG_COUNT_SSE];
166 RandomFill128(InSseState, ARRAYSIZE(InSseState));
167
169 {
170 // Set the state
171 set_SSE_state(InSseState);
172 }
174 {
175 ok(FALSE, "Failed to set SSE state\n");
176 return;
177 }
178 _SEH2_END;
179
180 // Run a different thread that uses SSE
182 ok(hThread != NULL, "CreateThread failed\n");
183 if (hThread == NULL)
184 {
185 skip("CreateThread failed\n");
186 return;
187 }
188
191
192 // Get the state
193 M128U64 OutSseState[REG_COUNT_SSE] = { 0 };
194 get_SSE_state(OutSseState);
195
196 // Validte the state of the non-volatile registers
197 for (ULONG i = 6; i < REG_COUNT_SSE; i++)
198 {
199 ok_eq_m128i(OutSseState[i], InSseState[i]);
200 }
201}
202
204{
206
207 // Get the current (fresh) state
208 M256U64 AvxState[REG_COUNT_AVX];
209 get_AVX_state(AvxState);
210
211 // Make sure it's all zero
212 static const M256U64 Zero256 = { 0 };
213 for (ULONG i = 0; i < ARRAYSIZE(AvxState); i++)
214 {
215 ok_eq_m256i(AvxState[i], Zero256);
216 }
217
218 // Set a new "random" state
219 RandomFill256(AvxState, ARRAYSIZE(AvxState));
220 set_AVX_state(AvxState);
221 return 0;
222}
223
224void Test_AVX(void)
225{
227 {
228 skip("AVX not supported\n");
229 return;
230 }
231
232 // Fill the array with random numbers
233 M256U64 InAvxState[REG_COUNT_AVX];
234 RandomFill256(InAvxState, ARRAYSIZE(InAvxState));
235
237 {
238 // Set the state
239 set_AVX_state(InAvxState);
240 }
242 {
243 ok(FALSE, "Failed to set AVX state\n");
244 return;
245 }
246 _SEH2_END;
247
248 // Run a different thread that uses AVX
250 ok(hThread != NULL, "CreateThread failed\n");
251 if (hThread == NULL)
252 {
253 skip("CreateThread failed\n");
254 return;
255 }
256
259
260 // Get the state
261 M256U64 OutAvxState[REG_COUNT_AVX] = { 0 };
262 get_AVX_state(OutAvxState);
263
264 // Validte the state of the non-volatile registers
265 for (ULONG i = 6; i < ARRAYSIZE(OutAvxState); i++)
266 {
267 ok_eq_m256i(OutAvxState[i], InAvxState[i]);
268 }
269}
270
272{
274
275 // Get the current (fresh) state
276 M512U64 Avx512State[REG_COUNT_AVX512];
277 get_AVX512_state(Avx512State);
278
279 // Make sure it's all zero
280 static const M512U64 Zero512 = { 0 };
281 for (ULONG i = 0; i < ARRAYSIZE(Avx512State); i++)
282 {
283 ok_eq_m512i(Avx512State[i], Zero512);
284 }
285
286 // Set a new "random" state
287 RandomFill512(Avx512State, ARRAYSIZE(Avx512State));
288 set_AVX512_state(Avx512State);
289 return 0;
290}
291
292void Test_AVX512(void)
293{
295 {
296 skip("AVX512 not supported\n");
297 return;
298 }
299
300 // Fill the array with random numbers
301 M512U64 InAvx512State[REG_COUNT_AVX512];
302 RandomFill512(InAvx512State, ARRAYSIZE(InAvx512State));
303
305 {
306 // Set the state
307 set_AVX512_state(InAvx512State);
308 }
310 {
311 ok(FALSE, "Failed to set AVX512 state\n");
312 return;
313 }
314 _SEH2_END;
315
316 // Run a different thread that uses AVX512
318 ok(hThread != NULL, "CreateThread failed\n");
319 if (hThread == NULL)
320 {
321 skip("CreateThread failed\n");
322 return;
323 }
324
327
328 // Get the state
329 M512U64 OutAvx512State[REG_COUNT_AVX512] = { 0 };
330 get_AVX512_state(OutAvx512State);
331
332 // Validte the state of the non-volatile registers
333 for (ULONG i = 6; i < ARRAYSIZE(OutAvx512State); i++)
334 {
335 ok_eq_m512i(OutAvx512State[i], InAvx512State[i]);
336 }
337}
338
339START_TEST(XStateSave)
340{
342
344
345 for (s_ProcessorNumber = 0;
348 {
350
351 Test_SSE();
352 Test_AVX();
353 Test_AVX512();
354 }
355}
M256U64
Definition: XStateSave.c:33
VOID RandomFill512(M512U64 *Data512, ULONG Count)
Definition: XStateSave.c:120
static ULONG s_ProcessorNumber
Definition: XStateSave.c:11
void __fastcall set_AVX512_state(const M512U64 data[REG_COUNT_AVX512])
void __fastcall get_AVX512_state(M512U64 data[REG_COUNT_AVX512])
static VOID AdjustAffinity(VOID)
Definition: XStateSave.c:15
static DWORD WINAPI Thread_AVX(LPVOID Parameter)
Definition: XStateSave.c:203
M128U64
Definition: XStateSave.c:28
BOOL ok_eq_m256i_(M256U64 a, M256U64 b, const char *variable, unsigned int line)
Definition: XStateSave.c:68
#define ok_eq_m128i(a, b)
Definition: XStateSave.c:66
BOOL ok_eq_m512i_(M512U64 a, M512U64 b, const char *variable, unsigned int line)
Definition: XStateSave.c:78
BOOL ok_eq_m128i_(M128U64 a, M128U64 b, const char *variable, unsigned int line)
Definition: XStateSave.c:59
VOID RandomFill128(M128U64 *Data128, ULONG Count)
Definition: XStateSave.c:100
#define ok_eq_m256i(a, b)
Definition: XStateSave.c:76
#define REG_COUNT_AVX512
Definition: XStateSave.c:47
ULONG g_randomSeed
Definition: XStateSave.c:91
void __fastcall get_AVX_state(M256U64 data[REG_COUNT_AVX])
void Test_AVX(void)
Definition: XStateSave.c:224
void Test_AVX512(void)
Definition: XStateSave.c:292
#define REG_COUNT_SSE
Definition: XStateSave.c:45
void __fastcall set_SSE_state(const M128U64 data[REG_COUNT_SSE])
ULONG64 GenRandom64(VOID)
Definition: XStateSave.c:93
#define REG_COUNT_AVX
Definition: XStateSave.c:46
static DWORD WINAPI Thread_SSE(LPVOID Parameter)
Definition: XStateSave.c:135
VOID RandomFill256(M256U64 *Data256, ULONG Count)
Definition: XStateSave.c:109
void Test_SSE(void)
Definition: XStateSave.c:156
#define ok_eq_m512i(a, b)
Definition: XStateSave.c:89
static DWORD WINAPI Thread_AVX512(LPVOID Parameter)
Definition: XStateSave.c:271
M512U64
Definition: XStateSave.c:38
void __fastcall set_AVX_state(const M256U64 data[REG_COUNT_AVX])
void __fastcall get_SSE_state(M128U64 data[REG_COUNT_SSE])
#define _DECLSPEC_INTRIN_TYPE
Definition: _mingw.h:231
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define __int64
Definition: basetyps.h:16
ULONG64 u64
Definition: btrfs.h:15
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define CloseHandle
Definition: compat.h:739
ULONG_PTR KAFFINITY
Definition: compat.h:85
SYSTEM_INFO sysinfo
Definition: dbghelp.c:76
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
BOOL WINAPI IsProcessorFeaturePresent(IN DWORD ProcessorFeature)
Definition: sysinfo.c:169
DWORD_PTR WINAPI SetThreadAffinityMask(IN HANDLE hThread, IN DWORD_PTR dwThreadAffinityMask)
Definition: thread.c:662
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLenum variable
Definition: glext.h:9031
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
unsigned __int64 ULONG64
Definition: imports.h:198
#define __fastcall
Definition: sync.c:38
NTSYSAPI ULONG NTAPI RtlRandom(_Inout_ PULONG Seed)
HANDLE hThread
Definition: wizard.c:28
int Count
Definition: noreturn.cpp:7
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define equal(x, y)
Definition: reader.cc:56
DWORD dwNumberOfProcessors
Definition: winbase.h:1218
Definition: parser.c:49
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
uint32_t ULONG
Definition: typedefs.h:59
#define _CRT_ALIGN(x)
Definition: corecrt.h:217
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
#define WINAPI
Definition: msvc.h:6
#define PF_XMMI_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:130
#define PF_AVX_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:162
#define PF_AVX512F_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:164
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:336