2 * Synchronization tests
4 * Copyright 2018 Daniel Lehman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
31 #include "wine/test.h"
33 static BOOL (WINAPI
*pWaitOnAddress
)(volatile void *, void *, SIZE_T
, DWORD
);
34 static void (WINAPI
*pWakeByAddressAll
)(void *);
35 static void (WINAPI
*pWakeByAddressSingle
)(void *);
38 static DWORD WINAPI
test_WaitOnAddress_func(void *arg
)
45 while (!(compare
= address
))
47 SetLastError(0xdeadbeef);
48 ret
= pWaitOnAddress(&address
, &compare
, sizeof(compare
), INFINITE
);
49 ok(ret
, "wait failed\n");
50 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS
) /* Win 8 */,
51 "got error %d\n", GetLastError());
53 } while (InterlockedCompareExchange(&address
, compare
- 1, compare
) != compare
);
58 static void test_WaitOnAddress(void)
60 DWORD gle
, val
, nthreads
;
68 win_skip("WaitOnAddress not supported, skipping test\n");
74 if (0) /* crash on Windows */
76 ret
= pWaitOnAddress(&address
, NULL
, 4, 0);
77 ret
= pWaitOnAddress(NULL
, &compare
, 4, 0);
80 /* invalid arguments */
81 SetLastError(0xdeadbeef);
82 pWakeByAddressSingle(NULL
);
84 ok(gle
== 0xdeadbeef, "got %d\n", gle
);
86 SetLastError(0xdeadbeef);
87 pWakeByAddressAll(NULL
);
89 ok(gle
== 0xdeadbeef, "got %d\n", gle
);
91 SetLastError(0xdeadbeef);
92 ret
= pWaitOnAddress(NULL
, NULL
, 0, 0);
94 ok(gle
== ERROR_INVALID_PARAMETER
, "got %d\n", gle
);
95 ok(!ret
, "got %d\n", ret
);
99 SetLastError(0xdeadbeef);
100 ret
= pWaitOnAddress(&address
, &compare
, 5, 0);
101 gle
= GetLastError();
102 ok(gle
== ERROR_INVALID_PARAMETER
, "got %d\n", gle
);
103 ok(!ret
, "got %d\n", ret
);
104 ok(address
== 0, "got %s\n", wine_dbgstr_longlong(address
));
105 ok(compare
== 0, "got %s\n", wine_dbgstr_longlong(compare
));
109 SetLastError(0xdeadbeef);
110 pWakeByAddressSingle(&address
);
111 gle
= GetLastError();
112 ok(gle
== 0xdeadbeef, "got %d\n", gle
);
113 ok(address
== 0, "got %s\n", wine_dbgstr_longlong(address
));
115 SetLastError(0xdeadbeef);
116 pWakeByAddressAll(&address
);
117 gle
= GetLastError();
118 ok(gle
== 0xdeadbeef, "got %d\n", gle
);
119 ok(address
== 0, "got %s\n", wine_dbgstr_longlong(address
));
121 /* different address size */
124 SetLastError(0xdeadbeef);
125 ret
= pWaitOnAddress(&address
, &compare
, 2, 0);
126 gle
= GetLastError();
127 ok(gle
== 0xdeadbeef || broken(gle
== ERROR_SUCCESS
) /* Win 8 */, "got %d\n", gle
);
128 ok(ret
, "got %d\n", ret
);
130 SetLastError(0xdeadbeef);
131 ret
= pWaitOnAddress(&address
, &compare
, 1, 0);
132 gle
= GetLastError();
133 ok(gle
== ERROR_TIMEOUT
, "got %d\n", gle
);
134 ok(!ret
, "got %d\n", ret
);
136 /* simple wait case */
139 SetLastError(0xdeadbeef);
140 ret
= pWaitOnAddress(&address
, &compare
, 4, 0);
141 gle
= GetLastError();
142 ok(gle
== 0xdeadbeef || broken(gle
== ERROR_SUCCESS
) /* Win 8 */, "got %d\n", gle
);
143 ok(ret
, "got %d\n", ret
);
145 /* WakeByAddressAll */
147 for (i
= 0; i
< ARRAY_SIZE(threads
); i
++)
148 threads
[i
] = CreateThread(NULL
, 0, test_WaitOnAddress_func
, NULL
, 0, NULL
);
151 address
= ARRAY_SIZE(threads
);
152 pWakeByAddressAll(&address
);
153 val
= WaitForMultipleObjects(ARRAY_SIZE(threads
), threads
, TRUE
, 5000);
154 ok(val
== WAIT_OBJECT_0
, "got %d\n", val
);
155 for (i
= 0; i
< ARRAY_SIZE(threads
); i
++)
156 CloseHandle(threads
[i
]);
157 ok(!address
, "got unexpected value %s\n", wine_dbgstr_longlong(address
));
159 /* WakeByAddressSingle */
161 for (i
= 0; i
< ARRAY_SIZE(threads
); i
++)
162 threads
[i
] = CreateThread(NULL
, 0, test_WaitOnAddress_func
, NULL
, 0, NULL
);
165 nthreads
= ARRAY_SIZE(threads
);
166 address
= ARRAY_SIZE(threads
);
169 pWakeByAddressSingle(&address
);
170 val
= WaitForMultipleObjects(nthreads
, threads
, FALSE
, 2000);
171 ok(val
< WAIT_OBJECT_0
+ nthreads
, "got %u\n", val
);
172 CloseHandle(threads
[val
]);
173 memmove(&threads
[val
], &threads
[val
+1], (nthreads
- val
- 1) * sizeof(threads
[0]));
176 ok(!address
, "got unexpected value %s\n", wine_dbgstr_longlong(address
));
179 static void test_Sleep(void)
181 LARGE_INTEGER frequency
;
182 LARGE_INTEGER t1
, t2
;
183 double elapsed_time
, min
, max
;
189 ret
= QueryPerformanceFrequency(&frequency
);
190 ok(ret
, "QueryPerformanceFrequency failed\n");
192 ret
= QueryPerformanceCounter(&t1
);
193 ok(ret
, "QueryPerformanceCounter failed\n");
195 /* Get the timer resolution before... */
197 status
= NtQueryTimerResolution(&dummy
, &dummy
, &r1
);
198 ok(status
== STATUS_SUCCESS
, "NtQueryTimerResolution() failed (%x)\n", status
);
200 for (i
= 0; i
< 50; i
++) {
204 ret
= QueryPerformanceCounter(&t2
);
205 ok(ret
, "QueryPerformanceCounter failed\n");
207 /* ...and after in case some other process changes it during this test */
209 status
= NtQueryTimerResolution(&dummy
, &dummy
, &r2
);
210 ok(status
== STATUS_SUCCESS
, "NtQueryTimerResolution() failed (%x)\n", status
);
212 elapsed_time
= (t2
.QuadPart
- t1
.QuadPart
) / (double)frequency
.QuadPart
;
213 min
= 50.0 * (r1
< r2
? r1
: r2
) / 10000000.0;
214 max
= 50.0 * (r1
< r2
? r2
: r1
) / 10000000.0;
216 /* Add an extra 1s to account for potential scheduling delays */
217 ok(0.9 * min
<= elapsed_time
&& elapsed_time
<= 1.0 + max
,
218 "got %f, expected between %f and %f\n", elapsed_time
, min
, max
);
225 hmod
= LoadLibraryA("kernel32.dll");
226 pWaitOnAddress
= (void *)GetProcAddress(hmod
, "WaitOnAddress");
227 ok(!pWaitOnAddress
, "expected only in kernelbase.dll\n");
229 hmod
= LoadLibraryA("kernelbase.dll");
230 pWaitOnAddress
= (void *)GetProcAddress(hmod
, "WaitOnAddress");
231 pWakeByAddressAll
= (void *)GetProcAddress(hmod
, "WakeByAddressAll");
232 pWakeByAddressSingle
= (void *)GetProcAddress(hmod
, "WakeByAddressSingle");
234 test_WaitOnAddress();