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
102 #elif defined(__x86_64__)
104 #elif defined __arm__
106 #elif defined __aarch64__
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"
117 " name=\"Wine.vcomp.Test\"\n"
118 " version=\"1.0.0.0\"\n"
119 " processorArchitecture=\"" ARCH
"\"\n"
121 "<description>Wine vcomp test suite</description>\n"
123 " <dependentAssembly>\n"
124 " <assemblyIdentity\n"
126 " name=\"Microsoft.VC80.OpenMP\"\n"
127 " version=\"8.0.50608.0\"\n"
128 " processorArchitecture=\"" ARCH
"\"\n"
129 " publicKeyToken=\"1fc8b3b9a1e18e3b\"\n"
131 " </dependentAssembly>\n"
137 static void create_vcomp_manifest(void)
139 char temp_path
[MAX_PATH
];
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");
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");
166 if (!WriteFile(file
, vcomp_manifest
, sizeof(vcomp_manifest
) - 1, &written
, NULL
))
170 if (written
!= sizeof(vcomp_manifest
) - 1)
172 ok(0, "failed to write manifest file\n");
173 DeleteFileA(vcomp_manifest_file
);
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
);
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)
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) \
213 p ## func = (void *)GetProcAddress(vcomp_handle, #func); \
214 if (!p ## func) trace("Failed to get address for %s\n", #func); \
218 static BOOL
init_vcomp(void)
220 create_vcomp_manifest();
222 vcomp_handle
= LoadLibraryA("vcomp.dll");
225 win_skip("vcomp.dll not installed\n");
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
);
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
;
303 InterlockedIncrement(count
);
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
);
318 p_vcomp_fork(TRUE
, 2, num_threads_cb2
, TRUE
, &thread_count
);
320 ok(thread_count
== nested_threads
, "expected %d threads, got %d\n", nested_threads
, thread_count
);
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
);
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);
336 p_vcomp_fork(TRUE
, 2, num_threads_cb2
, TRUE
, &thread_count
);
338 ok(thread_count
== 4, "expected 4 threads, got %d\n", thread_count
);
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
465 static void test_vcomp_fork(void)
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);
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
);
496 skip("skipping float test on non-x86\n");
499 pomp_set_num_threads(max_threads
);
502 static void CDECL
section_cb(LONG
*a
, LONG
*b
, LONG
*c
)
506 p_vcomp_sections_init(20);
507 while ((i
= p_vcomp_sections_next()) != -1)
509 InterlockedIncrement(a
);
513 p_vcomp_sections_init(30);
514 while ((i
= p_vcomp_sections_next()) != -1)
516 InterlockedIncrement(b
);
520 p_vcomp_sections_init(40);
521 while ((i
= p_vcomp_sections_next()) != -1)
523 InterlockedIncrement(c
);
528 static void test_vcomp_sections_init(void)
531 int max_threads
= pomp_get_max_threads();
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
);
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
);
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
);
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)
585 *end
= increment
? -1 : 1;
590 iterations
= 1 + (last
- first
) / step
;
593 iterations
= 1 + (first
- last
) / step
;
597 per_thread
= iterations
/ num_threads
;
598 remaining
= iterations
- per_thread
* num_threads
;
600 if (thread_num
< remaining
)
603 first
+= remaining
* step
;
611 *begin
= first
+ per_thread
* thread_num
* step
;
612 *end
= *begin
+ (per_thread
- 1) * step
;
616 static void CDECL
for_static_simple_cb(void)
636 { 0, 100, -3 }, /* 10 */
641 { 0, 0x80000000, 1 },
642 { 0, 0xfffffffe, 1 },
643 { 0, 0xffffffff, 1 },
646 { 50, 50, 2 }, /* 20 */
656 { 100, 200, 150 }, /* 30 */
658 int num_threads
= pomp_get_num_threads();
659 int thread_num
= pomp_get_thread_num();
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();
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();
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();
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();
718 static void test_vcomp_for_static_simple_init(void)
720 int max_threads
= pomp_get_max_threads();
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)
757 *loops
= !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
768 return thread_num
? 0 : VCOMP_FOR_STATIC_BROKEN_NEXT
;
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
776 return VCOMP_FOR_STATIC_BROKEN_LOOP
;
780 iterations
= 1 + (last
- first
) / step
;
783 iterations
= 1 + (first
- last
) / step
;
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
;
802 static void CDECL
for_static_cb(void)
813 { 0, 0, 1, 1 }, /* 0 */
823 { 0, 100, 1, 150 }, /* 10 */
833 { 0, 100, -3, 1 }, /* 20 */
843 { 0, 0x10000000, 1, 123 }, /* 30 */
844 { 0, 0x20000000, 1, 123 },
845 { 0, 0x40000000, 1, 123 },
846 { 0, -0x80000000, 1, 123 },
853 { 100, 200, 3, 1 }, /* 40 */
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();
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
;
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
);
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();
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
);
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();
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();
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
;
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};
1079 int max_threads
= pomp_get_max_threads();
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 */
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
);
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
);
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 */
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
);
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
);
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 */
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
);
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
);
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();
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();
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
;
1270 p_vcomp_enter_critsect(&critsect
);
1274 p_vcomp_leave_critsect(critsect
);
1276 ok(critsect
!= NULL
, "expected critsect != NULL\n");
1278 EnterCriticalSection(critsect
);
1282 LeaveCriticalSection(critsect
);
1285 static void test_vcomp_enter_critsect(void)
1287 int max_threads
= pomp_get_max_threads();
1293 ok(a
== 2, "expected a == 2, got %d\n", a
);
1295 for (i
= 1; i
<= 4; i
++)
1297 pomp_set_num_threads(i
);
1300 p_vcomp_fork(TRUE
, 1, critsect_cb
, &a
);
1301 ok(a
== 2 * i
, "expected a == %d, got %d\n", 2 * i
, a
);
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)
1318 static void test_omp_init_lock(void)
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
);
1340 ok(ret
== 1, "expected ret == 1, got %d\n", 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
;
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
);
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)
1396 void (CDECL
*func
)(int *, int);
1397 int v1
, v2
, expected
;
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 },
1419 void (CDECL
*func
)(unsigned int *, unsigned int);
1420 unsigned int v1
, v2
, expected
;
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 },
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)
1450 void (CDECL
*func
)(float *, float);
1451 float v1
, v2
, expected
;
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 },
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)
1475 void (CDECL
*func
)(double *, double);
1476 double v1
, v2
, expected
;
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 },
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
);
1501 test_omp_get_num_threads(FALSE
);
1502 test_omp_get_num_threads(TRUE
);
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();
1512 test_omp_init_lock();
1513 test_omp_init_nest_lock();
1514 test_atomic_integer32();
1515 test_atomic_float();
1516 test_atomic_double();