cmd: DIR command outputs free space for the path.
[wine.git] / dlls / msvcp140_atomic_wait / tests / msvcp140_atomic_wait.c
blobc10217cf34f5ef80be4351c396a81c8e2c84e8f2
1 /*
2 * Copyright 2022 Daniel Lehman
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdio.h>
20 #include <process.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wine/test.h"
26 static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void);
28 static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t);
29 static void (__stdcall *p___std_close_threadpool_work)(PTP_WORK);
30 static PTP_WORK (__stdcall *p___std_create_threadpool_work)(PTP_WORK_CALLBACK, void*, PTP_CALLBACK_ENVIRON);
31 static void (__stdcall *p___std_submit_threadpool_work)(PTP_WORK);
32 static void (__stdcall *p___std_wait_for_threadpool_work_callbacks)(PTP_WORK, BOOL);
33 static BOOL (__stdcall *p___std_atomic_wait_direct)(volatile void*, void*, size_t, DWORD);
34 static void (__stdcall *p___std_atomic_notify_one_direct)(void*);
36 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
37 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
38 static HMODULE init(void)
40 HMODULE msvcp;
42 if (!(msvcp = LoadLibraryA("msvcp140_atomic_wait.dll")))
43 return NULL;
45 SET(p___std_parallel_algorithms_hw_threads, "__std_parallel_algorithms_hw_threads");
47 SET(p___std_bulk_submit_threadpool_work, "__std_bulk_submit_threadpool_work");
48 SET(p___std_close_threadpool_work, "__std_close_threadpool_work");
49 SET(p___std_create_threadpool_work, "__std_create_threadpool_work");
50 SET(p___std_submit_threadpool_work, "__std_submit_threadpool_work");
51 SET(p___std_wait_for_threadpool_work_callbacks, "__std_wait_for_threadpool_work_callbacks");
52 SET(p___std_atomic_wait_direct, "__std_atomic_wait_direct");
53 SET(p___std_atomic_notify_one_direct, "__std_atomic_notify_one_direct");
54 return msvcp;
57 static void test___std_parallel_algorithms_hw_threads(void)
59 SYSTEM_INFO si;
60 unsigned int nthr;
62 GetSystemInfo(&si);
63 nthr = p___std_parallel_algorithms_hw_threads();
64 ok(nthr == si.dwNumberOfProcessors, "expected %lu, got %u\n", si.dwNumberOfProcessors, nthr);
67 static PTP_WORK cb_work;
68 static void *cb_context;
69 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
70 LONG *workcalled = context;
71 cb_work = work;
72 cb_context = context;
74 InterlockedIncrement(workcalled);
77 static HANDLE cb_event;
78 static void CALLBACK threadpool_workfinalization(TP_CALLBACK_INSTANCE *instance, void *context)
80 LONG *workcalled = context;
82 InterlockedIncrement(workcalled);
83 SetEvent(cb_event);
86 static void test_threadpool_work(void)
88 PTP_WORK work;
89 DWORD gle, ret;
90 LONG workcalled;
91 TP_CALLBACK_ENVIRON environment;
92 TP_CALLBACK_ENVIRON_V3 environment3;
94 if (0) /* crash on windows */
96 p___std_bulk_submit_threadpool_work(NULL, 5);
97 p___std_create_threadpool_work(NULL, NULL, NULL);
98 p___std_submit_threadpool_work(NULL);
99 p___std_wait_for_threadpool_work_callbacks(NULL, FALSE);
100 p___std_close_threadpool_work(NULL);
103 /* simple test */
104 workcalled = 0;
105 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled, NULL);
106 ok(!!work, "failed to create threadpool_work\n");
107 p___std_submit_threadpool_work(work);
108 p___std_wait_for_threadpool_work_callbacks(work, FALSE);
109 p___std_close_threadpool_work(work);
110 ok(workcalled == 1, "expected work to be called once, got %ld\n", workcalled);
111 ok(cb_work == work, "expected %p, got %p\n", work, cb_work);
112 ok(cb_context == &workcalled, "expected %p, got %p\n", &workcalled, cb_context);
114 /* bulk submit */
115 workcalled = 0;
116 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled, NULL);
117 ok(!!work, "failed to create threadpool_work\n");
118 p___std_bulk_submit_threadpool_work(work, 13);
119 p___std_wait_for_threadpool_work_callbacks(work, FALSE);
120 p___std_close_threadpool_work(work);
121 ok(workcalled == 13, "expected work to be called 13 times, got %ld\n", workcalled);
123 workcalled = 0;
124 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled, NULL);
125 ok(!!work, "failed to create threadpool_work\n");
126 p___std_bulk_submit_threadpool_work(work, 0);
127 p___std_wait_for_threadpool_work_callbacks(work, FALSE);
128 p___std_close_threadpool_work(work);
129 ok(workcalled == 0, "expected no work, got %ld\n", workcalled);
131 /* test with environment */
132 cb_event = CreateEventW(NULL, TRUE, FALSE, NULL);
133 memset(&environment, 0, sizeof(environment));
134 environment.Version = 1;
135 environment.FinalizationCallback = threadpool_workfinalization;
136 workcalled = 0;
137 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled, &environment);
138 ok(!!work, "failed to create threadpool_work\n");
139 p___std_submit_threadpool_work(work);
140 p___std_wait_for_threadpool_work_callbacks(work, FALSE);
141 p___std_close_threadpool_work(work);
142 ret = WaitForSingleObject(cb_event, 1000);
143 ok(ret == WAIT_OBJECT_0, "expected finalization callback to be called\n");
144 ok(workcalled == 2, "expected work to be called twice, got %ld\n", workcalled);
145 CloseHandle(cb_event);
147 /* test with environment version 3 */
148 memset(&environment3, 0, sizeof(environment3));
149 environment3.Version = 3;
150 environment3.CallbackPriority = TP_CALLBACK_PRIORITY_NORMAL;
151 SetLastError(0xdeadbeef);
152 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled,
153 (TP_CALLBACK_ENVIRON *)&environment3);
154 gle = GetLastError();
155 ok(gle == 0xdeadbeef, "expected 0xdeadbeef, got %lx\n", gle);
156 ok(!!work, "failed to create threadpool_work\n");
157 p___std_close_threadpool_work(work);
159 memset(&environment3, 0, sizeof(environment3));
160 environment3.Version = 3;
161 environment3.CallbackPriority = TP_CALLBACK_PRIORITY_INVALID;
162 SetLastError(0xdeadbeef);
163 work = p___std_create_threadpool_work(threadpool_workcallback, &workcalled,
164 (TP_CALLBACK_ENVIRON *)&environment3);
165 gle = GetLastError();
166 ok(gle == ERROR_INVALID_PARAMETER, "expected %d, got %ld\n", ERROR_INVALID_PARAMETER, gle);
167 ok(!work, "expected failure\n");
170 LONG64 address;
171 static void __cdecl atomic_wait_thread(void *arg)
173 LONG64 compare = 0;
174 int r;
176 r = p___std_atomic_wait_direct(&address, &compare, sizeof(address), 2000);
177 ok(r == 1, "r = %d\n", r);
180 static void test___std_atomic_wait_direct(void)
182 LONG64 compare;
183 HANDLE thread;
184 DWORD gle;
185 int r;
187 if (!GetProcAddress(GetModuleHandleA("kernelbase"), "WaitOnAddress"))
189 win_skip("WaitOnAddress not available\n");
190 return;
193 address = compare = 0;
194 SetLastError(0);
195 r = p___std_atomic_wait_direct(&address, &compare, 5, 0);
196 ok(!r, "r = %d\n", r);
197 gle = GetLastError();
198 ok(gle == ERROR_INVALID_PARAMETER, "expected %d, got %ld\n", ERROR_INVALID_PARAMETER, gle);
200 SetLastError(0);
201 r = p___std_atomic_wait_direct(&address, &compare, 1, 0);
202 ok(!r, "r = %d\n", r);
203 gle = GetLastError();
204 ok(gle == ERROR_TIMEOUT, "expected %d, got %ld\n", ERROR_TIMEOUT, gle);
205 r = p___std_atomic_wait_direct(&address, &compare, 2, 0);
206 ok(!r, "r = %d\n", r);
207 gle = GetLastError();
208 ok(gle == ERROR_TIMEOUT, "expected %d, got %ld\n", ERROR_TIMEOUT, gle);
209 r = p___std_atomic_wait_direct(&address, &compare, 4, 0);
210 ok(!r, "r = %d\n", r);
211 gle = GetLastError();
212 ok(gle == ERROR_TIMEOUT, "expected %d, got %ld\n", ERROR_TIMEOUT, gle);
213 r = p___std_atomic_wait_direct(&address, &compare, 8, 0);
214 ok(!r, "r = %d\n", r);
215 gle = GetLastError();
216 ok(gle == ERROR_TIMEOUT, "expected %d, got %ld\n", ERROR_TIMEOUT, gle);
218 SetLastError(0);
219 r = p___std_atomic_wait_direct(&address, &compare, 8, 1);
220 ok(!r, "r = %d\n", r);
221 gle = GetLastError();
222 ok(gle == ERROR_TIMEOUT, "expected %d, got %ld\n", ERROR_TIMEOUT, gle);
224 compare = 1;
225 SetLastError(0);
226 r = p___std_atomic_wait_direct(&address, &compare, 8, 0);
227 ok(r == 1, "r = %d\n", r);
228 gle = GetLastError();
229 ok(!gle, "expected 0, got %ld\n", gle);
231 thread = (HANDLE)_beginthread(atomic_wait_thread, 0, NULL);
232 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed\n");
233 Sleep(100);
234 address = 1;
235 p___std_atomic_notify_one_direct(&address);
236 WaitForSingleObject(thread, INFINITE);
237 CloseHandle(thread);
240 START_TEST(msvcp140_atomic_wait)
242 HMODULE msvcp;
243 if (!(msvcp = init()))
245 win_skip("msvcp140_atomic_wait.dll not installed\n");
246 return;
248 test___std_parallel_algorithms_hw_threads();
249 test_threadpool_work();
250 test___std_atomic_wait_direct();
251 FreeLibrary(msvcp);