TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / vcomp / tests / vcomp.c
blob4f030d3eedce1dfd589c1a513832c4bc557c4fcd
1 /*
2 * Unit test suite for vcomp
4 * Copyright 2012 Dan Kegel
5 * Copyright 2015 Sebastian Lackner
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
24 static char vcomp_manifest_file[MAX_PATH];
25 static HANDLE vcomp_actctx_hctx;
26 static ULONG_PTR vcomp_actctx_cookie;
27 static HMODULE vcomp_handle;
29 static HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*);
30 static BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*);
31 static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
32 static VOID (WINAPI *pReleaseActCtx)(HANDLE);
34 typedef CRITICAL_SECTION *omp_lock_t;
35 typedef CRITICAL_SECTION *omp_nest_lock_t;
37 static void (CDECL *p_vcomp_atomic_add_i4)(int *dest, int val);
38 static void (CDECL *p_vcomp_atomic_add_r4)(float *dest, float val);
39 static void (CDECL *p_vcomp_atomic_add_r8)(double *dest, double val);
40 static void (CDECL *p_vcomp_atomic_and_i4)(int *dest, int val);
41 static void (CDECL *p_vcomp_atomic_div_i4)(int *dest, int val);
42 static void (CDECL *p_vcomp_atomic_div_r4)(float *dest, float val);
43 static void (CDECL *p_vcomp_atomic_div_r8)(double *dest, double val);
44 static void (CDECL *p_vcomp_atomic_div_ui4)(unsigned int *dest, unsigned int val);
45 static void (CDECL *p_vcomp_atomic_mul_i4)(int *dest, int val);
46 static void (CDECL *p_vcomp_atomic_mul_r4)(float *dest, float val);
47 static void (CDECL *p_vcomp_atomic_mul_r8)(double *dest, double val);
48 static void (CDECL *p_vcomp_atomic_or_i4)(int *dest, int val);
49 static void (CDECL *p_vcomp_atomic_shl_i4)(int *dest, int val);
50 static void (CDECL *p_vcomp_atomic_shr_i4)(int *dest, int val);
51 static void (CDECL *p_vcomp_atomic_shr_ui4)(unsigned int *dest, unsigned int val);
52 static void (CDECL *p_vcomp_atomic_sub_i4)(int *dest, int val);
53 static void (CDECL *p_vcomp_atomic_sub_r4)(float *dest, float val);
54 static void (CDECL *p_vcomp_atomic_sub_r8)(double *dest, double val);
55 static void (CDECL *p_vcomp_atomic_xor_i4)(int *dest, int val);
56 static void (CDECL *p_vcomp_barrier)(void);
57 static void (CDECL *p_vcomp_enter_critsect)(CRITICAL_SECTION **critsect);
58 static void (CDECL *p_vcomp_flush)(void);
59 static void (CDECL *p_vcomp_for_dynamic_init)(unsigned int flags, unsigned int first, unsigned int last,
60 int step, unsigned int chunksize);
61 static int (CDECL *p_vcomp_for_dynamic_next)(unsigned int *begin, unsigned int *end);
62 static void (CDECL *p_vcomp_for_static_end)(void);
63 static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
64 int *begin, int *end, int *next, int *lastchunk);
65 static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
66 BOOL increment, unsigned int *begin, unsigned int *end);
67 static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
68 static int (CDECL *p_vcomp_get_thread_num)(void);
69 static void (CDECL *p_vcomp_leave_critsect)(CRITICAL_SECTION *critsect);
70 static int (CDECL *p_vcomp_master_begin)(void);
71 static void (CDECL *p_vcomp_master_end)(void);
72 static void (CDECL *p_vcomp_sections_init)(int n);
73 static int (CDECL *p_vcomp_sections_next)(void);
74 static void (CDECL *p_vcomp_set_num_threads)(int num_threads);
75 static int (CDECL *p_vcomp_single_begin)(int flags);
76 static void (CDECL *p_vcomp_single_end)(void);
77 static void (CDECL *pomp_destroy_lock)(omp_lock_t *lock);
78 static void (CDECL *pomp_destroy_nest_lock)(omp_nest_lock_t *lock);
79 static int (CDECL *pomp_get_max_threads)(void);
80 static int (CDECL *pomp_get_nested)(void);
81 static int (CDECL *pomp_get_num_threads)(void);
82 static int (CDECL *pomp_get_thread_num)(void);
83 static int (CDECL *pomp_in_parallel)(void);
84 static void (CDECL *pomp_init_lock)(omp_lock_t *lock);
85 static void (CDECL *pomp_init_nest_lock)(omp_nest_lock_t *lock);
86 static void (CDECL *pomp_set_lock)(omp_lock_t *lock);
87 static void (CDECL *pomp_set_nest_lock)(omp_nest_lock_t *lock);
88 static void (CDECL *pomp_set_nested)(int nested);
89 static void (CDECL *pomp_set_num_threads)(int num_threads);
90 static int (CDECL *pomp_test_lock)(omp_lock_t *lock);
91 static int (CDECL *pomp_test_nest_lock)(omp_nest_lock_t *lock);
92 static void (CDECL *pomp_unset_lock)(omp_lock_t *lock);
93 static void (CDECL *pomp_unset_nest_lock)(omp_nest_lock_t *lock);
95 #define VCOMP_DYNAMIC_FLAGS_STATIC 0x01
96 #define VCOMP_DYNAMIC_FLAGS_CHUNKED 0x02
97 #define VCOMP_DYNAMIC_FLAGS_GUIDED 0x03
98 #define VCOMP_DYNAMIC_FLAGS_INCREMENT 0x40
100 #ifdef __i386__
101 #define ARCH "x86"
102 #elif defined(__x86_64__)
103 #define ARCH "amd64"
104 #elif defined __arm__
105 #define ARCH "arm"
106 #elif defined __aarch64__
107 #define ARCH "arm64"
108 #else
109 #define ARCH "none"
110 #endif
112 static const char vcomp_manifest[] =
113 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
114 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
115 " <assemblyIdentity\n"
116 " type=\"win32\"\n"
117 " name=\"Wine.vcomp.Test\"\n"
118 " version=\"1.0.0.0\"\n"
119 " processorArchitecture=\"" ARCH "\"\n"
120 " />\n"
121 "<description>Wine vcomp test suite</description>\n"
122 "<dependency>\n"
123 " <dependentAssembly>\n"
124 " <assemblyIdentity\n"
125 " type=\"win32\"\n"
126 " name=\"Microsoft.VC80.OpenMP\"\n"
127 " version=\"8.0.50608.0\"\n"
128 " processorArchitecture=\"" ARCH "\"\n"
129 " publicKeyToken=\"1fc8b3b9a1e18e3b\"\n"
130 " />\n"
131 " </dependentAssembly>\n"
132 "</dependency>\n"
133 "</assembly>\n";
135 #undef ARCH
137 static void create_vcomp_manifest(void)
139 char temp_path[MAX_PATH];
140 HMODULE kernel32;
141 DWORD written;
142 ACTCTXA ctx;
143 HANDLE file;
145 kernel32 = GetModuleHandleA("kernel32.dll");
146 pCreateActCtxA = (void *)GetProcAddress(kernel32, "CreateActCtxA");
147 pActivateActCtx = (void *)GetProcAddress(kernel32, "ActivateActCtx");
148 pDeactivateActCtx = (void *)GetProcAddress(kernel32, "DeactivateActCtx");
149 pReleaseActCtx = (void *)GetProcAddress(kernel32, "ReleaseActCtx");
150 if (!pCreateActCtxA) return;
152 if (!GetTempPathA(sizeof(temp_path), temp_path) ||
153 !GetTempFileNameA(temp_path, "vcomp", 0, vcomp_manifest_file))
155 ok(0, "failed to create manifest file\n");
156 return;
159 file = CreateFileA(vcomp_manifest_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
160 if (file == INVALID_HANDLE_VALUE)
162 ok(0, "failed to open manifest file\n");
163 return;
166 if (!WriteFile(file, vcomp_manifest, sizeof(vcomp_manifest) - 1, &written, NULL))
167 written = 0;
168 CloseHandle(file);
170 if (written != sizeof(vcomp_manifest) - 1)
172 ok(0, "failed to write manifest file\n");
173 DeleteFileA(vcomp_manifest_file);
174 return;
177 memset(&ctx, 0, sizeof(ctx));
178 ctx.cbSize = sizeof(ctx);
179 ctx.lpSource = vcomp_manifest_file;
180 vcomp_actctx_hctx = pCreateActCtxA(&ctx);
181 if (!vcomp_actctx_hctx)
183 ok(0, "failed to create activation context\n");
184 DeleteFileA(vcomp_manifest_file);
185 return;
188 if (!pActivateActCtx(vcomp_actctx_hctx, &vcomp_actctx_cookie))
190 win_skip("failed to activate context\n");
191 pReleaseActCtx(vcomp_actctx_hctx);
192 DeleteFileA(vcomp_manifest_file);
193 vcomp_actctx_hctx = NULL;
197 static void release_vcomp(void)
199 if (vcomp_handle)
200 FreeLibrary(vcomp_handle);
202 if (vcomp_actctx_hctx)
204 pDeactivateActCtx(0, vcomp_actctx_cookie);
205 pReleaseActCtx(vcomp_actctx_hctx);
206 DeleteFileA(vcomp_manifest_file);
210 #define VCOMP_GET_PROC(func) \
211 do \
213 p ## func = (void *)GetProcAddress(vcomp_handle, #func); \
214 if (!p ## func) trace("Failed to get address for %s\n", #func); \
216 while (0)
218 static BOOL init_vcomp(void)
220 create_vcomp_manifest();
222 vcomp_handle = LoadLibraryA("vcomp.dll");
223 if (!vcomp_handle)
225 win_skip("vcomp.dll not installed\n");
226 release_vcomp();
227 return FALSE;
230 VCOMP_GET_PROC(_vcomp_atomic_add_i4);
231 VCOMP_GET_PROC(_vcomp_atomic_add_r4);
232 VCOMP_GET_PROC(_vcomp_atomic_add_r8);
233 VCOMP_GET_PROC(_vcomp_atomic_and_i4);
234 VCOMP_GET_PROC(_vcomp_atomic_div_i4);
235 VCOMP_GET_PROC(_vcomp_atomic_div_r4);
236 VCOMP_GET_PROC(_vcomp_atomic_div_r8);
237 VCOMP_GET_PROC(_vcomp_atomic_div_ui4);
238 VCOMP_GET_PROC(_vcomp_atomic_mul_i4);
239 VCOMP_GET_PROC(_vcomp_atomic_mul_r4);
240 VCOMP_GET_PROC(_vcomp_atomic_mul_r8);
241 VCOMP_GET_PROC(_vcomp_atomic_or_i4);
242 VCOMP_GET_PROC(_vcomp_atomic_shl_i4);
243 VCOMP_GET_PROC(_vcomp_atomic_shr_i4);
244 VCOMP_GET_PROC(_vcomp_atomic_shr_ui4);
245 VCOMP_GET_PROC(_vcomp_atomic_sub_i4);
246 VCOMP_GET_PROC(_vcomp_atomic_sub_r4);
247 VCOMP_GET_PROC(_vcomp_atomic_sub_r8);
248 VCOMP_GET_PROC(_vcomp_atomic_xor_i4);
249 VCOMP_GET_PROC(_vcomp_barrier);
250 VCOMP_GET_PROC(_vcomp_enter_critsect);
251 VCOMP_GET_PROC(_vcomp_flush);
252 VCOMP_GET_PROC(_vcomp_for_dynamic_init);
253 VCOMP_GET_PROC(_vcomp_for_dynamic_next);
254 VCOMP_GET_PROC(_vcomp_for_static_end);
255 VCOMP_GET_PROC(_vcomp_for_static_init);
256 VCOMP_GET_PROC(_vcomp_for_static_simple_init);
257 VCOMP_GET_PROC(_vcomp_fork);
258 VCOMP_GET_PROC(_vcomp_get_thread_num);
259 VCOMP_GET_PROC(_vcomp_leave_critsect);
260 VCOMP_GET_PROC(_vcomp_master_begin);
261 VCOMP_GET_PROC(_vcomp_master_end);
262 VCOMP_GET_PROC(_vcomp_sections_init);
263 VCOMP_GET_PROC(_vcomp_sections_next);
264 VCOMP_GET_PROC(_vcomp_set_num_threads);
265 VCOMP_GET_PROC(_vcomp_single_begin);
266 VCOMP_GET_PROC(_vcomp_single_end);
267 VCOMP_GET_PROC(omp_destroy_lock);
268 VCOMP_GET_PROC(omp_destroy_nest_lock);
269 VCOMP_GET_PROC(omp_get_max_threads);
270 VCOMP_GET_PROC(omp_get_nested);
271 VCOMP_GET_PROC(omp_get_num_threads);
272 VCOMP_GET_PROC(omp_get_thread_num);
273 VCOMP_GET_PROC(omp_in_parallel);
274 VCOMP_GET_PROC(omp_init_lock);
275 VCOMP_GET_PROC(omp_init_nest_lock);
276 VCOMP_GET_PROC(omp_set_lock);
277 VCOMP_GET_PROC(omp_set_nest_lock);
278 VCOMP_GET_PROC(omp_set_nested);
279 VCOMP_GET_PROC(omp_set_num_threads);
280 VCOMP_GET_PROC(omp_test_lock);
281 VCOMP_GET_PROC(omp_test_nest_lock);
282 VCOMP_GET_PROC(omp_unset_lock);
283 VCOMP_GET_PROC(omp_unset_nest_lock);
285 return TRUE;
288 #undef VCOMP_GET_PROC
290 static void CDECL num_threads_cb2(int parallel, LONG *count)
292 int is_parallel = pomp_in_parallel();
293 ok(is_parallel == parallel, "expected %d, got %d\n", parallel, is_parallel);
295 InterlockedIncrement(count);
298 static void CDECL num_threads_cb(BOOL nested, int parallel, int nested_threads, LONG *count)
300 int is_parallel, num_threads, thread_num;
301 LONG thread_count;
303 InterlockedIncrement(count);
304 p_vcomp_barrier();
306 num_threads = pomp_get_num_threads();
307 ok(num_threads == *count, "expected num_threads == %d, got %d\n", *count, num_threads);
308 thread_num = pomp_get_thread_num();
309 ok(thread_num >= 0 && thread_num < num_threads,
310 "expected thread_num in range [0, %d], got %d\n", num_threads - 1, thread_num);
311 ok(thread_num == p_vcomp_get_thread_num(),
312 "expected _vcomp_get_thread_num to return the same value\n");
314 is_parallel = pomp_in_parallel();
315 ok(is_parallel == parallel, "expected %d, got %d\n", parallel, is_parallel);
317 thread_count = 0;
318 p_vcomp_fork(TRUE, 2, num_threads_cb2, TRUE, &thread_count);
319 if (nested)
320 ok(thread_count == nested_threads, "expected %d threads, got %d\n", nested_threads, thread_count);
321 else
322 ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
324 is_parallel = pomp_in_parallel();
325 ok(is_parallel == parallel, "expected %d, got %d\n", parallel, is_parallel);
327 thread_count = 0;
328 p_vcomp_fork(FALSE, 2, num_threads_cb2, parallel, &thread_count);
329 ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
331 is_parallel = pomp_in_parallel();
332 ok(is_parallel == parallel, "expected %d, got %d\n", parallel, is_parallel);
334 p_vcomp_set_num_threads(4);
335 thread_count = 0;
336 p_vcomp_fork(TRUE, 2, num_threads_cb2, TRUE, &thread_count);
337 if (nested)
338 ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
339 else
340 ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
342 is_parallel = pomp_in_parallel();
343 ok(is_parallel == parallel, "expected %d, got %d\n", parallel, is_parallel);
346 static void test_omp_get_num_threads(BOOL nested)
348 int is_nested, is_parallel, max_threads, num_threads, thread_num;
349 LONG thread_count;
351 ok(pomp_get_thread_num != p_vcomp_get_thread_num,
352 "expected omp_get_thread_num != _vcomp_get_thread_num\n");
354 pomp_set_nested(nested);
355 is_nested = pomp_get_nested();
356 ok(is_nested == nested, "expected %d, got %d\n", nested, is_nested);
358 max_threads = pomp_get_max_threads();
359 ok(max_threads >= 1, "expected max_threads >= 1, got %d\n", max_threads);
360 thread_num = pomp_get_thread_num();
361 ok(thread_num == 0, "expected thread_num == 0, got %d\n", thread_num);
363 is_parallel = pomp_in_parallel();
364 ok(is_parallel == FALSE, "expected FALSE, got %d\n", is_parallel);
366 num_threads = pomp_get_num_threads();
367 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
368 thread_count = 0;
369 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, max_threads, &thread_count);
370 ok(thread_count == max_threads, "expected %d threads, got %d\n", max_threads, thread_count);
372 is_parallel = pomp_in_parallel();
373 ok(is_parallel == FALSE, "expected FALSE, got %d\n", is_parallel);
375 num_threads = pomp_get_num_threads();
376 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
377 thread_count = 0;
378 p_vcomp_fork(FALSE, 4, num_threads_cb, TRUE, FALSE, max_threads, &thread_count);
379 ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
381 is_parallel = pomp_in_parallel();
382 ok(is_parallel == FALSE, "expected FALSE, got %d\n", is_parallel);
384 pomp_set_num_threads(1);
385 num_threads = pomp_get_num_threads();
386 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
387 thread_count = 0;
388 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 1, &thread_count);
389 ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
391 is_parallel = pomp_in_parallel();
392 ok(is_parallel == FALSE, "expected FALSE, got %d\n", is_parallel);
394 pomp_set_num_threads(2);
395 num_threads = pomp_get_num_threads();
396 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
397 thread_count = 0;
398 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 2, &thread_count);
399 ok(thread_count == 2, "expected 2 threads, got %d\n", thread_count);
401 pomp_set_num_threads(4);
402 num_threads = pomp_get_num_threads();
403 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
404 thread_count = 0;
405 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
406 ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
408 p_vcomp_set_num_threads(8);
409 num_threads = pomp_get_num_threads();
410 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
411 thread_count = 0;
412 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
413 ok(thread_count == 8, "expected 8 threads, got %d\n", thread_count);
414 thread_count = 0;
415 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
416 ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
418 p_vcomp_set_num_threads(0);
419 num_threads = pomp_get_num_threads();
420 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
421 thread_count = 0;
422 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
423 ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
425 pomp_set_num_threads(0);
426 num_threads = pomp_get_num_threads();
427 ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
428 thread_count = 0;
429 p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
430 ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
432 pomp_set_num_threads(max_threads);
433 pomp_set_nested(FALSE);
436 static void CDECL fork_ptr_cb(LONG *a, LONG *b, LONG *c, LONG *d, LONG *e)
438 InterlockedIncrement(a);
439 InterlockedIncrement(b);
440 InterlockedIncrement(c);
441 InterlockedIncrement(d);
442 InterlockedIncrement(e);
445 static void CDECL fork_uintptr_cb(UINT_PTR a, UINT_PTR b, UINT_PTR c, UINT_PTR d, UINT_PTR e)
447 ok(a == 1, "expected a == 1, got %p\n", (void *)a);
448 ok(b == MAXUINT_PTR - 2, "expected b == MAXUINT_PTR - 2, got %p\n", (void *)b);
449 ok(c == 3, "expected c == 3, got %p\n", (void *)c);
450 ok(d == MAXUINT_PTR - 4, "expected d == MAXUINT_PTR - 4, got %p\n", (void *)d);
451 ok(e == 5, "expected e == 5, got %p\n", (void *)e);
454 #ifdef __i386__
455 static void CDECL fork_float_cb(float a, float b, float c, float d, float e)
457 ok(1.4999 < a && a < 1.5001, "expected a == 1.5, got %f\n", a);
458 ok(2.4999 < b && b < 2.5001, "expected b == 2.5, got %f\n", b);
459 ok(3.4999 < c && c < 3.5001, "expected c == 3.5, got %f\n", c);
460 ok(4.4999 < d && d < 4.5001, "expected d == 4.5, got %f\n", d);
461 ok(5.4999 < e && e < 5.5001, "expected e == 5.5, got %f\n", e);
463 #endif
465 static void test_vcomp_fork(void)
467 LONG a, b, c, d, e;
468 int max_threads = pomp_get_max_threads();
469 pomp_set_num_threads(4);
471 a = 0; b = 1; c = 2; d = 3; e = 4;
472 p_vcomp_fork(FALSE, 5, fork_ptr_cb, &a, &b, &c, &d, &e);
473 ok(a == 1, "expected a == 1, got %d\n", a);
474 ok(b == 2, "expected b == 2, got %d\n", b);
475 ok(c == 3, "expected c == 3, got %d\n", c);
476 ok(d == 4, "expected d == 4, got %d\n", d);
477 ok(e == 5, "expected e == 5, got %d\n", e);
479 a = 0; b = 1; c = 2; d = 3; e = 4;
480 p_vcomp_fork(TRUE, 5, fork_ptr_cb, &a, &b, &c, &d, &e);
481 ok(a == 4, "expected a == 4, got %d\n", a);
482 ok(b == 5, "expected b == 5, got %d\n", b);
483 ok(c == 6, "expected c == 6, got %d\n", c);
484 ok(d == 7, "expected d == 7, got %d\n", d);
485 ok(e == 8, "expected e == 8, got %d\n", e);
487 p_vcomp_fork(TRUE, 5, fork_uintptr_cb, (UINT_PTR)1, (UINT_PTR)(MAXUINT_PTR - 2),
488 (UINT_PTR)3, (UINT_PTR)(MAXUINT_PTR - 4), (UINT_PTR)5);
490 #ifdef __i386__
492 void (CDECL *func)(BOOL, int, void *, float, float, float, float, float) = (void *)p_vcomp_fork;
493 func(TRUE, 5, fork_float_cb, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f);
495 #else
496 skip("skipping float test on non-x86\n");
497 #endif
499 pomp_set_num_threads(max_threads);
502 static void CDECL section_cb(LONG *a, LONG *b, LONG *c)
504 int i;
506 p_vcomp_sections_init(20);
507 while ((i = p_vcomp_sections_next()) != -1)
509 InterlockedIncrement(a);
510 Sleep(1);
513 p_vcomp_sections_init(30);
514 while ((i = p_vcomp_sections_next()) != -1)
516 InterlockedIncrement(b);
517 Sleep(1);
520 p_vcomp_sections_init(40);
521 while ((i = p_vcomp_sections_next()) != -1)
523 InterlockedIncrement(c);
524 Sleep(1);
528 static void test_vcomp_sections_init(void)
530 LONG a, b, c;
531 int max_threads = pomp_get_max_threads();
532 int i;
534 if (0)
536 /* calling _vcomp_sections_next without prior _vcomp_sections_init
537 * returns uninitialized memory on Windows. */
538 i = p_vcomp_sections_next();
539 ok(i == -1, "expected -1, got %d\n", i);
542 a = b = c = 0;
543 section_cb(&a, &b, &c);
544 ok(a == 20, "expected a == 20, got %d\n", a);
545 ok(b == 30, "expected b == 30, got %d\n", b);
546 ok(c == 40, "expected c == 40, got %d\n", c);
548 for (i = 1; i <= 4; i++)
550 pomp_set_num_threads(i);
552 a = b = c = 0;
553 p_vcomp_fork(TRUE, 3, section_cb, &a, &b, &c);
554 ok(a == 20, "expected a == 20, got %d\n", a);
555 ok(b == 30, "expected b == 30, got %d\n", b);
556 ok(c == 40, "expected c == 40, got %d\n", c);
558 a = b = c = 0;
559 p_vcomp_fork(FALSE, 3, section_cb, &a, &b, &c);
560 ok(a == 20, "expected a == 20, got %d\n", a);
561 ok(b == 30, "expected b == 30, got %d\n", b);
562 ok(c == 40, "expected c == 40, got %d\n", c);
565 pomp_set_num_threads(max_threads);
568 static void my_for_static_simple_init(BOOL dynamic, unsigned int first, unsigned int last, int step,
569 BOOL increment, unsigned int *begin, unsigned int *end)
571 unsigned int iterations, per_thread, remaining;
572 int num_threads = pomp_get_num_threads();
573 int thread_num = pomp_get_thread_num();
575 if (!dynamic && num_threads == 1)
577 *begin = first;
578 *end = last;
579 return;
582 if (step <= 0)
584 *begin = 0;
585 *end = increment ? -1 : 1;
586 return;
589 if (increment)
590 iterations = 1 + (last - first) / step;
591 else
593 iterations = 1 + (first - last) / step;
594 step *= -1;
597 per_thread = iterations / num_threads;
598 remaining = iterations - per_thread * num_threads;
600 if (thread_num < remaining)
601 per_thread++;
602 else if (per_thread)
603 first += remaining * step;
604 else
606 *begin = first;
607 *end = first - step;
608 return;
611 *begin = first + per_thread * thread_num * step;
612 *end = *begin + (per_thread - 1) * step;
616 static void CDECL for_static_simple_cb(void)
618 static const struct
620 unsigned int first;
621 unsigned int last;
622 int step;
624 tests[] =
626 { 0, 0, 1 }, /* 0 */
627 { 0, 1, 1 },
628 { 0, 2, 1 },
629 { 0, 3, 1 },
630 { 0, 100, 0 },
631 { 0, 100, 1 },
632 { 0, 100, 2 },
633 { 0, 100, 3 },
634 { 0, 100, -1 },
635 { 0, 100, -2 },
636 { 0, 100, -3 }, /* 10 */
637 { 0, 100, 10 },
638 { 0, 100, 50 },
639 { 0, 100, 100 },
640 { 0, 100, 150 },
641 { 0, 0x80000000, 1 },
642 { 0, 0xfffffffe, 1 },
643 { 0, 0xffffffff, 1 },
644 { 50, 50, 0 },
645 { 50, 50, 1 },
646 { 50, 50, 2 }, /* 20 */
647 { 50, 50, 3 },
648 { 50, 50, -1 },
649 { 50, 50, -2 },
650 { 50, 50, -3 },
651 { 100, 200, 1 },
652 { 100, 200, 5 },
653 { 100, 200, 10 },
654 { 100, 200, 50 },
655 { 100, 200, 100 },
656 { 100, 200, 150 }, /* 30 */
658 int num_threads = pomp_get_num_threads();
659 int thread_num = pomp_get_thread_num();
660 int i;
662 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
664 unsigned int my_begin, my_end, begin, end;
666 begin = end = 0xdeadbeef;
667 my_for_static_simple_init(FALSE, tests[i].first, tests[i].last, tests[i].step, FALSE, &my_begin, &my_end);
668 p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, FALSE, &begin, &end);
670 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
671 i, thread_num, num_threads, my_begin, begin);
672 ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
673 i, thread_num, num_threads, my_end, end);
675 p_vcomp_for_static_end();
676 p_vcomp_barrier();
678 begin = end = 0xdeadbeef;
679 my_for_static_simple_init(FALSE, tests[i].first, tests[i].last, tests[i].step, TRUE, &my_begin, &my_end);
680 p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, TRUE, &begin, &end);
682 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
683 i, thread_num, num_threads, my_begin, begin);
684 ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
685 i, thread_num, num_threads, my_end, end);
687 p_vcomp_for_static_end();
688 p_vcomp_barrier();
690 if (tests[i].first == tests[i].last) continue;
692 begin = end = 0xdeadbeef;
693 my_for_static_simple_init(FALSE, tests[i].last, tests[i].first, tests[i].step, FALSE, &my_begin, &my_end);
694 p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, FALSE, &begin, &end);
696 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
697 i, thread_num, num_threads, my_begin, begin);
698 ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
699 i, thread_num, num_threads, my_end, end);
701 p_vcomp_for_static_end();
702 p_vcomp_barrier();
704 begin = end = 0xdeadbeef;
705 my_for_static_simple_init(FALSE, tests[i].last, tests[i].first, tests[i].step, TRUE, &my_begin, &my_end);
706 p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, TRUE, &begin, &end);
708 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %u, got %u\n",
709 i, thread_num, num_threads, my_begin, begin);
710 ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
711 i, thread_num, num_threads, my_end, end);
713 p_vcomp_for_static_end();
714 p_vcomp_barrier();
718 static void test_vcomp_for_static_simple_init(void)
720 int max_threads = pomp_get_max_threads();
721 int i;
723 for_static_simple_cb();
725 for (i = 1; i <= 4; i++)
727 pomp_set_num_threads(i);
728 p_vcomp_fork(TRUE, 0, for_static_simple_cb);
729 p_vcomp_fork(FALSE, 0, for_static_simple_cb);
732 pomp_set_num_threads(max_threads);
735 #define VCOMP_FOR_STATIC_BROKEN_LOOP 1
736 #define VCOMP_FOR_STATIC_BROKEN_NEXT 2
738 static DWORD CDECL my_for_static_init(int first, int last, int step, int chunksize, unsigned int *loops,
739 int *begin, int *end, int *next, int *lastchunk)
741 unsigned int iterations, num_chunks, per_thread, remaining;
742 int num_threads = pomp_get_num_threads();
743 int thread_num = pomp_get_thread_num();
745 if (num_threads == 1 && chunksize != 1)
747 *loops = 1;
748 *begin = first;
749 *end = last;
750 *next = 0;
751 *lastchunk = first;
752 return 0;
755 if (first == last)
757 *loops = !thread_num;
758 if (!thread_num)
760 /* The value in *next on Windows is either uninitialized, or contains
761 * garbage. The value shouldn't matter for *loops <= 1, so no need to
762 * reproduce that. */
763 *begin = first;
764 *end = last;
765 *next = 0;
766 *lastchunk = first;
768 return thread_num ? 0 : VCOMP_FOR_STATIC_BROKEN_NEXT;
771 if (step <= 0)
773 /* The total number of iterations depends on the number of threads here,
774 * which doesn't make any sense. This is most likely a bug in the Windows
775 * implementation. */
776 return VCOMP_FOR_STATIC_BROKEN_LOOP;
779 if (first < last)
780 iterations = 1 + (last - first) / step;
781 else
783 iterations = 1 + (first - last) / step;
784 step *= -1;
787 if (chunksize < 1)
788 chunksize = 1;
790 num_chunks = ((DWORD64)iterations + chunksize - 1) / chunksize;
791 per_thread = num_chunks / num_threads;
792 remaining = num_chunks - per_thread * num_threads;
794 *loops = per_thread + (thread_num < remaining);
795 *begin = first + thread_num * chunksize * step;
796 *end = *begin + (chunksize - 1) * step;
797 *next = chunksize * num_threads * step;
798 *lastchunk = first + (num_chunks - 1) * chunksize * step;
799 return 0;
802 static void CDECL for_static_cb(void)
804 static const struct
806 int first;
807 int last;
808 int step;
809 int chunksize;
811 tests[] =
813 { 0, 0, 1, 1 }, /* 0 */
814 { 0, 1, 1, 1 },
815 { 0, 2, 1, 1 },
816 { 0, 3, 1, 1 },
817 { 0, 100, 1, 0 },
818 { 0, 100, 1, 1 },
819 { 0, 100, 1, 5 },
820 { 0, 100, 1, 10 },
821 { 0, 100, 1, 50 },
822 { 0, 100, 1, 100 },
823 { 0, 100, 1, 150 }, /* 10 */
824 { 0, 100, 3, 0 },
825 { 0, 100, 3, 1 },
826 { 0, 100, 3, 5 },
827 { 0, 100, 3, 10 },
828 { 0, 100, 3, 50 },
829 { 0, 100, 3, 100 },
830 { 0, 100, 3, 150 },
831 { 0, 100, 5, 1 },
832 { 0, 100, -3, 0 },
833 { 0, 100, -3, 1 }, /* 20 */
834 { 0, 100, -3, 5 },
835 { 0, 100, -3, 10 },
836 { 0, 100, -3, 50 },
837 { 0, 100, -3, 100 },
838 { 0, 100, -3, 150 },
839 { 0, 100, 10, 1 },
840 { 0, 100, 50, 1 },
841 { 0, 100, 100, 1 },
842 { 0, 100, 150, 1 },
843 { 0, 0x10000000, 1, 123 }, /* 30 */
844 { 0, 0x20000000, 1, 123 },
845 { 0, 0x40000000, 1, 123 },
846 { 0, -0x80000000, 1, 123 },
847 { 50, 50, 1, 1 },
848 { 50, 50, 1, 2 },
849 { 50, 50, 1, -1 },
850 { 50, 50, 1, -2 },
851 { 50, 50, 2, 1 },
852 { 50, 50, 3, 1 },
853 { 100, 200, 3, 1 }, /* 40 */
854 { 100, 200, 3, -1 },
855 { 0x7ffffffe, -0x80000000, 1, 123 },
856 { 0x7fffffff, -0x80000000, 1, 123 },
858 int num_threads = pomp_get_num_threads();
859 int thread_num = pomp_get_thread_num();
860 int i;
862 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
864 int my_begin, my_end, my_next, my_lastchunk;
865 int begin, end, next, lastchunk;
866 unsigned int my_loops, loops;
867 DWORD broken_flags;
869 my_loops = my_begin = my_end = my_next = my_lastchunk = 0xdeadbeef;
870 loops = begin = end = next = lastchunk = 0xdeadbeef;
871 broken_flags = my_for_static_init(tests[i].first, tests[i].last, tests[i].step, tests[i].chunksize,
872 &my_loops, &my_begin, &my_end, &my_next, &my_lastchunk);
873 p_vcomp_for_static_init(tests[i].first, tests[i].last, tests[i].step, tests[i].chunksize,
874 &loops, &begin, &end, &next, &lastchunk);
876 if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
878 ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %u\n",
879 i, thread_num, num_threads, loops);
881 else
883 ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %u, got %u\n",
884 i, thread_num, num_threads, my_loops, loops);
885 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
886 i, thread_num, num_threads, my_begin, begin);
887 ok(end == my_end, "test %d, thread %d/%d: expected end == %d, got %d\n",
888 i, thread_num, num_threads, my_end, end);
889 ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
890 "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
891 ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
892 i, thread_num, num_threads, my_lastchunk, lastchunk);
895 p_vcomp_for_static_end();
896 p_vcomp_barrier();
898 if (tests[i].first == tests[i].last) continue;
900 my_loops = my_begin = my_end = my_next = my_lastchunk = 0xdeadbeef;
901 loops = begin = end = next = lastchunk = 0xdeadbeef;
902 broken_flags = my_for_static_init(tests[i].last, tests[i].first, tests[i].step, tests[i].chunksize,
903 &my_loops, &my_begin, &my_end, &my_next, &my_lastchunk);
904 p_vcomp_for_static_init(tests[i].last, tests[i].first, tests[i].step, tests[i].chunksize,
905 &loops, &begin, &end, &next, &lastchunk);
907 if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
909 ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %u\n",
910 i, thread_num, num_threads, loops);
912 else
914 ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %u, got %u\n",
915 i, thread_num, num_threads, my_loops, loops);
916 ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
917 i, thread_num, num_threads, my_begin, begin);
918 ok(end == my_end, "test %d, thread %d/%d: expected end == %d, got %d\n",
919 i, thread_num, num_threads, my_end, end);
920 ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
921 "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
922 ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
923 i, thread_num, num_threads, my_lastchunk, lastchunk);
926 p_vcomp_for_static_end();
927 p_vcomp_barrier();
931 #undef VCOMP_FOR_STATIC_BROKEN_LOOP
932 #undef VCOMP_FOR_STATIC_BROKEN_NEXT
934 static void test_vcomp_for_static_init(void)
936 int max_threads = pomp_get_max_threads();
937 int i;
939 for_static_cb();
941 for (i = 1; i <= 4; i++)
943 pomp_set_num_threads(i);
944 p_vcomp_fork(TRUE, 0, for_static_cb);
945 p_vcomp_fork(FALSE, 0, for_static_cb);
948 pomp_set_num_threads(max_threads);
951 static void CDECL for_dynamic_static_cb(void)
953 unsigned int my_begin, my_end, begin, end;
954 int ret;
956 begin = end = 0xdeadbeef;
957 my_for_static_simple_init(TRUE, 0, 1000, 7, TRUE, &my_begin, &my_end);
958 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_STATIC | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 1);
959 ret = p_vcomp_for_dynamic_next(&begin, &end);
960 ok(ret == TRUE, "expected ret == TRUE, got %d\n", ret);
961 ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
962 ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
963 ret = p_vcomp_for_dynamic_next(&begin, &end);
964 ok(ret == FALSE, "expected ret == FALSE, got %d\n", ret);
966 begin = end = 0xdeadbeef;
967 my_for_static_simple_init(TRUE, 1000, 0, 7, FALSE, &my_begin, &my_end);
968 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_STATIC, 1000, 0, 7, 1);
969 ret = p_vcomp_for_dynamic_next(&begin, &end);
970 ok(ret == TRUE, "expected ret == TRUE, got %d\n", ret);
971 ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
972 ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
973 ret = p_vcomp_for_dynamic_next(&begin, &end);
974 ok(ret == FALSE, "expected ret == FALSE, got %d\n", ret);
976 begin = end = 0xdeadbeef;
977 my_for_static_simple_init(TRUE, 0, 1000, 7, TRUE, &my_begin, &my_end);
978 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_STATIC | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 5);
979 ret = p_vcomp_for_dynamic_next(&begin, &end);
980 ok(ret == TRUE, "expected ret == TRUE, got %d\n", ret);
981 ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
982 ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
983 ret = p_vcomp_for_dynamic_next(&begin, &end);
984 ok(ret == FALSE, "expected ret == FALSE, got %d\n", ret);
986 begin = end = 0xdeadbeef;
987 my_for_static_simple_init(TRUE, 1000, 0, 7, FALSE, &my_begin, &my_end);
988 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_STATIC, 1000, 0, 7, 5);
989 ret = p_vcomp_for_dynamic_next(&begin, &end);
990 ok(ret == TRUE, "expected ret == TRUE, got %d\n", ret);
991 ok(begin == my_begin, "expected begin == %u, got %u\n", my_begin, begin);
992 ok(end == my_end, "expected end == %u, got %u\n", my_end, end);
993 ret = p_vcomp_for_dynamic_next(&begin, &end);
994 ok(ret == FALSE, "expected ret == FALSE, got %d\n", ret);
997 static void CDECL for_dynamic_chunked_cb(LONG *a, LONG *b, LONG *c, LONG *d)
999 unsigned int begin, end;
1001 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_CHUNKED | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 1);
1002 while (p_vcomp_for_dynamic_next(&begin, &end))
1004 if (begin == 994) ok(end == 1000, "expected end == 1000, got %u\n", end);
1005 else ok(begin == end, "expected begin == end, got %u and %u\n", begin, end);
1006 InterlockedExchangeAdd(a, begin);
1009 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_CHUNKED, 1000, 0, 7, 1);
1010 while (p_vcomp_for_dynamic_next(&begin, &end))
1012 if (begin == 6) ok(end == 0, "expected end == 0, got %u\n", end);
1013 else ok(begin == end, "expected begin == end, got %u and %u\n", begin, end);
1014 InterlockedExchangeAdd(b, begin);
1017 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_CHUNKED | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 5);
1018 while (p_vcomp_for_dynamic_next(&begin, &end))
1020 if (begin == 980) ok(end == 1000, "expected end == 1000, got %u\n", end);
1021 else ok(begin + 28 == end, "expected begin + 28 == end, got %u and %u\n", begin + 28, end);
1022 InterlockedExchangeAdd(c, begin);
1025 p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FLAGS_CHUNKED, 1000, 0, 7, 5);
1026 while (p_vcomp_for_dynamic_next(&begin, &end))
1028 if (begin == 20) ok(end == 0, "expected end == 0, got %u\n", end);
1029 else ok(begin - 28 == end, "expected begin - 28 == end, got %u and %u\n", begin - 28, end);
1030 InterlockedExchangeAdd(d, begin);
1034 static void CDECL for_dynamic_guided_cb(unsigned int flags, LONG *a, LONG *b, LONG *c, LONG *d)
1036 int num_threads = pomp_get_num_threads();
1037 unsigned int begin, end;
1039 p_vcomp_for_dynamic_init(flags | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 1);
1040 while (p_vcomp_for_dynamic_next(&begin, &end))
1042 ok(num_threads != 1 || (begin == 0 && end == 1000),
1043 "expected begin == 0 and end == 1000, got %u and %u\n", begin, end);
1044 InterlockedExchangeAdd(a, begin);
1047 p_vcomp_for_dynamic_init(flags, 1000, 0, 7, 1);
1048 while (p_vcomp_for_dynamic_next(&begin, &end))
1050 ok(num_threads != 1 || (begin == 1000 && end == 0),
1051 "expected begin == 1000 and end == 0, got %u and %u\n", begin, end);
1052 InterlockedExchangeAdd(b, begin);
1055 p_vcomp_for_dynamic_init(flags | VCOMP_DYNAMIC_FLAGS_INCREMENT, 0, 1000, 7, 5);
1056 while (p_vcomp_for_dynamic_next(&begin, &end))
1058 ok(num_threads != 1 || (begin == 0 && end == 1000),
1059 "expected begin == 0 and end == 1000, got %u and %u\n", begin, end);
1060 InterlockedExchangeAdd(c, begin);
1063 p_vcomp_for_dynamic_init(flags, 1000, 0, 7, 5);
1064 while (p_vcomp_for_dynamic_next(&begin, &end))
1066 ok(num_threads != 1 || (begin == 1000 && end == 0),
1067 "expected begin == 1000 and end == 0, got %u and %u\n", begin, end);
1068 InterlockedExchangeAdd(d, begin);
1072 static void test_vcomp_for_dynamic_init(void)
1074 static const int guided_a[] = {0, 6041, 9072, 11179};
1075 static const int guided_b[] = {1000, 1959, 2928, 3821};
1076 static const int guided_c[] = {0, 4067, 6139, 7273};
1077 static const int guided_d[] = {1000, 1933, 2861, 3727};
1078 LONG a, b, c, d;
1079 int max_threads = pomp_get_max_threads();
1080 int i;
1082 /* test static scheduling */
1083 for_dynamic_static_cb();
1085 for (i = 1; i <= 4; i++)
1087 pomp_set_num_threads(i);
1088 p_vcomp_fork(TRUE, 0, for_dynamic_static_cb);
1089 p_vcomp_fork(FALSE, 0, for_dynamic_static_cb);
1092 /* test chunked scheduling */
1093 a = b = c = d = 0;
1094 for_dynamic_chunked_cb(&a, &b, &c, &d);
1095 ok(a == 71071, "expected a == 71071, got %d\n", a);
1096 ok(b == 71929, "expected b == 71929, got %d\n", b);
1097 ok(c == 14210, "expected c == 14210, got %d\n", c);
1098 ok(d == 14790, "expected d == 14790, got %d\n", d);
1100 for (i = 1; i <= 4; i++)
1102 pomp_set_num_threads(i);
1104 a = b = c = d = 0;
1105 p_vcomp_fork(TRUE, 4, for_dynamic_chunked_cb, &a, &b, &c, &d);
1106 ok(a == 71071, "expected a == 71071, got %d\n", a);
1107 ok(b == 71929, "expected b == 71929, got %d\n", b);
1108 ok(c == 14210, "expected c == 14210, got %d\n", c);
1109 ok(d == 14790, "expected d == 14790, got %d\n", d);
1111 a = b = c = d = 0;
1112 p_vcomp_fork(FALSE, 4, for_dynamic_chunked_cb, &a, &b, &c, &d);
1113 ok(a == 71071, "expected a == 71071, got %d\n", a);
1114 ok(b == 71929, "expected b == 71929, got %d\n", b);
1115 ok(c == 14210, "expected c == 14210, got %d\n", c);
1116 ok(d == 14790, "expected d == 14790, got %d\n", d);
1119 /* test guided scheduling */
1120 a = b = c = d = 0;
1121 for_dynamic_guided_cb(VCOMP_DYNAMIC_FLAGS_GUIDED, &a, &b, &c, &d);
1122 ok(a == guided_a[0], "expected a == %d, got %d\n", guided_a[0], a);
1123 ok(b == guided_b[0], "expected b == %d, got %d\n", guided_b[0], b);
1124 ok(c == guided_c[0], "expected c == %d, got %d\n", guided_c[0], c);
1125 ok(d == guided_d[0], "expected d == %d, got %d\n", guided_d[0], d);
1127 for (i = 1; i <= 4; i++)
1129 pomp_set_num_threads(i);
1131 a = b = c = d = 0;
1132 p_vcomp_fork(TRUE, 5, for_dynamic_guided_cb, VCOMP_DYNAMIC_FLAGS_GUIDED, &a, &b, &c, &d);
1133 ok(a == guided_a[i - 1], "expected a == %d, got %d\n", guided_a[i - 1], a);
1134 ok(b == guided_b[i - 1], "expected b == %d, got %d\n", guided_b[i - 1], b);
1135 ok(c == guided_c[i - 1], "expected c == %d, got %d\n", guided_c[i - 1], c);
1136 ok(d == guided_d[i - 1], "expected d == %d, got %d\n", guided_d[i - 1], d);
1138 a = b = c = d = 0;
1139 p_vcomp_fork(FALSE, 5, for_dynamic_guided_cb, VCOMP_DYNAMIC_FLAGS_GUIDED, &a, &b, &c, &d);
1140 ok(a == guided_a[0], "expected a == %d, got %d\n", guided_a[0], a);
1141 ok(b == guided_b[0], "expected b == %d, got %d\n", guided_b[0], b);
1142 ok(c == guided_c[0], "expected c == %d, got %d\n", guided_c[0], c);
1143 ok(d == guided_d[0], "expected d == %d, got %d\n", guided_d[0], d);
1146 /* test with empty flags */
1147 a = b = c = d = 0;
1148 for_dynamic_guided_cb(0, &a, &b, &c, &d);
1149 ok(a == guided_a[0], "expected a == %d, got %d\n", guided_a[0], a);
1150 ok(b == guided_b[0], "expected b == %d, got %d\n", guided_b[0], b);
1151 ok(c == guided_c[0], "expected c == %d, got %d\n", guided_c[0], c);
1152 ok(d == guided_d[0], "expected d == %d, got %d\n", guided_d[0], d);
1154 for (i = 1; i <= 4; i++)
1156 pomp_set_num_threads(i);
1158 a = b = c = d = 0;
1159 p_vcomp_fork(TRUE, 5, for_dynamic_guided_cb, 0, &a, &b, &c, &d);
1160 ok(a == guided_a[i - 1], "expected a == %d, got %d\n", guided_a[i - 1], a);
1161 ok(b == guided_b[i - 1], "expected b == %d, got %d\n", guided_b[i - 1], b);
1162 ok(c == guided_c[i - 1], "expected c == %d, got %d\n", guided_c[i - 1], c);
1163 ok(d == guided_d[i - 1], "expected d == %d, got %d\n", guided_d[i - 1], d);
1165 a = b = c = d = 0;
1166 p_vcomp_fork(FALSE, 5, for_dynamic_guided_cb, 0, &a, &b, &c, &d);
1167 ok(a == guided_a[0], "expected a == %d, got %d\n", guided_a[0], a);
1168 ok(b == guided_b[0], "expected b == %d, got %d\n", guided_b[0], b);
1169 ok(c == guided_c[0], "expected c == %d, got %d\n", guided_c[0], c);
1170 ok(d == guided_d[0], "expected d == %d, got %d\n", guided_d[0], d);
1173 pomp_set_num_threads(max_threads);
1176 static void CDECL master_cb(HANDLE semaphore)
1178 int num_threads = pomp_get_num_threads();
1179 int thread_num = pomp_get_thread_num();
1181 if (p_vcomp_master_begin())
1183 ok(thread_num == 0, "expected thread_num == 0, got %d\n", thread_num);
1184 if (num_threads >= 2)
1186 DWORD result = WaitForSingleObject(semaphore, 1000);
1187 ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
1189 p_vcomp_master_end();
1192 if (thread_num == 1)
1193 ReleaseSemaphore(semaphore, 1, NULL);
1196 static void test_vcomp_master_begin(void)
1198 int max_threads = pomp_get_max_threads();
1199 HANDLE semaphore;
1200 int i;
1202 semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
1203 ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
1205 master_cb(semaphore);
1207 for (i = 1; i <= 4; i++)
1209 pomp_set_num_threads(i);
1210 p_vcomp_fork(TRUE, 1, master_cb, semaphore);
1211 p_vcomp_fork(FALSE, 1, master_cb, semaphore);
1214 CloseHandle(semaphore);
1215 pomp_set_num_threads(max_threads);
1218 static void CDECL single_cb(int flags, HANDLE semaphore)
1220 int num_threads = pomp_get_num_threads();
1222 if (p_vcomp_single_begin(flags))
1224 if (num_threads >= 2)
1226 DWORD result = WaitForSingleObject(semaphore, 1000);
1227 ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
1230 p_vcomp_single_end();
1232 if (p_vcomp_single_begin(flags))
1234 if (num_threads >= 2)
1235 ReleaseSemaphore(semaphore, 1, NULL);
1237 p_vcomp_single_end();
1240 static void test_vcomp_single_begin(void)
1242 int max_threads = pomp_get_max_threads();
1243 HANDLE semaphore;
1244 int i;
1246 semaphore = CreateSemaphoreA(NULL, 0, 1, NULL);
1247 ok(semaphore != NULL, "CreateSemaphoreA failed %u\n", GetLastError());
1249 single_cb(0, semaphore);
1250 single_cb(1, semaphore);
1252 for (i = 1; i <= 4; i++)
1254 pomp_set_num_threads(i);
1255 p_vcomp_fork(TRUE, 2, single_cb, 0, semaphore);
1256 p_vcomp_fork(TRUE, 2, single_cb, 1, semaphore);
1257 p_vcomp_fork(FALSE, 2, single_cb, 0, semaphore);
1258 p_vcomp_fork(FALSE, 2, single_cb, 1, semaphore);
1261 CloseHandle(semaphore);
1262 pomp_set_num_threads(max_threads);
1265 static void CDECL critsect_cb(LONG *a)
1267 static CRITICAL_SECTION *critsect;
1268 LONG tmp;
1270 p_vcomp_enter_critsect(&critsect);
1271 tmp = *a;
1272 Sleep(50);
1273 *a = tmp + 1;
1274 p_vcomp_leave_critsect(critsect);
1276 ok(critsect != NULL, "expected critsect != NULL\n");
1278 EnterCriticalSection(critsect);
1279 tmp = *a;
1280 Sleep(50);
1281 *a = tmp + 1;
1282 LeaveCriticalSection(critsect);
1285 static void test_vcomp_enter_critsect(void)
1287 int max_threads = pomp_get_max_threads();
1288 LONG a;
1289 int i;
1291 a = 0;
1292 critsect_cb(&a);
1293 ok(a == 2, "expected a == 2, got %d\n", a);
1295 for (i = 1; i <= 4; i++)
1297 pomp_set_num_threads(i);
1299 a = 0;
1300 p_vcomp_fork(TRUE, 1, critsect_cb, &a);
1301 ok(a == 2 * i, "expected a == %d, got %d\n", 2 * i, a);
1303 a = 0;
1304 p_vcomp_fork(FALSE, 1, critsect_cb, &a);
1305 ok(a == 2, "expected a == 2, got %d\n", a);
1308 pomp_set_num_threads(max_threads);
1311 static void test_vcomp_flush(void)
1313 p_vcomp_flush();
1314 p_vcomp_flush();
1315 p_vcomp_flush();
1318 static void test_omp_init_lock(void)
1320 omp_lock_t lock;
1321 int ret;
1323 pomp_init_lock(&lock);
1325 /* test omp_set_lock */
1326 pomp_set_lock(&lock);
1327 pomp_unset_lock(&lock);
1329 /* test omp_test_lock */
1330 ret = pomp_test_lock(&lock);
1331 ok(ret == 1, "expected ret == 1, got %d\n", ret);
1332 ret = pomp_test_lock(&lock);
1333 ok(ret == 0, "expected ret == 0, got %d\n", ret);
1334 pomp_unset_lock(&lock);
1336 /* test with EnterCriticalSection */
1337 EnterCriticalSection(lock);
1338 ret = pomp_test_lock(&lock);
1339 todo_wine
1340 ok(ret == 1, "expected ret == 1, got %d\n", ret);
1341 if (ret)
1343 ret = pomp_test_lock(&lock);
1344 ok(ret == 0, "expected ret == 0, got %d\n", ret);
1345 pomp_unset_lock(&lock);
1347 LeaveCriticalSection(lock);
1349 pomp_destroy_lock(&lock);
1352 static void test_omp_init_nest_lock(void)
1354 omp_nest_lock_t lock;
1355 int ret;
1357 ok(pomp_init_nest_lock == pomp_init_lock, "expected omp_init_nest_lock == %p, got %p\n",
1358 pomp_init_lock, pomp_init_nest_lock);
1359 ok(pomp_destroy_nest_lock == pomp_destroy_lock, "expected omp_destroy_nest_lock == %p, got %p\n",
1360 pomp_destroy_lock, pomp_destroy_nest_lock);
1362 pomp_init_nest_lock(&lock);
1364 /* test omp_set_nest_lock */
1365 pomp_set_nest_lock(&lock);
1366 pomp_set_nest_lock(&lock);
1367 pomp_unset_nest_lock(&lock);
1368 pomp_unset_nest_lock(&lock);
1370 /* test omp_test_nest_lock */
1371 ret = pomp_test_nest_lock(&lock);
1372 ok(ret == 1, "expected ret == 1, got %d\n", ret);
1373 ret = pomp_test_nest_lock(&lock);
1374 ok(ret == 2, "expected ret == 2, got %d\n", ret);
1375 ret = pomp_test_nest_lock(&lock);
1376 ok(ret == 3, "expected ret == 3, got %d\n", ret);
1377 pomp_unset_nest_lock(&lock);
1378 pomp_unset_nest_lock(&lock);
1379 pomp_unset_nest_lock(&lock);
1381 /* test with EnterCriticalSection */
1382 EnterCriticalSection(lock);
1383 ret = pomp_test_nest_lock(&lock);
1384 todo_wine
1385 ok(ret == 1, "expected ret == 1, got %d\n", ret);
1386 pomp_unset_nest_lock(&lock);
1387 LeaveCriticalSection(lock);
1389 pomp_destroy_nest_lock(&lock);
1392 static void test_atomic_integer32(void)
1394 struct
1396 void (CDECL *func)(int *, int);
1397 int v1, v2, expected;
1399 tests1[] =
1401 { p_vcomp_atomic_add_i4, 0x11223344, 0x77665544, -0x77777778 },
1402 { p_vcomp_atomic_and_i4, 0x11223344, 0x77665544, 0x11221144 },
1403 { p_vcomp_atomic_div_i4, 0x77665544, 0x11223344, 6 },
1404 { p_vcomp_atomic_div_i4, 0x77665544, -0x11223344, -6 },
1405 { p_vcomp_atomic_mul_i4, 0x11223344, 0x77665544, -0xecccdf0 },
1406 { p_vcomp_atomic_mul_i4, 0x11223344, -0x77665544, 0xecccdf0 },
1407 { p_vcomp_atomic_or_i4, 0x11223344, 0x77665544, 0x77667744 },
1408 { p_vcomp_atomic_shl_i4, 0x11223344, 3, -0x76ee65e0 },
1409 /* { p_vcomp_atomic_shl_i4, 0x11223344, 35, -0x76ee65e0 }, */ /* depends on Architecture */
1410 { p_vcomp_atomic_shl_i4, -0x11223344, 3, 0x76ee65e0 },
1411 { p_vcomp_atomic_shr_i4, 0x11223344, 3, 0x2244668 },
1412 /* { p_vcomp_atomic_shr_i4, 0x11223344, 35, 0x2244668 }, */ /* depends on Architecture */
1413 { p_vcomp_atomic_shr_i4, -0x11223344, 3, -0x2244669 },
1414 { p_vcomp_atomic_sub_i4, 0x11223344, 0x77665544, -0x66442200 },
1415 { p_vcomp_atomic_xor_i4, 0x11223344, 0x77665544, 0x66446600 },
1417 struct
1419 void (CDECL *func)(unsigned int *, unsigned int);
1420 unsigned int v1, v2, expected;
1422 tests2[] =
1424 { p_vcomp_atomic_div_ui4, 0x77665544, 0x11223344, 6 },
1425 { p_vcomp_atomic_div_ui4, 0x77665544, 0xeeddccbc, 0 },
1426 { p_vcomp_atomic_shr_ui4, 0x11223344, 3, 0x2244668 },
1427 /* { p_vcomp_atomic_shr_ui4, 0x11223344, 35, 0x2244668 }, */ /* depends on Architecture */
1428 { p_vcomp_atomic_shr_ui4, 0xeeddccbc, 3, 0x1ddbb997 },
1430 int i;
1432 for (i = 0; i < sizeof(tests1)/sizeof(tests1[0]); i++)
1434 int val = tests1[i].v1;
1435 tests1[i].func(&val, tests1[i].v2);
1436 ok(val == tests1[i].expected, "test %d: expected val == %d, got %d\n", i, tests1[i].expected, val);
1438 for (i = 0; i < sizeof(tests2)/sizeof(tests2[0]); i++)
1440 unsigned int val = tests2[i].v1;
1441 tests2[i].func(&val, tests2[i].v2);
1442 ok(val == tests2[i].expected, "test %d: expected val == %u, got %u\n", i, tests2[i].expected, val);
1446 static void test_atomic_float(void)
1448 struct
1450 void (CDECL *func)(float *, float);
1451 float v1, v2, expected;
1453 tests[] =
1455 { p_vcomp_atomic_add_r4, 42.0, 17.0, 42.0 + 17.0 },
1456 { p_vcomp_atomic_div_r4, 42.0, 17.0, 42.0 / 17.0 },
1457 { p_vcomp_atomic_mul_r4, 42.0, 17.0, 42.0 * 17.0 },
1458 { p_vcomp_atomic_sub_r4, 42.0, 17.0, 42.0 - 17.0 },
1460 int i;
1462 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1464 float val = tests[i].v1;
1465 tests[i].func(&val, tests[i].v2);
1466 ok(tests[i].expected - 0.001 < val && val < tests[i].expected + 0.001,
1467 "test %d: expected val == %f, got %f\n", i, tests[i].expected, val);
1471 static void test_atomic_double(void)
1473 struct
1475 void (CDECL *func)(double *, double);
1476 double v1, v2, expected;
1478 tests[] =
1480 { p_vcomp_atomic_add_r8, 42.0, 17.0, 42.0 + 17.0 },
1481 { p_vcomp_atomic_div_r8, 42.0, 17.0, 42.0 / 17.0 },
1482 { p_vcomp_atomic_mul_r8, 42.0, 17.0, 42.0 * 17.0 },
1483 { p_vcomp_atomic_sub_r8, 42.0, 17.0, 42.0 - 17.0 },
1485 int i;
1487 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
1489 double val = tests[i].v1;
1490 tests[i].func(&val, tests[i].v2);
1491 ok(tests[i].expected - 0.001 < val && val < tests[i].expected + 0.001,
1492 "test %d: expected val == %f, got %f\n", i, tests[i].expected, val);
1496 START_TEST(vcomp)
1498 if (!init_vcomp())
1499 return;
1501 test_omp_get_num_threads(FALSE);
1502 test_omp_get_num_threads(TRUE);
1503 test_vcomp_fork();
1504 test_vcomp_sections_init();
1505 test_vcomp_for_static_simple_init();
1506 test_vcomp_for_static_init();
1507 test_vcomp_for_dynamic_init();
1508 test_vcomp_master_begin();
1509 test_vcomp_single_begin();
1510 test_vcomp_enter_critsect();
1511 test_vcomp_flush();
1512 test_omp_init_lock();
1513 test_omp_init_nest_lock();
1514 test_atomic_integer32();
1515 test_atomic_float();
1516 test_atomic_double();
1518 release_vcomp();