[CMLIB]
[reactos.git] / rostests / kmtests / ntos_ke / KeMutex.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Mutant/Mutex test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #define ULONGS_PER_POINTER (sizeof(PVOID) / sizeof(ULONG))
11 #define MUTANT_SIZE (2 + 6 * ULONGS_PER_POINTER)
12
13 C_ASSERT(sizeof(DISPATCHER_HEADER) == 8 + 2 * sizeof(PVOID));
14 C_ASSERT(sizeof(KMUTANT) == sizeof(DISPATCHER_HEADER) + 3 * sizeof(PVOID) + sizeof(PVOID));
15 C_ASSERT(sizeof(KMUTANT) == MUTANT_SIZE * sizeof(ULONG));
16
17 #define CheckMutex(Mutex, Held, New, ExpectedApcDisable) do { \
18 PKTHREAD Thread = KeGetCurrentThread(); \
19 ok_eq_uint((Mutex)->Header.Type, MutantObject); \
20 ok_eq_uint((Mutex)->Header.Abandoned, 0x55); \
21 ok_eq_uint((Mutex)->Header.Size, MUTANT_SIZE); \
22 ok_eq_uint((Mutex)->Header.DpcActive, 0x55); \
23 ok_eq_pointer((Mutex)->Header.WaitListHead.Flink, \
24 &(Mutex)->Header.WaitListHead); \
25 ok_eq_pointer((Mutex)->Header.WaitListHead.Blink, \
26 &(Mutex)->Header.WaitListHead); \
27 if (Held) \
28 { \
29 ok_eq_long((Mutex)->Header.SignalState, 0); \
30 ok_eq_pointer((Mutex)->MutantListEntry.Flink, &Thread->MutantListHead); \
31 ok_eq_pointer((Mutex)->MutantListEntry.Blink, &Thread->MutantListHead); \
32 ok_eq_pointer(Thread->MutantListHead.Flink, &(Mutex)->MutantListEntry); \
33 ok_eq_pointer(Thread->MutantListHead.Blink, &(Mutex)->MutantListEntry); \
34 ok_eq_pointer((Mutex)->OwnerThread, Thread); \
35 } \
36 else \
37 { \
38 ok_eq_long((Mutex)->Header.SignalState, 1); \
39 if (New) \
40 { \
41 ok_eq_pointer((Mutex)->MutantListEntry.Flink, \
42 (PVOID)0x5555555555555555ULL); \
43 ok_eq_pointer((Mutex)->MutantListEntry.Blink, \
44 (PVOID)0x5555555555555555ULL); \
45 } \
46 ok_eq_pointer(Thread->MutantListHead.Flink, &Thread->MutantListHead); \
47 ok_eq_pointer(Thread->MutantListHead.Blink, &Thread->MutantListHead); \
48 ok_eq_pointer((Mutex)->OwnerThread, NULL); \
49 } \
50 ok_eq_uint((Mutex)->Abandoned, 0); \
51 ok_eq_uint((Mutex)->ApcDisable, ExpectedApcDisable); \
52 } while (0)
53
54 #define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql) do \
55 { \
56 ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \
57 ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \
58 ok_eq_bool(KeAreAllApcsDisabled(), AllApcsDisabled); \
59 ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \
60 ok_irql(Irql); \
61 } while (0)
62
63 static
64 VOID
65 TestMutant(VOID)
66 {
67 NTSTATUS Status;
68 KMUTANT Mutant;
69 LONG State;
70 PKTHREAD Thread = KeGetCurrentThread();
71
72 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
73 RtlFillMemory(&Mutant, sizeof(Mutant), 0x55);
74 KeInitializeMutant(&Mutant, FALSE);
75 CheckMutex(&Mutant, FALSE, TRUE, 0);
76 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
77
78 RtlFillMemory(&Mutant, sizeof(Mutant), 0x55);
79 KeInitializeMutant(&Mutant, TRUE);
80 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
81 CheckMutex(&Mutant, TRUE, TRUE, 0);
82 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
83 ok_eq_long(State, 0);
84 CheckMutex(&Mutant, FALSE, FALSE, 0);
85 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
86
87 /* Acquire and release */
88 Status = KeWaitForSingleObject(&Mutant,
89 Executive,
90 KernelMode,
91 FALSE,
92 NULL);
93 ok_eq_hex(Status, STATUS_SUCCESS);
94 CheckMutex(&Mutant, TRUE, TRUE, 0);
95 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
96
97 State = KeReleaseMutant(&Mutant, 1, FALSE, FALSE);
98 ok_eq_long(State, 0);
99 CheckMutex(&Mutant, FALSE, FALSE, 0);
100 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
101 }
102
103 static
104 VOID
105 TestMutex(VOID)
106 {
107 NTSTATUS Status;
108 KMUTEX Mutex;
109 LONG State;
110 PKTHREAD Thread = KeGetCurrentThread();
111
112 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
113 RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
114 KeInitializeMutex(&Mutex, 0);
115 CheckMutex(&Mutex, FALSE, TRUE, 1);
116 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
117
118 RtlFillMemory(&Mutex, sizeof(Mutex), 0x55);
119 KeInitializeMutex(&Mutex, 123);
120 CheckMutex(&Mutex, FALSE, TRUE, 1);
121 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
122
123 Status = KeWaitForSingleObject(&Mutex,
124 Executive,
125 KernelMode,
126 FALSE,
127 NULL);
128 ok_eq_hex(Status, STATUS_SUCCESS);
129 CheckMutex(&Mutex, TRUE, FALSE, 1);
130 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
131
132 State = KeReleaseMutex(&Mutex, FALSE);
133 ok_eq_long(State, 0);
134 CheckMutex(&Mutex, FALSE, FALSE, 1);
135 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
136 }
137
138 START_TEST(KeMutex)
139 {
140 TestMutant();
141 TestMutex();
142 }