mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / vcomp110 / tests / vcomp110.c
blobe0be668dffdea6e1b98e35ae345cad738811ff1d
1 /*
2 * Unit test suite for vcomp110
4 * Copyright 2021 Paul Gofman for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include "wine/test.h"
24 static HMODULE vcomp_handle;
26 static void (WINAPIV *pC2VectParallel)(int start, int end, int step, BOOL end_included, int thread_count,
27 BOOL dynamic_distribution, void *function, int nargs, ...);
28 static int (CDECL *p_vcomp_get_thread_num)(void);
29 static int (CDECL *pomp_get_num_threads)(void);
30 static void (CDECL *pomp_set_num_threads)(int num_threads);
31 static void (CDECL *p_vcomp_set_num_threads)(int num_threads);
33 #define VCOMP_GET_PROC(func) \
34 do \
35 { \
36 p ## func = (void *)GetProcAddress(vcomp_handle, #func); \
37 if (!p ## func) trace("Failed to get address for %s\n", #func); \
38 } \
39 while (0)
41 static BOOL init_vcomp(void)
43 vcomp_handle = LoadLibraryA("vcomp110.dll");
44 if (!vcomp_handle)
46 win_skip("vcomp110.dll is not installed.\n");
47 return FALSE;
50 VCOMP_GET_PROC(C2VectParallel);
51 VCOMP_GET_PROC(_vcomp_get_thread_num);
52 VCOMP_GET_PROC(omp_get_num_threads);
53 VCOMP_GET_PROC(omp_set_num_threads);
54 VCOMP_GET_PROC(_vcomp_set_num_threads);
56 return TRUE;
59 #define TEST_C2VECTPARALLEL_MAX_THREADS 256
60 #define TEST_C2VECTPARALLEL_MAX_VALUES 256
61 #define TEST_C2VECTPARALLEL_MAX_CALLS 256
63 struct C2VectParallel_test_data
65 int start;
66 int end;
67 int step;
68 BOOL end_included;
69 int thread_count;
70 unsigned int expected_call_count;
71 unsigned int expected_dynamic_call_count;
74 static volatile LONG test_C2VectParallel_call_count;
76 static void CDECL test_C2VectParallel_payload(int start, int end, void *test_parameter,
77 const struct C2VectParallel_test_data *test, unsigned int test_index, BOOL dynamic_distribution)
79 int thread_count = test->thread_count ? test->thread_count : 5;
80 int thread = p_vcomp_get_thread_num();
81 int expected_start, expected_end;
82 int omp_num_threads;
83 int step_sign;
85 step_sign = test->step > 0 ? 1 : -1;
87 omp_num_threads = pomp_get_num_threads();
89 InterlockedIncrement(&test_C2VectParallel_call_count);
91 if ((step_sign > 0 && test->end < test->start) || (step_sign < 0 && test->end > test->start)
92 || (test->end - test->start) / test->step < 2)
94 ok(omp_num_threads == 1, "Got unexpected omp_num_threads %u, thread_count %u, test %u.\n",
95 omp_num_threads, thread_count, test_index);
96 ok(!thread, "Got unexpected thread %d, test %u.\n", thread, test_index);
97 ok(start == test->start, "Got unexpected start %d, expected %d, thread %d, test %u.\n",
98 start, test->start, thread, test_index);
99 ok(end == test->end, "Got unexpected end %d, expected %d, thread %d, test %u.\n",
100 end, test->end, thread, test_index);
101 return;
104 ok(thread_count == omp_num_threads, "Got unexpected omp_num_threads %u, thread_count %u, test %u.\n",
105 omp_num_threads, thread_count, test_index);
107 ok(test_parameter == (void *)0xdeadbeef, "Got unexpected test_parameter %p.\n", test_parameter);
109 if (dynamic_distribution)
111 unsigned int remaining_count;
112 unsigned int loop_count = 0;
114 expected_start = test->start;
117 ++loop_count;
118 remaining_count = test->end - expected_start + test->step - step_sign * !test->end_included;
119 if (test->step < 0)
120 remaining_count = (unsigned int)-remaining_count / -test->step;
121 else
122 remaining_count /= test->step;
124 expected_end = expected_start + (remaining_count + thread_count - 1) / thread_count * test->step
125 + step_sign * !test->end_included;
127 if ((expected_end - test->end) * step_sign > 0)
128 expected_end = test->end;
129 else
130 expected_end -= test->step;
132 if (expected_start == start)
133 break;
135 expected_start = expected_end - step_sign * !test->end_included + test->step;
137 while (loop_count < 100);
138 ok(loop_count < 100, "Could not match start %d after %u iterations, test %u.\n",
139 start, loop_count, test_index);
141 else
143 unsigned int step_count, steps_per_call, remainder;
145 step_count = test->end - test->start + test->step - step_sign * !test->end_included;
146 if (test->step < 0)
147 step_count = (unsigned int)-step_count / -test->step;
148 else
149 step_count /= test->step;
151 steps_per_call = step_count / thread_count;
152 remainder = step_count % thread_count;
154 if (thread < remainder)
156 expected_start = thread * (steps_per_call + 1);
157 expected_end = expected_start + steps_per_call + 1;
159 else if (thread < step_count)
161 expected_start = remainder + steps_per_call * thread;
162 expected_end = expected_start + steps_per_call;
164 else
166 expected_start = expected_end = 0;
169 expected_start = test->start + expected_start * test->step;
170 expected_end = test->start + expected_end * test->step;
172 expected_end -= test->step;
173 if (!test->end_included)
174 expected_end += step_sign;
177 ok(start == expected_start, "Got unexpected start %d, expected %d, thread %d, test %u.\n",
178 start, expected_start, thread, test_index);
179 ok(end == expected_end, "Got unexpected end %d, expected %d, start %d, thread %d, dynamic %#x, test %u.\n",
180 end, expected_end, start, thread, dynamic_distribution, test_index);
183 #if 0
184 static void CDECL test_C2VectParallel_single_argument(int start)
186 ok(0, "Should not get here.\n");
188 #endif
190 static void test_C2VectParallel(void)
192 static const struct C2VectParallel_test_data tests[] =
194 {28, 28, 1, 0, 6, 1, 1},
195 {28, 28, 1, 1, 6, 1, 1},
196 {28, 29, 1, 0, 6, 1, 1},
197 {28, 29, 1, 1, 6, 1, 1},
199 /* Native generates calls from excessive threads with empty range here. */
200 {28, 30, 1, 0, 6, 6, 2},
201 {28, 31, 1, 0, 6, 6, 3},
202 {28, 33, 1, 0, 6, 6, 5},
203 {0, -2, -1, 0, 3, 3, 2},
205 /* But not in such cases. */
206 {28, 30, 1, 1, 6, 3, 3},
207 {28, 31, 2, 0, 6, 1, 1},
208 {28, 32, 2, 0, 6, 2, 2},
210 {28, 57, 1, 0, 6, 6, 13},
211 {28, 57, 1, 1, 6, 6, 13},
212 {28, 57, 4, 1, 6, 6, 7},
213 {28, 36, 4, 0, 6, 2, 2},
214 {28, 36, 4, 1, 6, 3, 3},
215 {36, 28, 4, 0, 6, 1, 1},
216 {36, 28, 4, 1, 6, 1, 1},
217 {57, 28, -1, 0, 6, 6, 13},
218 {57, 28, -1, 1, 6, 6, 13},
219 {36, 28, -4, 0, 6, 2, 2},
220 {36, 28, -4, 1, 6, 3, 3},
221 {28, 57, 1, 0, 0, 5, 11},
222 {-10, -2, 2, 1, 2, 2, 3},
223 {0x7ffffffd, 0x7fffffff, 1, 1, 2, 2, 2},
224 {-1, 0x7fffffff, 0x10000000, 1, 2, 1, 1},
225 {0, 0x7fffffff, 1, 0, 2, 2, 31},
226 {0, 0x7fffffff, 1, 1, 2, 2, 32},
227 {-10000, 0x7fffffff, 1, 1, 2, 1, 1},
228 {-10000, 0x7fffffff, -1, 1, 2, 1, 1},
229 {-10000, 0x7fffffff, 2, 1, 2, 1, 1},
230 {-10000, 0x7ffffff0, 2, 1, 2, 1, 1},
231 {-10000, 0x7fffffff - 10000, 1, 0, 1, 1, 1},
232 {-10000, 0x7fffffff - 10000, 1, 1, 1, 1, 1},
233 {-10000, 0x7fffffff - 10000, 1, 0, 2, 2, 31},
234 {-10000, 0x7fffffff - 10000, 1, 1, 2, 2, 32},
235 {-10000, 0x7fffffff - 10000, 2, 0, 2, 2, 31},
236 {-10000, 0x7fffffff - 10000, 2, 1, 2, 2, 31},
237 {0x80000001, 0, 2, 0, 3, 3, 51},
238 {0x80000001, 0, 2, 1, 3, 3, 51},
239 {0x80000000, 0x7fffffff, 1, 0, 3, 1, 1},
240 {0x80000000, 0x7fffffff, 1, 1, 3, 1, 1},
241 {0x80000000, 0x7fffffff, 2, 0, 3, 1, 1},
242 {0x80000000, 0x7fffffff, 2, 1, 3, 1, 1},
243 {0x80000001, 1, 1, 0, 3, 1, 1},
244 {0x80000001, 1, 1, 1, 3, 1, 1},
245 {0x80000001, 0, 1, 0, 3, 3, 52},
246 {0x80000001, 0, 1, 1, 3, 3, 52},
247 {28, 28, 1, 0, -1, 1, 1},
248 #if 0
249 /* Results in division by zero on Windows. */
250 {28, 57, 0, 0, 6, 6},
251 #endif
253 int num_threads;
254 unsigned int i;
256 pomp_set_num_threads(5);
257 p_vcomp_set_num_threads(3);
258 num_threads = pomp_get_num_threads();
259 ok(num_threads == 1, "Got unexpected num_threads %u.\n", num_threads);
261 #if 0
262 /* Results in stack overflow on Windows. */
263 pC2VectParallel(28, 57, 1, 0, 2, FALSE, test_C2VectParallel_single_argument, 1);
264 #endif
266 for (i = 0; i < ARRAY_SIZE(tests); ++i)
268 const struct C2VectParallel_test_data *test = &tests[i];
270 test_C2VectParallel_call_count = 0;
271 pC2VectParallel(test->start, test->end, test->step, test->end_included, test->thread_count,
272 FALSE, test_C2VectParallel_payload, 6, (void *)0xdeadbeef, test, i, FALSE);
273 ok(test_C2VectParallel_call_count == test->expected_call_count,
274 "Got unexpected call count %u, expected %u, test %u.\n",
275 test_C2VectParallel_call_count, test->expected_call_count, i);
277 test_C2VectParallel_call_count = 0;
278 pC2VectParallel(test->start, test->end, test->step, test->end_included, test->thread_count,
279 ~0u, test_C2VectParallel_payload, 6, (void *)0xdeadbeef, test, i, TRUE);
280 ok(test_C2VectParallel_call_count == test->expected_dynamic_call_count,
281 "Got unexpected call count %u, expected %u, test %u.\n",
282 test_C2VectParallel_call_count, test->expected_dynamic_call_count, i);
286 START_TEST(vcomp110)
288 if (!init_vcomp())
289 return;
291 test_C2VectParallel();