ReactOS 0.4.15-dev-7918-g2a2556c
RtlCriticalSection.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Test for Rtl Critical Section API
5 * COPYRIGHT: Copyright 2023 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8#include "precomp.h"
9#include <pseh/pseh2.h>
10
15
16typedef
21 _In_ ULONG SpinCount,
23
28
29static
30void
32{
34 BOOL HasDebugInfo = (g_Version <= _WIN32_WINNT_VISTA);
35
37 {
40 }
42 {
44 }
47
55 if (HasDebugInfo)
56 {
57 ok(CritSect.DebugInfo != NULL, "DebugInfo is %p\n", CritSect.DebugInfo);
58 ok(CritSect.DebugInfo != LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
59 }
60 else
61 {
62 ok(CritSect.DebugInfo == LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
63 }
64
72 if (HasDebugInfo)
73 {
74 ok(CritSect.DebugInfo != NULL, "DebugInfo is %p\n", CritSect.DebugInfo);
75 ok(CritSect.DebugInfo != LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
76 }
77 else
78 {
79 ok(CritSect.DebugInfo == LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
80 }
81
85
89
91 {
93 {
96 }
98 {
100 }
101 _SEH2_END;
103
111 if (HasDebugInfo)
112 {
113 ok(CritSect.DebugInfo != NULL, "DebugInfo is %p\n", CritSect.DebugInfo);
114 ok(CritSect.DebugInfo != LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
115 if ((CritSect.DebugInfo != NULL) && (CritSect.DebugInfo != LongToPtr(-1)))
116 {
121 ok(CritSect.DebugInfo->ProcessLocksList.Flink != NULL, "Flink is NULL\n");
122 ok(CritSect.DebugInfo->ProcessLocksList.Blink != NULL, "Blink is NULL\n");
125 {
130 }
135 }
136 }
137 else
138 {
139 ok(CritSect.DebugInfo == LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
140 }
141
144
147
150
152 {
154 }
156 {
158 }
159 _SEH2_END;
161
162 for (ULONG i = 0; i < 32; i++)
163 {
164 ULONG Flags = 1UL << i;
165 ULONG AllowedFlags = 0x07FFFFFF;
166 if (g_Version >= _WIN32_WINNT_WIN7) AllowedFlags |= 0x18000000;
167 NTSTATUS ExpectedStatus = (Flags & ~AllowedFlags) ?
170 ok(Status == ExpectedStatus, "Wrong Status (0x%lx) for Flags 0x%lx\n",
171 Status, Flags);
172 if (NT_SUCCESS(Status))
173 {
174 ULONG SetFlags = Flags & 0x08000000;
175 if (g_Version >= _WIN32_WINNT_WIN7) SetFlags |= (Flags & 0x03000000);
177 }
178 }
179
183 {
185 }
187 {
189 }
190 _SEH2_END;
192
193 Status = pfnRtlInitializeCriticalSectionEx(&CritSect, 0x12345678, 0xFFFFFFFF);
195
198 {
200 ok(CritSect.DebugInfo != NULL, "DebugInfo is %p\n", CritSect.DebugInfo);
201 ok(CritSect.DebugInfo != LongToPtr(-1), "DebugInfo is %p\n", CritSect.DebugInfo);
202 if ((CritSect.DebugInfo != NULL) && (CritSect.DebugInfo != LongToPtr(-1)))
203 {
208 ok(CritSect.DebugInfo->ProcessLocksList.Flink != NULL, "Flink is NULL\n");
209 ok(CritSect.DebugInfo->ProcessLocksList.Blink != NULL, "Blink is NULL\n");
212 {
217 }
222 }
223 }
224 else
225 {
227 }
228 }
229 else
230 {
231 skip("RtlInitializeCriticalSectionEx not available.\n");
232 }
233}
234
235static
236DWORD
237WINAPI
239 _In_ LPVOID lpParameter)
240{
241 printf("ThreadProc1 starting\n");
243
245
246 printf("ThreadProc1 waiting\n");
248 printf("ThreadProc1 returned from wait\n");
249
251
252 return 0;
253}
254
255static
256DWORD
257WINAPI
259 _In_ LPVOID lpParameter)
260{
261 printf("ThreadProc2 starting\n");
263
265
266 printf("ThreadProc2 waiting\n");
268 printf("ThreadProc2 returned from wait\n");
269
271
272 return 0;
273}
274
275static
276void
278{
279 DWORD dwThreadId1, dwThreadId2;
281
283
284 // Acquire once
291
292 // Acquire recursively
299
304
305 // Create thread 1 and wait to it time to try to acquire the critical section
306 hThread1 = CreateThread(NULL, 0, ThreadProc1, NULL, 0, &dwThreadId1);
307
308 // Wait up to 10 s
309 for (ULONG i = 0; (CritSect.LockCount == -2) && (i < 1000); i++)
310 {
311 Sleep(10);
312 }
313
317 //ok_ptr(CritSect.LockSemaphore, LongToPtr(-1)); // TODO: this behaves differently on different OS versions
319
320 // Create thread 2 and wait to it time to try to acquire the critical section
321 hThread2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &dwThreadId2);
322
323 // Wait up to 10 s
324 for (ULONG i = 0; (CritSect.LockCount == -6) && (i < 1000); i++)
325 {
326 Sleep(10);
327 }
328
332 //ok_ptr(CritSect.LockSemaphore, LongToPtr(-1));
334
339
340 // Wait until thread 1 has acquired the critical section
342
346 //ok_ptr(CritSect.LockSemaphore, LongToPtr(-1));
347 if (g_DefaultSpinCount != 0)
348 {
349 ok(CritSect.SpinCount <= g_DefaultSpinCount, "SpinCount increased\n");
350 }
351 else
352 {
354 }
355
357
358 // Release thread 1, wait for thread 2 to acquire the critical section
361
365 //ok_ptr(CritSect.LockSemaphore, LongToPtr(-1));
366 if (g_DefaultSpinCount != 0)
367 {
368 ok(CritSect.SpinCount <= g_DefaultSpinCount, "SpinCount increased\n");
369 }
370 else
371 {
373 }
374
375 // Release thread 2
377
378 // To make Thomas happy :)
381}
382
383START_TEST(RtlCriticalSection)
384{
385 HMODULE hmodNtDll = GetModuleHandleA("ntdll.dll");
387 GetProcAddress(hmodNtDll, "RtlInitializeCriticalSectionEx");
388
392 printf("g_VerInfo: %lu.%lu.%lu ('%s')\n ",
398 printf("g_SysInfo.dwNumberOfProcessors = %lu\n", g_SysInfo.dwNumberOfProcessors);
399
401 {
402 g_DefaultSpinCount = 0x20007d0;
403 }
404 else
405 {
407 }
408
409 Test_Init();
410 Test_Acquire();
411}
FN_RtlInitializeCriticalSectionEx * pfnRtlInitializeCriticalSectionEx
HANDLE hEventThread1Ready
RTL_CRITICAL_SECTION CritSect
HANDLE hEventThread2Ready
static DWORD WINAPI ThreadProc1(_In_ LPVOID lpParameter)
static void Test_Acquire(void)
static DWORD WINAPI ThreadProc2(_In_ LPVOID lpParameter)
NTSTATUS NTAPI FN_RtlInitializeCriticalSectionEx(_Out_ PRTL_CRITICAL_SECTION CriticalSection, _In_ ULONG SpinCount, _In_ ULONG Flags)
SYSTEM_INFO g_SysInfo
static void Test_Init(void)
HANDLE hEventThread2Cont
OSVERSIONINFOEXA g_VerInfo
ULONG g_Version
HANDLE hEventThread1Cont
ULONG g_DefaultSpinCount
static HANDLE hThread2
static HANDLE hThread1
#define ok_ntstatus(status, expected)
Definition: atltest.h:135
#define ok_long(expression, result)
Definition: atltest.h:133
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define ok_size_t(expression, result)
Definition: atltest.h:115
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
#define ok_ptr(expression, result)
Definition: atltest.h:108
LONG NTSTATUS
Definition: precomp.h:26
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define LongToPtr(l)
Definition: basetsd.h:91
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
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
BOOL WINAPI GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation)
Definition: version.c:69
#define INFINITE
Definition: serial.h:102
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define printf
Definition: freeldr.h:93
Status
Definition: gdiplustypes.h:25
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:85
CRITICAL_SECTION CriticalSection
Definition: iprtprio.c:40
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSectionAndSpinCount(_In_ PRTL_CRITICAL_SECTION CriticalSection, _In_ ULONG SpinCount)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG dwMajorVersion
Definition: rtltypes.h:256
ULONG dwMinorVersion
Definition: rtltypes.h:257
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:255
ULONG dwBuildNumber
Definition: rtltypes.h:258
CHAR szCSDVersion[128]
Definition: rtltypes.h:260
struct _RTL_CRITICAL_SECTION * CriticalSection
Definition: rtltypes.h:1422
PRTL_CRITICAL_SECTION_DEBUG DebugInfo
Definition: rtltypes.h:1431
DWORD dwNumberOfProcessors
Definition: winbase.h:1177
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define CreateEvent
Definition: winbase.h:3748
#define WINAPI
Definition: msvc.h:6
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1089
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170