vcomp-Functions: Update vcomp patches and add various improvements.

This commit is contained in:
Sebastian Lackner 2015-07-19 01:07:16 +02:00
parent c1c337b07c
commit 679a5cef17
14 changed files with 1495 additions and 1012 deletions

View File

@ -4485,19 +4485,25 @@ fi
# | dlls/vcomp90/vcomp90.spec
# |
if test "$enable_vcomp_Functions" -eq 1; then
patch_apply vcomp-Functions/0001-vcomp-Implement-_vcomp_for_static_simple_init-and-_v.patch
patch_apply vcomp-Functions/0002-vcomp-tests-Add-tests-for-_vcomp_for_static_simple_i.patch
patch_apply vcomp-Functions/0003-vcomp-Implement-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0004-vcomp-tests-Add-tests-for-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0005-vcomp-Implement-omp_in_parallel.patch
patch_apply vcomp-Functions/0006-vcomp-Implement-_vcomp_for_dynamic_init-and-_vcomp_f.patch
patch_apply vcomp-Functions/0001-vcomp-Split-team-data-and-task-data.patch
patch_apply vcomp-Functions/0002-vcomp-Fix-handling-of-_vcomp_fork-with-ifval-FALSE.patch
patch_apply vcomp-Functions/0003-vcomp-Implement-omp_in_parallel-and-add-tests.patch
patch_apply vcomp-Functions/0004-vcomp-Implement-_vcomp_for_static_simple_init-and-_v.patch
patch_apply vcomp-Functions/0005-vcomp-tests-Add-tests-for-_vcomp_for_static_simple_i.patch
patch_apply vcomp-Functions/0006-vcomp-Implement-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0007-vcomp-tests-Add-tests-for-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0008-vcomp-Implement-_vcomp_for_dynamic_init-and-_vcomp_f.patch
patch_apply vcomp-Functions/0009-vcomp-tests-Add-tests-for-_vcomp_for_dynamic_init.patch
(
echo '+ { "Sebastian Lackner", "vcomp: Split team data and task data.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Fix handling of _vcomp_fork with ifval == FALSE.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement omp_in_parallel and add tests.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_for_static_simple_init and _vcomp_for_static_end.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp/tests: Add tests for _vcomp_for_static_simple_init.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_for_static_init.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp/tests: Add tests for _vcomp_for_static_init.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement omp_in_parallel.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next and add tests.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp/tests: Add tests for _vcomp_for_dynamic_init.", 1 },';
) >> "$patchlist"
fi

View File

@ -0,0 +1,192 @@
From 52ef17d8550f05778f548cc01fce2a0eaa3b223b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 18 Jul 2015 17:22:01 +0200
Subject: vcomp: Split team data and task data.
---
dlls/vcomp/main.c | 47 ++++++++++++++++++++++++++++++++++-------------
dlls/vcomp/tests/vcomp.c | 20 ++++++++++++++++++++
2 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 0f8a272..8866b15 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -52,6 +52,7 @@ static RTL_CRITICAL_SECTION vcomp_section = { &critsect_debug, -1, 0, 0, 0, 0 };
struct vcomp_thread_data
{
struct vcomp_team_data *team;
+ struct vcomp_task_data *task;
int thread_num;
int fork_threads;
@@ -77,7 +78,10 @@ struct vcomp_team_data
/* barrier */
unsigned int barrier;
int barrier_count;
+};
+struct vcomp_task_data
+{
/* section */
unsigned int section;
int num_sections;
@@ -177,20 +181,32 @@ static inline void vcomp_set_thread_data(struct vcomp_thread_data *thread_data)
TlsSetValue(vcomp_context_tls, thread_data);
}
+struct vcomp_thread_and_task_data
+{
+ struct vcomp_thread_data thread;
+ struct vcomp_task_data task;
+};
+
static struct vcomp_thread_data *vcomp_init_thread_data(void)
{
struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_task_data *task_data;
if (thread_data) return thread_data;
- if (!(thread_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*thread_data))))
+ if (!(thread_data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct vcomp_thread_and_task_data))))
{
ERR("could not create thread data\n");
ExitProcess(1);
}
+ task_data = &((struct vcomp_thread_and_task_data *)thread_data)->task;
+ task_data->section = 0;
+
thread_data->team = NULL;
+ thread_data->task = task_data;
thread_data->thread_num = 0;
thread_data->fork_threads = 0;
+ thread_data->section = 1;
vcomp_set_thread_data(thread_data);
return thread_data;
@@ -311,35 +327,35 @@ void CDECL _vcomp_single_end(void)
void CDECL _vcomp_sections_init(int n)
{
- struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
- struct vcomp_team_data *team_data = thread_data->team;
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_task_data *task_data = thread_data->task;
TRACE("(%d)\n", n);
EnterCriticalSection(&vcomp_section);
thread_data->section++;
- if ((int)(thread_data->section - team_data->section) > 0)
+ if ((int)(thread_data->section - task_data->section) > 0)
{
- team_data->section = thread_data->section;
- team_data->num_sections = n;
- team_data->section_index = 0;
+ task_data->section = thread_data->section;
+ task_data->num_sections = n;
+ task_data->section_index = 0;
}
LeaveCriticalSection(&vcomp_section);
}
int CDECL _vcomp_sections_next(void)
{
- struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
- struct vcomp_team_data *team_data = thread_data->team;
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_task_data *task_data = thread_data->task;
int i = -1;
TRACE("()\n");
EnterCriticalSection(&vcomp_section);
- if (thread_data->section == team_data->section &&
- team_data->section_index != team_data->num_sections)
+ if (thread_data->section == task_data->section &&
+ task_data->section_index != task_data->num_sections)
{
- i = team_data->section_index++;
+ i = task_data->section_index++;
}
LeaveCriticalSection(&vcomp_section);
return i;
@@ -391,6 +407,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
struct vcomp_thread_data *prev_thread_data = vcomp_init_thread_data();
struct vcomp_thread_data thread_data;
struct vcomp_team_data team_data;
+ struct vcomp_task_data task_data;
int num_threads;
TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
@@ -412,9 +429,11 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
__ms_va_start(team_data.valist, wrapper);
team_data.barrier = 0;
team_data.barrier_count = 0;
- team_data.section = 0;
+
+ task_data.section = 0;
thread_data.team = &team_data;
+ thread_data.task = &task_data;
thread_data.thread_num = 0;
thread_data.fork_threads = 0;
thread_data.section = 1;
@@ -431,6 +450,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
{
struct vcomp_thread_data *data = LIST_ENTRY(ptr, struct vcomp_thread_data, entry);
data->team = &team_data;
+ data->task = &task_data;
data->thread_num = team_data.num_threads++;
data->fork_threads = 0;
data->section = 1;
@@ -450,6 +470,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
if (!data) break;
data->team = &team_data;
+ data->task = &task_data;
data->thread_num = team_data.num_threads;
data->fork_threads = 0;
data->section = 1;
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index c433991..a933a4e 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -378,6 +378,20 @@ static void test_vcomp_sections_init(void)
int max_threads = pomp_get_max_threads();
int i;
+if (0)
+{
+ /* calling _vcomp_sections_next without prior _vcomp_sections_init
+ * returns uninitialized memory on Windows. */
+ i = p_vcomp_sections_next();
+ ok(i == -1, "expected -1, got %d\n", i);
+}
+
+ a = b = c = 0;
+ section_cb(&a, &b, &c);
+ ok(a == 20, "expected a = 20, got %d\n", a);
+ ok(b == 30, "expected b = 30, got %d\n", b);
+ ok(c == 40, "expected c = 40, got %d\n", c);
+
for (i = 1; i <= 4; i++)
{
pomp_set_num_threads(i);
@@ -387,6 +401,12 @@ static void test_vcomp_sections_init(void)
ok(a == 20, "expected a = 20, got %d\n", a);
ok(b == 30, "expected b = 30, got %d\n", b);
ok(c == 40, "expected c = 40, got %d\n", c);
+
+ a = b = c = 0;
+ p_vcomp_fork(FALSE, 3, section_cb, &a, &b, &c);
+ ok(a == 20, "expected a = 20, got %d\n", a);
+ ok(b == 30, "expected b = 30, got %d\n", b);
+ ok(c == 40, "expected c = 40, got %d\n", c);
}
pomp_set_num_threads(max_threads);
--
2.4.5

View File

@ -0,0 +1,122 @@
From fea70f187f3f04cfecd4c38014d51ea6a29d53c6 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 18 Jul 2015 18:00:45 +0200
Subject: vcomp: Fix handling of _vcomp_fork with ifval == FALSE.
Nested forks are still possible in this case, when it is not running inside
of a parallel block.
---
dlls/vcomp/main.c | 10 ++++++++--
dlls/vcomp/tests/vcomp.c | 23 ++++++++++++++++++++---
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 8866b15..8526d86 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -54,6 +54,7 @@ struct vcomp_thread_data
struct vcomp_team_data *team;
struct vcomp_task_data *task;
int thread_num;
+ BOOL parallel;
int fork_threads;
/* only used for concurrent tasks */
@@ -205,6 +206,7 @@ static struct vcomp_thread_data *vcomp_init_thread_data(void)
thread_data->team = NULL;
thread_data->task = task_data;
thread_data->thread_num = 0;
+ thread_data->parallel = FALSE;
thread_data->fork_threads = 0;
thread_data->section = 1;
@@ -412,10 +414,11 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
+ if (prev_thread_data->parallel && !vcomp_nested_fork)
+ ifval = FALSE;
+
if (!ifval)
num_threads = 1;
- else if (prev_thread_data->team && !vcomp_nested_fork)
- num_threads = 1;
else if (prev_thread_data->fork_threads)
num_threads = prev_thread_data->fork_threads;
else
@@ -435,6 +438,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
thread_data.team = &team_data;
thread_data.task = &task_data;
thread_data.thread_num = 0;
+ thread_data.parallel = ifval || prev_thread_data->parallel;
thread_data.fork_threads = 0;
thread_data.section = 1;
list_init(&thread_data.entry);
@@ -452,6 +456,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->team = &team_data;
data->task = &task_data;
data->thread_num = team_data.num_threads++;
+ data->parallel = thread_data.parallel;
data->fork_threads = 0;
data->section = 1;
list_remove(&data->entry);
@@ -472,6 +477,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->team = &team_data;
data->task = &task_data;
data->thread_num = team_data.num_threads;
+ data->parallel = thread_data.parallel;
data->fork_threads = 0;
data->section = 1;
InitializeConditionVariable(&data->cond);
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index a933a4e..4dae41f 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -208,17 +208,21 @@ static void CDECL num_threads_cb(BOOL nested, int nested_threads, LONG *count)
thread_count = 0;
p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
if (nested)
- ok(thread_count == nested_threads, "expected %d thread, got %d\n", nested_threads, thread_count);
+ ok(thread_count == nested_threads, "expected %d threads, got %d\n", nested_threads, thread_count);
else
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+ thread_count = 0;
+ p_vcomp_fork(FALSE, 1, num_threads_cb2, &thread_count);
+ ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+
p_vcomp_set_num_threads(4);
thread_count = 0;
p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
if (nested)
- ok(thread_count == 4 , "expected 4 thread, got %d\n", thread_count);
+ ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
else
- ok(thread_count == 1 , "expected 1 thread, got %d\n", thread_count);
+ ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
}
static void test_omp_get_num_threads(BOOL nested)
@@ -241,6 +245,19 @@ static void test_omp_get_num_threads(BOOL nested)
p_vcomp_fork(TRUE, 3, num_threads_cb, nested, max_threads, &thread_count);
ok(thread_count == max_threads, "expected %d threads, got %d\n", max_threads, thread_count);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(FALSE, 3, num_threads_cb, TRUE, max_threads, &thread_count);
+ ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+
+ pomp_set_num_threads(1);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 1, &thread_count);
+ ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+
pomp_set_num_threads(2);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
--
2.4.5

View File

@ -1,264 +0,0 @@
From abd9917d138e9e7c4f4fa9c13c15c44072d604f8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 05:12:39 +0200
Subject: vcomp/tests: Add tests for _vcomp_for_static_simple_init.
---
dlls/vcomp/tests/vcomp.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 220 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index c433991..bba1fe3 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -32,6 +32,9 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
+static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
+ BOOL forward, unsigned int *begin, unsigned int *end);
static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
static void (CDECL *p_vcomp_sections_init)(int n);
static int (CDECL *p_vcomp_sections_next)(void);
@@ -170,6 +173,8 @@ static BOOL init_vcomp(void)
}
VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_for_static_end);
+ VCOMP_GET_PROC(_vcomp_for_static_simple_init);
VCOMP_GET_PROC(_vcomp_fork);
VCOMP_GET_PROC(_vcomp_sections_init);
VCOMP_GET_PROC(_vcomp_sections_next);
@@ -392,6 +397,220 @@ static void test_vcomp_sections_init(void)
pomp_set_num_threads(max_threads);
}
+static void CDECL _test_vcomp_for_static_simple_init(void)
+{
+ static const struct
+ {
+ unsigned int first;
+ unsigned int last;
+ int step;
+ BOOL forward;
+ }
+ tests[] =
+ {
+ /* loop forward, step 1 */
+ { 0, 0, 1, TRUE },
+ { 0, 1, 1, TRUE },
+ { 0, 2, 1, TRUE },
+ { 0, 3, 1, TRUE },
+ { 0, 0x10000000, 1, TRUE },
+ { 0, 0x20000000, 1, TRUE },
+ { 0, 0x40000000, 1, TRUE },
+ { 0, 0x80000000, 1, TRUE },
+
+ /* loop forward, varying step */
+ { 0, 100, 1, TRUE },
+ { 0, 100, 5, TRUE },
+ { 0, 100, 10, TRUE },
+ { 0, 100, 25, TRUE },
+ { 0, 100, 50, TRUE },
+ { 0, 100, 75, TRUE },
+ { 0, 100, 100, TRUE },
+ { 0, 100, 150, TRUE },
+
+ /* empty loop forward, varying step */
+ { 50, 50, 3, TRUE },
+ { 50, 50, 2, TRUE },
+ { 50, 50, 1, TRUE },
+ { 50, 50, 0, TRUE },
+ { 50, 50, -1, TRUE },
+ { 50, 50, -2, TRUE },
+ { 50, 50, -3, TRUE },
+
+ /* loop backward, step 1 */
+ { 0, 0, 1, FALSE },
+ { 1, 0, 1, FALSE },
+ { 2, 0, 1, FALSE },
+ { 3, 0, 1, FALSE },
+ { 0x10000000, 0, 1, FALSE },
+ { 0x20000000, 0, 1, FALSE },
+ { 0x40000000, 0, 1, FALSE },
+ { 0x80000000, 0, 1, FALSE },
+
+ /* loop backward, varying step */
+ { 100, 0, 1, FALSE },
+ { 100, 0, 5, FALSE },
+ { 100, 0, 10, FALSE },
+ { 100, 0, 25, FALSE },
+ { 100, 0, 50, FALSE },
+ { 100, 0, 75, FALSE },
+ { 100, 0, 100, FALSE },
+ { 100, 0, 150, FALSE },
+
+ /* empty loop backward, varying step */
+ { 50, 50, 3, FALSE },
+ { 50, 50, 2, FALSE },
+ { 50, 50, 1, FALSE },
+ { 50, 50, 0, FALSE },
+ { 50, 50, -1, FALSE },
+ { 50, 50, -2, FALSE },
+ { 50, 50, -3, FALSE },
+
+ /* test overflow in forward loop */
+ { 0, 0, 1, TRUE },
+ { 1, 0, 1, TRUE },
+ { 2, 0, 1, TRUE },
+ { 3, 0, 1, TRUE },
+ { 0x10000000, 0, 1, TRUE },
+ { 0x20000000, 0, 1, TRUE },
+ { 0x40000000, 0, 1, TRUE },
+ { 0x80000000, 0, 1, TRUE },
+
+ { 100, 0, 1, TRUE },
+ { 100, 0, 5, TRUE },
+ { 100, 0, 10, TRUE },
+ { 100, 0, 25, TRUE },
+ { 100, 0, 50, TRUE },
+ { 100, 0, 75, TRUE },
+ { 100, 0, 100, TRUE },
+ { 100, 0, 150, TRUE },
+
+ /* test overflow in backward loop */
+ { 0, 0, 1, FALSE },
+ { 0, 1, 1, FALSE },
+ { 0, 2, 1, FALSE },
+ { 0, 3, 1, FALSE },
+ { 0, 0x10000000, 1, FALSE },
+ { 0, 0x20000000, 1, FALSE },
+ { 0, 0x40000000, 1, FALSE },
+ { 0, 0x80000000, 1, FALSE },
+
+ { 0, 100, 1, FALSE },
+ { 0, 100, 5, FALSE },
+ { 0, 100, 10, FALSE },
+ { 0, 100, 25, FALSE },
+ { 0, 100, 50, FALSE },
+ { 0, 100, 75, FALSE },
+ { 0, 100, 100, FALSE },
+ { 0, 100, 150, FALSE },
+ };
+ unsigned int begin, end, expected_begin, expected_end;
+ int thread_num = pomp_get_thread_num();
+ int num_threads = pomp_get_num_threads();
+ int i;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ {
+ unsigned int iterations, per_thread, remaining;
+ DWORD64 first = tests[i].first;
+ DWORD64 last = tests[i].last;
+ int step = tests[i].step;
+
+ if (num_threads == 1)
+ {
+ expected_begin = first;
+ expected_end = last;
+ goto done;
+ }
+
+ if (tests[i].forward)
+ {
+ if (tests[i].step <= 0)
+ {
+ expected_begin = 0;
+ expected_end = -1;
+ goto done;
+ }
+
+ if (last < first)
+ last += 0x100000000;
+
+ iterations = 1 + (last - first) / step;
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ per_thread++;
+ else if (per_thread)
+ first += remaining * step;
+ else
+ {
+ expected_begin = first;
+ expected_end = first - step;
+ goto done;
+ }
+
+ expected_begin = first + per_thread * thread_num * step;
+ expected_end = expected_begin + (per_thread - 1) * step;
+ }
+ else
+ {
+ if (tests[i].step <= 0)
+ {
+ expected_begin = 0;
+ expected_end = 1;
+ goto done;
+ }
+
+ if (first < last)
+ first += 0x100000000;
+
+ iterations = 1 + (first - last) / step;
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ per_thread++;
+ else if (per_thread)
+ first -= remaining * step;
+ else
+ {
+ expected_begin = first;
+ expected_end = first + step;
+ goto done;
+ }
+
+ expected_begin = first - per_thread * thread_num * step;
+ expected_end = expected_begin - (per_thread - 1) * step;
+ }
+
+done:
+ begin = end = 0xdeadbeef;
+ p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step,
+ tests[i].forward, &begin, &end);
+
+ ok(begin == expected_begin, "%d:%d/%d: expected begin = %u, got %u\n",
+ i, thread_num, num_threads, expected_begin, end);
+ ok(end == expected_end, "%d:%d/%d: expected end = %u, got %u\n",
+ i, thread_num, num_threads, expected_end, end);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+ }
+}
+
+static void test_vcomp_for_static_simple_init(void)
+{
+ int i;
+
+ for (i = 1; i <= 4; i++)
+ {
+ trace("Running tests with %d threads\n", i);
+ pomp_set_num_threads(i);
+ p_vcomp_fork(TRUE, 0, _test_vcomp_for_static_simple_init);
+ }
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -401,6 +620,7 @@ START_TEST(vcomp)
test_omp_get_num_threads(TRUE);
test_vcomp_fork();
test_vcomp_sections_init();
+ test_vcomp_for_static_simple_init();
release_vcomp();
}
--
2.4.5

View File

@ -0,0 +1,244 @@
From 8f71eb6dce0bf634c75a5dc7a5137f45594a530a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 18 Jul 2015 23:39:01 +0200
Subject: vcomp: Implement omp_in_parallel and add tests.
---
dlls/vcomp/main.c | 6 +++++
dlls/vcomp/tests/vcomp.c | 59 ++++++++++++++++++++++++++++++++++-----------
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
5 files changed, 54 insertions(+), 17 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 8526d86..a17407c 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -363,6 +363,12 @@ int CDECL _vcomp_sections_next(void)
return i;
}
+BOOL CDECL omp_in_parallel(void)
+{
+ TRACE("()\n");
+ return vcomp_init_thread_data()->parallel;
+}
+
static DWORD WINAPI _vcomp_fork_worker(void *param)
{
struct vcomp_thread_data *thread_data = param;
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 4dae41f..6b22d48 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -40,6 +40,7 @@ static int (CDECL *pomp_get_max_threads)(void);
static int (CDECL *pomp_get_nested)(void);
static int (CDECL *pomp_get_num_threads)(void);
static int (CDECL *pomp_get_thread_num)(void);
+static BOOL (CDECL *pomp_in_parallel)(void);
static void (CDECL *pomp_set_nested)(int nested);
static void (CDECL *pomp_set_num_threads)(int num_threads);
@@ -178,6 +179,7 @@ static BOOL init_vcomp(void)
VCOMP_GET_PROC(omp_get_nested);
VCOMP_GET_PROC(omp_get_num_threads);
VCOMP_GET_PROC(omp_get_thread_num);
+ VCOMP_GET_PROC(omp_in_parallel);
VCOMP_GET_PROC(omp_set_nested);
VCOMP_GET_PROC(omp_set_num_threads);
@@ -186,15 +188,19 @@ static BOOL init_vcomp(void)
#undef VCOMP_GET_PROC
-static void CDECL num_threads_cb2(LONG *count)
+static void CDECL num_threads_cb2(BOOL parallel, LONG *count)
{
+ BOOL is_parallel = pomp_in_parallel();
+ ok(is_parallel == parallel, "expected %u, got %u\n", parallel, is_parallel);
+
InterlockedIncrement(count);
}
-static void CDECL num_threads_cb(BOOL nested, int nested_threads, LONG *count)
+static void CDECL num_threads_cb(BOOL nested, BOOL parallel, int nested_threads, LONG *count)
{
int num_threads, thread_num;
LONG thread_count;
+ BOOL is_parallel;
InterlockedIncrement(count);
p_vcomp_barrier();
@@ -205,30 +211,43 @@ static void CDECL num_threads_cb(BOOL nested, int nested_threads, LONG *count)
ok(thread_num >= 0 && thread_num < num_threads,
"expected thread_num in range [0, %d], got %d\n", num_threads - 1, thread_num);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == parallel, "expected %u, got %u\n", parallel, is_parallel);
+
thread_count = 0;
- p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
+ p_vcomp_fork(TRUE, 2, num_threads_cb2, TRUE, &thread_count);
if (nested)
ok(thread_count == nested_threads, "expected %d threads, got %d\n", nested_threads, thread_count);
else
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == parallel, "expected %u, got %u\n", parallel, is_parallel);
+
thread_count = 0;
- p_vcomp_fork(FALSE, 1, num_threads_cb2, &thread_count);
+ p_vcomp_fork(FALSE, 2, num_threads_cb2, parallel, &thread_count);
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == parallel, "expected %u, got %u\n", parallel, is_parallel);
+
p_vcomp_set_num_threads(4);
thread_count = 0;
- p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
+ p_vcomp_fork(TRUE, 2, num_threads_cb2, TRUE, &thread_count);
if (nested)
ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
else
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == parallel, "expected %u, got %u\n", parallel, is_parallel);
}
static void test_omp_get_num_threads(BOOL nested)
{
int is_nested, max_threads, num_threads, thread_num;
LONG thread_count;
+ BOOL is_parallel;
pomp_set_nested(nested);
is_nested = pomp_get_nested();
@@ -239,61 +258,73 @@ static void test_omp_get_num_threads(BOOL nested)
thread_num = pomp_get_thread_num();
ok(thread_num == 0, "expected thread_num == 0, got %d\n", thread_num);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == FALSE, "expected FALSE, got %u\n", is_parallel);
+
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, max_threads, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, max_threads, &thread_count);
ok(thread_count == max_threads, "expected %d threads, got %d\n", max_threads, thread_count);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == FALSE, "expected FALSE, got %u\n", is_parallel);
+
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(FALSE, 3, num_threads_cb, TRUE, max_threads, &thread_count);
+ p_vcomp_fork(FALSE, 4, num_threads_cb, TRUE, FALSE, max_threads, &thread_count);
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == FALSE, "expected FALSE, got %u\n", is_parallel);
+
pomp_set_num_threads(1);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 1, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 1, &thread_count);
ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+ is_parallel = pomp_in_parallel();
+ ok(is_parallel == FALSE, "expected FALSE, got %u\n", is_parallel);
+
pomp_set_num_threads(2);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 2, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 2, &thread_count);
ok(thread_count == 2, "expected 2 threads, got %d\n", thread_count);
pomp_set_num_threads(4);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
p_vcomp_set_num_threads(8);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
ok(thread_count == 8, "expected 8 threads, got %d\n", thread_count);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
p_vcomp_set_num_threads(0);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
pomp_set_num_threads(0);
num_threads = pomp_get_num_threads();
ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
thread_count = 0;
- p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ p_vcomp_fork(TRUE, 4, num_threads_cb, nested, TRUE, 4, &thread_count);
ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
pomp_set_num_threads(max_threads);
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index dfbd184..5a5b114 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num()
@ stub omp_get_wtick
@ cdecl omp_get_wtime()
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel()
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long)
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 6eb6ae5..debc5ff 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num() vcomp.omp_get_thread_num
@ stub omp_get_wtick
@ cdecl omp_get_wtime() vcomp.omp_get_wtime
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel() vcomp.omp_in_parallel
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long) vcomp.omp_set_dynamic
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 6eb6ae5..debc5ff 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num() vcomp.omp_get_thread_num
@ stub omp_get_wtick
@ cdecl omp_get_wtime() vcomp.omp_get_wtime
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel() vcomp.omp_in_parallel
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long) vcomp.omp_set_dynamic
--
2.4.5

View File

@ -1,36 +1,34 @@
From 3ebb9a8afbb3592c6988eb4b6cc2f0872fef45fb Mon Sep 17 00:00:00 2001
From a2e77ca2e3e956aaabaa5190a0e8cc822349f1a8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 18:59:41 +0200
Subject: vcomp: Implement _vcomp_for_static_simple_init and
_vcomp_for_static_end.
---
dlls/vcomp/main.c | 90 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 +-
dlls/vcomp100/vcomp100.spec | 4 +-
dlls/vcomp90/vcomp90.spec | 4 +-
4 files changed, 96 insertions(+), 6 deletions(-)
dlls/vcomp/main.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 ++--
dlls/vcomp100/vcomp100.spec | 4 ++--
dlls/vcomp90/vcomp90.spec | 4 ++--
4 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 0f8a272..7000e1b 100644
index a17407c..b647bb1 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -345,6 +345,96 @@ int CDECL _vcomp_sections_next(void)
@@ -363,6 +363,63 @@ int CDECL _vcomp_sections_next(void)
return i;
}
+void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last, int step, BOOL forward,
+ unsigned int *begin, unsigned int *end)
+void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last, int step,
+ BOOL increment, unsigned int *begin, unsigned int *end)
+{
+ unsigned int iterations, per_thread, remaining;
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations, per_thread, remaining;
+ DWORD num_threads, thread_num;
+ int num_threads = team_data ? team_data->num_threads : 1;
+ int thread_num = thread_data->thread_num;
+
+ TRACE("(%d, %d, %d, %d, %p, %p)\n", first, last, step, forward, begin, end);
+
+ num_threads = team_data->num_threads;
+ thread_num = thread_data->thread_num;
+ TRACE("(%u, %u, %d, %u, %p, %p)\n", first, last, step, increment, begin, end);
+
+ if (num_threads == 1)
+ {
@ -42,78 +40,47 @@ index 0f8a272..7000e1b 100644
+ if (step <= 0)
+ {
+ *begin = 0;
+ *end = forward ? -1 : 1;
+ *end = increment ? -1 : 1;
+ return;
+ }
+
+ if (forward)
+ {
+ DWORD64 last64 = last;
+ if (last64 < first)
+ last64 += 0x100000000;
+
+ iterations = 1 + (last64 - first) / step;
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ {
+ per_thread++;
+ }
+ else if (per_thread)
+ {
+ first += remaining * step;
+ }
+ else
+ {
+ *begin = first;
+ *end = first - step;
+ return;
+ }
+
+ *begin = first + per_thread * thread_num * step;
+ *end = *begin + (per_thread - 1) * step;
+ }
+ if (increment)
+ iterations = 1 + (last - first) / step;
+ else
+ {
+ DWORD first64 = first;
+ if (first64 < last)
+ first64 += 0x100000000;
+
+ iterations = 1 + (first64 - last) / step;
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ {
+ per_thread++;
+ }
+ else if (per_thread)
+ {
+ first64 -= remaining * step;
+ }
+ else
+ {
+ *begin = first64;
+ *end = first64 + step;
+ return;
+ }
+
+ *begin = first64 - per_thread * thread_num * step;
+ *end = *begin - (per_thread - 1) * step;
+ iterations = 1 + (first - last) / step;
+ step *= -1;
+ }
+
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ per_thread++;
+ else if (per_thread)
+ first += remaining * step;
+ else
+ {
+ *begin = first;
+ *end = first - step;
+ return;
+ }
+
+ *begin = first + per_thread * thread_num * step;
+ *end = *begin + (per_thread - 1) * step;
+}
+
+void CDECL _vcomp_for_static_end(void)
+{
+ TRACE("()\n");
+ /* nothing to do here */
+}
+
static DWORD WINAPI _vcomp_fork_worker(void *param)
BOOL CDECL omp_in_parallel(void)
{
struct vcomp_thread_data *thread_data = param;
TRACE("()\n");
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index dfbd184..51dc13c 100644
index 5a5b114..d6b8bf5 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -59,10 +59,10 @@
@ -130,7 +97,7 @@ index dfbd184..51dc13c 100644
@ varargs _vcomp_fork(long long ptr)
@ stub _vcomp_get_thread_num
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 6eb6ae5..c2c644a 100644
index debc5ff..a6933c8 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -59,10 +59,10 @@
@ -147,7 +114,7 @@ index 6eb6ae5..c2c644a 100644
@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 6eb6ae5..c2c644a 100644
index debc5ff..a6933c8 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -59,10 +59,10 @@

View File

@ -1,243 +0,0 @@
From 9d2c0d36fecd34e7b111fa342aa73315bc26342a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 06:08:08 +0200
Subject: vcomp/tests: Add tests for _vcomp_for_static_init.
---
dlls/vcomp/tests/vcomp.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 199 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index bba1fe3..8de4510b 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -33,6 +33,8 @@ static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
+ int *begin, int *end, int *next, int *lastchunk);
static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
BOOL forward, unsigned int *begin, unsigned int *end);
static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
@@ -174,6 +176,7 @@ static BOOL init_vcomp(void)
VCOMP_GET_PROC(_vcomp_barrier);
VCOMP_GET_PROC(_vcomp_for_static_end);
+ VCOMP_GET_PROC(_vcomp_for_static_init);
VCOMP_GET_PROC(_vcomp_for_static_simple_init);
VCOMP_GET_PROC(_vcomp_fork);
VCOMP_GET_PROC(_vcomp_sections_init);
@@ -611,6 +614,201 @@ static void test_vcomp_for_static_simple_init(void)
}
}
+static void CDECL _test_vcomp_for_static_init(void)
+{
+ static const struct
+ {
+ int first;
+ int last;
+ int step;
+ int chunksize;
+ }
+ tests[] =
+ {
+ /* loop forward, step 1 */
+ { 0, 0, 1, 1 },
+ { 0, 1, 1, 1 },
+ { 0, 2, 1, 1 },
+ { 0, 3, 1, 1 },
+ { 0, 0x10000000, 1, 1 },
+ { 0, 0x20000000, 1, 1 },
+ { 0, 0x40000000, 1, 1 },
+ { 0, (int)0x80000000, 1, 1 },
+
+ /* loop forward, varying step */
+ {0, 100, 1, 1},
+ {0, 100, 5, 1},
+ {0, 100, 10, 1},
+ {0, 100, 25, 1},
+ {0, 100, 50, 1},
+ {0, 100, 75, 1},
+ {0, 100, 100, 1},
+ {0, 100, 150, 1},
+
+ /* empty loop forward, varying step */
+ { 50, 50, 3, 1 },
+ { 50, 50, 2, 1 },
+ { 50, 50, 1, 1 },
+ /*{ 50, 50, 0, 1 }, - generates a division by zero exception */
+ { 50, 50, -1, 1 },
+ { 50, 50, -2, 1 },
+ { 50, 50, -3, 1 },
+
+ /* loop backwards, step 1 */
+ { 0, 0, 1, 1 },
+ { 1, 0, 1, 1 },
+ { 2, 0, 1, 1 },
+ { 3, 0, 1, 1 },
+ { 0x10000000, 0, 1, 1 },
+ { 0x20000000, 0, 1, 1 },
+ { 0x40000000, 0, 1, 1 },
+ { (int)0x80000000, 0, 1, 1 },
+
+ /* loop backwards, varying step */
+ {100, 0, 1, 1},
+ {100, 0, 5, 1},
+ {100, 0, 10, 1},
+ {100, 0, 25, 1},
+ {100, 0, 50, 1},
+ {100, 0, 75, 1},
+ {100, 0, 100, 1},
+ {100, 0, 150, 1},
+
+ /* loop forward, varying chunksize */
+ {0, 100, 1, 1},
+ {0, 100, 1, 5},
+ {0, 100, 1, 10},
+ {0, 100, 1, 25},
+ {0, 100, 1, 50},
+ {0, 100, 1, 75},
+ {0, 100, 1, 100},
+ {0, 100, 1, 150},
+
+ {0, 100, 7, 1},
+ {0, 100, 7, 5},
+ {0, 100, 7, 10},
+ {0, 100, 7, 25},
+ {0, 100, 7, 50},
+ {0, 100, 7, 75},
+ {0, 100, 7, 100},
+ {0, 100, 7, 150},
+
+ /* loop backwards, varying chunksize */
+ {100, 0, 1, 1},
+ {100, 0, 1, 5},
+ {100, 0, 1, 10},
+ {100, 0, 1, 25},
+ {100, 0, 1, 50},
+ {100, 0, 1, 75},
+ {100, 0, 1, 100},
+ {100, 0, 1, 150},
+
+ {100, 0, 7, 1},
+ {100, 0, 7, 5},
+ {100, 0, 7, 10},
+ {100, 0, 7, 25},
+ {100, 0, 7, 50},
+ {100, 0, 7, 75},
+ {100, 0, 7, 100},
+ {100, 0, 7, 150},
+
+ };
+ int begin, end, expected_begin, expected_end;
+ unsigned int loops, expected_loops;
+ int lastchunk, expected_lastchunk;
+ int chunksize, expected_chunksize;
+ int thread_num = pomp_get_thread_num();
+ int num_threads = pomp_get_num_threads();
+ int i;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ {
+ unsigned int iterations, num_chunks, per_thread, remaining;
+ int first = tests[i].first;
+ int last = tests[i].last;
+ int step = tests[i].step;
+ chunksize = tests[i].chunksize;
+
+ if (chunksize < 1)
+ chunksize = 1;
+
+ if (num_threads == 1 && chunksize > 1)
+ {
+ expected_loops = 1;
+ expected_begin = first;
+ expected_end = last;
+ expected_chunksize = chunksize;
+ expected_lastchunk = first;
+ }
+ else if (last > first)
+ {
+ iterations = 1 + (last - first) / step;
+ num_chunks = (iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+
+ expected_loops = per_thread + (thread_num < remaining);
+ expected_begin = first + thread_num * chunksize * step;
+ expected_end = expected_begin + (chunksize - 1) * step;
+ expected_chunksize = chunksize * num_threads * step;
+ expected_lastchunk = first + (num_chunks - 1) * chunksize * step;
+
+ }
+ else if (last < first)
+ {
+ iterations = 1 + (first - last) / step;
+ num_chunks = (iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+
+ expected_loops = per_thread + (thread_num < remaining);
+ expected_begin = first - thread_num * chunksize * step;
+ expected_end = expected_begin - (chunksize - 1) * step;
+ expected_chunksize = - chunksize * num_threads * step;
+ expected_lastchunk = first - (num_chunks - 1) * chunksize * step;
+ }
+ else
+ {
+ expected_loops = (thread_num == 0);
+ expected_begin = first;
+ expected_end = last;
+ expected_chunksize = 0;
+ expected_lastchunk = first;
+ }
+
+ loops = begin = end = chunksize = lastchunk = 0xdeadbeef;
+ p_vcomp_for_static_init(tests[i].first, tests[i].last, tests[i].step, tests[i].chunksize,
+ &loops, &begin, &end, &chunksize, &lastchunk);
+
+ ok(loops == expected_loops, "%d:%d/%d: expected loops = %u, got %u\n",
+ i, thread_num, num_threads, expected_loops, loops);
+ ok(begin == expected_begin || broken(begin == 0xdeadbeef && first == last && thread_num > 0),
+ "%d:%d/%d: expected begin = %u, got %u\n", i, thread_num, num_threads, expected_begin, end);
+ ok(end == expected_end || broken(end == 0xdeadbeef && first == last && thread_num > 0),
+ "%d:%d/%d: expected end = %u, got %u\n", i, thread_num, num_threads, expected_end, end);
+ ok(chunksize == expected_chunksize || broken(chunksize == (int)0xdeadbeef && first == last) ||
+ broken(chunksize != expected_chunksize && num_threads == 1),
+ "%d:%d/%d: expected chunksize = %u, got %u\n", i, thread_num, num_threads, expected_chunksize, chunksize);
+ ok(lastchunk == expected_lastchunk || broken(lastchunk == 0xdeadbeef && first == last && thread_num > 0),
+ "%d:%d/%d: expected lastchunk = %u, got %u\n", i, thread_num, num_threads, expected_lastchunk, lastchunk);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+ }
+}
+
+static void test_vcomp_for_static_init(void)
+{
+ int i;
+
+ for (i = 1; i <= 4; i++)
+ {
+ trace("Running tests with %d threads\n", i);
+ pomp_set_num_threads(i);
+ p_vcomp_fork(TRUE, 0, _test_vcomp_for_static_init);
+ }
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -621,6 +819,7 @@ START_TEST(vcomp)
test_vcomp_fork();
test_vcomp_sections_init();
test_vcomp_for_static_simple_init();
+ test_vcomp_for_static_init();
release_vcomp();
}
--
2.4.5

View File

@ -1,71 +0,0 @@
From c9cf03f4ce4830885ee991ea8e8a5807532be6e5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 19:41:29 +0200
Subject: vcomp: Implement omp_in_parallel.
---
dlls/vcomp/main.c | 6 ++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index f09fdda..af6fe61 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -497,6 +497,12 @@ void CDECL _vcomp_for_static_end(void)
TRACE("()\n");
}
+int CDECL omp_in_parallel(void)
+{
+ TRACE("()\n");
+ return vcomp_init_thread_data()->team != NULL;
+}
+
static DWORD WINAPI _vcomp_fork_worker(void *param)
{
struct vcomp_thread_data *thread_data = param;
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 718f80e..7083ce4 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num()
@ stub omp_get_wtick
@ cdecl omp_get_wtime()
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel()
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long)
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index c0b3d98..56c7ae3 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num() vcomp.omp_get_thread_num
@ stub omp_get_wtick
@ cdecl omp_get_wtime() vcomp.omp_get_wtime
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel() vcomp.omp_in_parallel
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long) vcomp.omp_set_dynamic
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index c0b3d98..56c7ae3 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -98,7 +98,7 @@
@ cdecl omp_get_thread_num() vcomp.omp_get_thread_num
@ stub omp_get_wtick
@ cdecl omp_get_wtime() vcomp.omp_get_wtime
-@ stub omp_in_parallel
+@ cdecl omp_in_parallel() vcomp.omp_in_parallel
@ stub omp_init_lock
@ stub omp_init_nest_lock
@ cdecl omp_set_dynamic(long) vcomp.omp_set_dynamic
--
2.4.5

View File

@ -0,0 +1,217 @@
From fdcc5db8904f22d5fe4eb8ad393e371dd5026b31 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 18 Jul 2015 04:09:01 +0200
Subject: vcomp/tests: Add tests for _vcomp_for_static_simple_init.
---
dlls/vcomp/tests/vcomp.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 173 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 6b22d48..bab9f41 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -32,6 +32,9 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
+static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
+ BOOL increment, unsigned int *begin, unsigned int *end);
static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
static void (CDECL *p_vcomp_sections_init)(int n);
static int (CDECL *p_vcomp_sections_next)(void);
@@ -171,6 +174,8 @@ static BOOL init_vcomp(void)
}
VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_for_static_end);
+ VCOMP_GET_PROC(_vcomp_for_static_simple_init);
VCOMP_GET_PROC(_vcomp_fork);
VCOMP_GET_PROC(_vcomp_sections_init);
VCOMP_GET_PROC(_vcomp_sections_next);
@@ -460,6 +465,173 @@ if (0)
pomp_set_num_threads(max_threads);
}
+static void my_for_static_simple_init(unsigned int first, unsigned int last, int step,
+ BOOL increment, unsigned int *begin, unsigned int *end)
+{
+ unsigned int iterations, per_thread, remaining;
+ int num_threads = pomp_get_num_threads();
+ int thread_num = pomp_get_thread_num();
+
+ if (num_threads == 1)
+ {
+ *begin = first;
+ *end = last;
+ return;
+ }
+
+ if (step <= 0)
+ {
+ *begin = 0;
+ *end = increment ? -1 : 1;
+ return;
+ }
+
+ if (increment)
+ iterations = 1 + (last - first) / step;
+ else
+ {
+ iterations = 1 + (first - last) / step;
+ step *= -1;
+ }
+
+ per_thread = iterations / num_threads;
+ remaining = iterations - per_thread * num_threads;
+
+ if (thread_num < remaining)
+ per_thread++;
+ else if (per_thread)
+ first += remaining * step;
+ else
+ {
+ *begin = first;
+ *end = first - step;
+ return;
+ }
+
+ *begin = first + per_thread * thread_num * step;
+ *end = *begin + (per_thread - 1) * step;
+}
+
+
+static void CDECL for_static_simple_cb(void)
+{
+ static const struct
+ {
+ unsigned int first;
+ unsigned int last;
+ int step;
+ }
+ tests[] =
+ {
+ { 0, 0, 1 }, /* 0 */
+ { 0, 1, 1 },
+ { 0, 2, 1 },
+ { 0, 3, 1 },
+ { 0, 100, 0 },
+ { 0, 100, 1 },
+ { 0, 100, 2 },
+ { 0, 100, 3 },
+ { 0, 100, -1 },
+ { 0, 100, -2 },
+ { 0, 100, -3 }, /* 10 */
+ { 0, 100, 10 },
+ { 0, 100, 50 },
+ { 0, 100, 100 },
+ { 0, 100, 150 },
+ { 0, 0x80000000, 1 },
+ { 0, 0xfffffffe, 1 },
+ { 0, 0xffffffff, 1 },
+ { 50, 50, 0 },
+ { 50, 50, 1 },
+ { 50, 50, 2 }, /* 20 */
+ { 50, 50, 3 },
+ { 50, 50, -1 },
+ { 50, 50, -2 },
+ { 50, 50, -3 },
+ { 100, 200, 1 },
+ { 100, 200, 5 },
+ { 100, 200, 10 },
+ { 100, 200, 50 },
+ { 100, 200, 100 },
+ { 100, 200, 150 }, /* 30 */
+ };
+ int num_threads = pomp_get_num_threads();
+ int thread_num = pomp_get_thread_num();
+ int i;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ {
+ unsigned int my_begin, my_end, begin, end;
+
+ begin = end = 0xdeadbeef;
+ my_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, FALSE, &my_begin, &my_end);
+ p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, FALSE, &begin, &end);
+
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin = %u, got %u\n",
+ i, thread_num, num_threads, my_begin, end);
+ ok(end == my_end, "test %d, thread %d/%d: expected end = %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+
+ begin = end = 0xdeadbeef;
+ my_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, TRUE, &my_begin, &my_end);
+ p_vcomp_for_static_simple_init(tests[i].first, tests[i].last, tests[i].step, TRUE, &begin, &end);
+
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin = %u, got %u\n",
+ i, thread_num, num_threads, my_begin, end);
+ ok(end == my_end, "test %d, thread %d/%d: expected end = %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+
+ if (tests[i].first == tests[i].last) continue;
+
+ begin = end = 0xdeadbeef;
+ my_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, FALSE, &my_begin, &my_end);
+ p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, FALSE, &begin, &end);
+
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin = %u, got %u\n",
+ i, thread_num, num_threads, my_begin, end);
+ ok(end == my_end, "test %d, thread %d/%d: expected end = %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+
+ begin = end = 0xdeadbeef;
+ my_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, TRUE, &my_begin, &my_end);
+ p_vcomp_for_static_simple_init(tests[i].last, tests[i].first, tests[i].step, TRUE, &begin, &end);
+
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin = %u, got %u\n",
+ i, thread_num, num_threads, my_begin, end);
+ ok(end == my_end, "test %d, thread %d/%d: expected end = %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+ }
+}
+
+static void test_vcomp_for_static_simple_init(void)
+{
+ int max_threads = pomp_get_max_threads();
+ int i;
+
+ for_static_simple_cb();
+
+ for (i = 1; i <= 4; i++)
+ {
+ pomp_set_num_threads(i);
+ p_vcomp_fork(TRUE, 0, for_static_simple_cb);
+ p_vcomp_fork(FALSE, 0, for_static_simple_cb);
+ }
+
+ pomp_set_num_threads(max_threads);
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -469,6 +641,7 @@ START_TEST(vcomp)
test_omp_get_num_threads(TRUE);
test_vcomp_fork();
test_vcomp_sections_init();
+ test_vcomp_for_static_simple_init();
release_vcomp();
}
--
2.4.5

View File

@ -1,294 +0,0 @@
From 2884d2c0e05a7bf26fe340774fd3d6a29a1de416 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 23:28:31 +0200
Subject: vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next
and add tests.
---
dlls/vcomp/main.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/vcomp.c | 53 ++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 +-
dlls/vcomp100/vcomp100.spec | 4 +-
dlls/vcomp90/vcomp90.spec | 4 +-
5 files changed, 152 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index af6fe61..9771841 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -61,6 +61,9 @@ struct vcomp_thread_data
/* section */
unsigned int section;
+
+ /* dynamic */
+ unsigned int dynamic;
};
struct vcomp_team_data
@@ -82,6 +85,15 @@ struct vcomp_team_data
unsigned int section;
int num_sections;
int section_index;
+
+ /* dynamic */
+ DWORD dynamic;
+ DWORD dynamic_forward;
+ DWORD dynamic_first;
+ DWORD dynamic_iterations;
+ int dynamic_step;
+ DWORD dynamic_chunksize;
+ DWORD dynamic_min_chunksize;
};
#if defined(__i386__)
@@ -497,6 +509,83 @@ void CDECL _vcomp_for_static_end(void)
TRACE("()\n");
}
+void CDECL _vcomp_for_dynamic_init(int flags, int first, int last, int step, int chunksize)
+{
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations;
+ BOOL forward = (flags & 0x40) != 0;
+
+ TRACE("(%d, %d, %d, %d, %d)\n", flags, first, last, step, chunksize);
+
+ EnterCriticalSection(&vcomp_section);
+ thread_data->dynamic++;
+ if ((int)(thread_data->dynamic - team_data->dynamic) > 0)
+ {
+ /* first thread in a new for_dynamic */
+
+ if (forward)
+ {
+ DWORD64 last64 = last;
+ if (last64 < first)
+ last64 += 0x100000000;
+ iterations = 1 + (last64 - first) / step;
+ }
+ else
+ {
+ DWORD first64 = first;
+ if (first64 < last)
+ first64 += 0x100000000;
+ iterations = 1 + (first64 - last) / step;
+ }
+
+ team_data->dynamic = thread_data->dynamic;
+ team_data->dynamic_forward = forward;
+ team_data->dynamic_first = first;
+ team_data->dynamic_iterations = iterations;
+ team_data->dynamic_step = step;
+ team_data->dynamic_chunksize = max(1, iterations / team_data->num_threads);
+ team_data->dynamic_min_chunksize = max(1, chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+}
+
+int CDECL _vcomp_for_dynamic_next(int *begin, int *end)
+{
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations = 0;
+
+ TRACE("(%p, %p)\n", begin, end);
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_data->dynamic == team_data->dynamic &&
+ team_data->dynamic_iterations != 0)
+ {
+ iterations = min(team_data->dynamic_iterations, team_data->dynamic_chunksize);
+ team_data->dynamic_iterations -= iterations;
+
+ if (team_data->dynamic_forward)
+ {
+ *begin = team_data->dynamic_first;
+ *end = team_data->dynamic_first + (iterations - 1) * team_data->dynamic_step;
+ team_data->dynamic_first += iterations * team_data->dynamic_step;
+ }
+ else
+ {
+ *begin = team_data->dynamic_first;
+ *end = team_data->dynamic_first - (iterations - 1) * team_data->dynamic_step;
+ team_data->dynamic_first -= iterations * team_data->dynamic_step;
+ }
+
+ team_data->dynamic_chunksize =
+ max((team_data->dynamic_chunksize * 3 + 2)/4, team_data->dynamic_min_chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+
+ return (iterations != 0);
+}
+
int CDECL omp_in_parallel(void)
{
TRACE("()\n");
@@ -571,11 +660,13 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_data.barrier = 0;
team_data.barrier_count = 0;
team_data.section = 0;
+ team_data.dynamic = 0;
thread_data.team = &team_data;
thread_data.thread_num = 0;
thread_data.fork_threads = 0;
thread_data.section = 1;
+ thread_data.dynamic = 1;
list_init(&thread_data.entry);
InitializeConditionVariable(&thread_data.cond);
@@ -592,6 +683,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->thread_num = team_data.num_threads++;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
list_remove(&data->entry);
list_add_tail(&thread_data.entry, &data->entry);
WakeAllConditionVariable(&data->cond);
@@ -611,6 +703,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->thread_num = team_data.num_threads;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
InitializeConditionVariable(&data->cond);
thread = CreateThread(NULL, 0, _vcomp_fork_worker, data, 0, NULL);
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 8de4510b..3992bda 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -32,6 +32,8 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
+static void (CDECL *p_vcomp_for_dynamic_init)(int flags, int first, int last, int step, int chunksize);
+static int (CDECL *p_vcomp_for_dynamic_next)(int *begin, int *end);
static void (CDECL *p_vcomp_for_static_end)(void);
static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
int *begin, int *end, int *next, int *lastchunk);
@@ -175,6 +177,8 @@ static BOOL init_vcomp(void)
}
VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_for_dynamic_init);
+ VCOMP_GET_PROC(_vcomp_for_dynamic_next);
VCOMP_GET_PROC(_vcomp_for_static_end);
VCOMP_GET_PROC(_vcomp_for_static_init);
VCOMP_GET_PROC(_vcomp_for_static_simple_init);
@@ -809,6 +813,54 @@ static void test_vcomp_for_static_init(void)
}
}
+static void CDECL _test_vcomp_for_dynamic_init(LONG *a, LONG *b, LONG *c)
+{
+ int begin, end;
+
+ p_vcomp_for_dynamic_init(0x40, 1, 100000, 1, 30);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ InterlockedExchangeAdd(a, end - begin + 1);
+ Sleep(50);
+ }
+
+ p_vcomp_for_dynamic_init(0, 1337, 1, 1, 50);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ InterlockedExchangeAdd(b, begin - end + 1);
+ Sleep(50);
+ }
+
+ p_vcomp_for_dynamic_init(0x40, 1, 100000, 7, 30);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ while (begin <= end)
+ {
+ InterlockedIncrement(c);
+ begin += 7;
+ }
+ Sleep(50);
+ }
+}
+
+static void test_vcomp_for_dynamic_init(void)
+{
+ LONG a, b, c;
+ int i;
+
+ for (i = 1; i <= 4; i++)
+ {
+ trace("Running tests with %d threads\n", i);
+ pomp_set_num_threads(i);
+
+ a = b = c = 0;
+ p_vcomp_fork(TRUE, 3, _test_vcomp_for_dynamic_init, &a, &b, &c);
+ ok(a == 100000, "expected a = 100000, got %d\n", a);
+ ok(b == 1337, "expected b = 1337, got %d\n", b);
+ ok(c == 14286, "expected c = 14286, got %d\n", c);
+ }
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -820,6 +872,7 @@ START_TEST(vcomp)
test_vcomp_sections_init();
test_vcomp_for_static_simple_init();
test_vcomp_for_static_init();
+ test_vcomp_for_dynamic_init();
release_vcomp();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 7083ce4..1b02a65 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long)
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr)
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end()
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr)
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 56c7ae3..ab93ec2 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long) vcomp._vcomp_for_dynamic_init
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr) vcomp._vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 56c7ae3..ab93ec2 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long) vcomp._vcomp_for_dynamic_init
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr) vcomp._vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
--
2.4.5

View File

@ -1,90 +1,91 @@
From bbced4bb965ecd2f773783ffb19f76b6e908f109 Mon Sep 17 00:00:00 2001
From bf7251bea46154f6ef2f61182b87d8e19964f4e8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 19:19:00 +0200
Date: Sat, 18 Jul 2015 20:38:36 +0200
Subject: vcomp: Implement _vcomp_for_static_init.
---
dlls/vcomp/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/main.c | 63 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
4 files changed, 65 insertions(+), 3 deletions(-)
4 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 7000e1b..f09fdda 100644
index b647bb1..0148c8b 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -430,6 +430,68 @@ void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last,
}
@@ -414,6 +414,69 @@ void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last,
*end = *begin + (per_thread - 1) * step;
}
+void CDECL _vcomp_for_static_init(int first, int last, int step, int chunksize, unsigned int *loops,
+ int *begin, int *end, int *next, int *lastchunk)
+{
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations, num_chunks, per_thread, remaining;
+ DWORD num_threads, thread_num;
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ int num_threads = team_data ? team_data->num_threads : 1;
+ int thread_num = thread_data->thread_num;
+
+ TRACE("(%d, %d, %d, %d, %p, %p, %p, %p, %p)\n",
+ first, last, step, chunksize, loops, begin, end, next, lastchunk);
+
+ num_threads = team_data->num_threads;
+ thread_num = thread_data->thread_num;
+ if (num_threads == 1 && chunksize != 1)
+ {
+ *loops = 1;
+ *begin = first;
+ *end = last;
+ *next = 0;
+ *lastchunk = first;
+ return;
+ }
+
+ if (first == last)
+ {
+ *loops = !thread_num;
+ if (!thread_num)
+ {
+ *begin = first;
+ *end = last;
+ *next = 0;
+ *lastchunk = first;
+ }
+ return;
+ }
+
+ if (step <= 0)
+ {
+ *loops = 0;
+ return;
+ }
+
+ if (first < last)
+ iterations = 1 + (last - first) / step;
+ else
+ {
+ iterations = 1 + (first - last) / step;
+ step *= -1;
+ }
+
+ if (chunksize < 1)
+ chunksize = 1;
+
+ if (num_threads == 1 && chunksize > 1)
+ {
+ *loops = 1;
+ *begin = first;
+ *end = last;
+ *next = chunksize;
+ *lastchunk = first;
+ }
+ else if (last > first)
+ {
+ iterations = 1 + (last - first) / step;
+ num_chunks = (iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+ num_chunks = ((DWORD64)iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+
+ *loops = per_thread + (thread_num < remaining);
+ *begin = first + thread_num * chunksize * step;
+ *end = *begin + (chunksize - 1) * step;
+ *next = chunksize * num_threads * step;
+ *lastchunk = first + (num_chunks - 1) * chunksize * step;
+
+ }
+ else if (last < first)
+ {
+ iterations = 1 + (first - last) / step;
+ num_chunks = (iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+
+ *loops = per_thread + (thread_num < remaining);
+ *begin = first - thread_num * chunksize * step;
+ *end = *begin - (chunksize - 1) * step;
+ *next = - chunksize * num_threads * step;
+ *lastchunk = first - (num_chunks - 1) * chunksize * step;
+ }
+ else
+ {
+ *loops = (thread_num == 0);
+ *begin = first;
+ *end = last;
+ *next = 0;
+ *lastchunk = first;
+ }
+ *loops = per_thread + (thread_num < remaining);
+ *begin = first + thread_num * chunksize * step;
+ *end = *begin + (chunksize - 1) * step;
+ *next = chunksize * num_threads * step;
+ *lastchunk = first + (num_chunks - 1) * chunksize * step;
+}
+
void CDECL _vcomp_for_static_end(void)
{
TRACE("()\n");
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 51dc13c..718f80e 100644
index d6b8bf5..7083ce4 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -60,7 +60,7 @@
@ -97,7 +98,7 @@ index 51dc13c..718f80e 100644
@ cdecl _vcomp_for_static_simple_init(long long long long ptr ptr)
@ stub _vcomp_for_static_simple_init_i8
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index c2c644a..c0b3d98 100644
index a6933c8..56c7ae3 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -60,7 +60,7 @@
@ -110,7 +111,7 @@ index c2c644a..c0b3d98 100644
@ cdecl _vcomp_for_static_simple_init(long long long long ptr ptr) vcomp._vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index c2c644a..c0b3d98 100644
index a6933c8..56c7ae3 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -60,7 +60,7 @@

View File

@ -0,0 +1,287 @@
From b330549979468af9a322b980f0c2cb73031a5b3b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 18 Jul 2015 20:38:54 +0200
Subject: vcomp/tests: Add tests for _vcomp_for_static_init.
---
dlls/vcomp/tests/vcomp.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 243 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index bab9f41..205899d 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -33,6 +33,8 @@ static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
+ int *begin, int *end, int *next, int *lastchunk);
static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
BOOL increment, unsigned int *begin, unsigned int *end);
static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
@@ -175,6 +177,7 @@ static BOOL init_vcomp(void)
VCOMP_GET_PROC(_vcomp_barrier);
VCOMP_GET_PROC(_vcomp_for_static_end);
+ VCOMP_GET_PROC(_vcomp_for_static_init);
VCOMP_GET_PROC(_vcomp_for_static_simple_init);
VCOMP_GET_PROC(_vcomp_fork);
VCOMP_GET_PROC(_vcomp_sections_init);
@@ -632,6 +635,245 @@ static void test_vcomp_for_static_simple_init(void)
pomp_set_num_threads(max_threads);
}
+#define VCOMP_FOR_STATIC_BROKEN_LOOP 1
+#define VCOMP_FOR_STATIC_BROKEN_NEXT 2
+
+DWORD CDECL my_for_static_init(int first, int last, int step, int chunksize, unsigned int *loops,
+ int *begin, int *end, int *next, int *lastchunk)
+{
+ unsigned int iterations, num_chunks, per_thread, remaining;
+ int num_threads = pomp_get_num_threads();
+ int thread_num = pomp_get_thread_num();
+
+ if (num_threads == 1 && chunksize != 1)
+ {
+ *loops = 1;
+ *begin = first;
+ *end = last;
+ *next = 0;
+ *lastchunk = first;
+ return 0;
+ }
+
+ if (first == last)
+ {
+ *loops = !thread_num;
+ if (!thread_num)
+ {
+ /* The value in *next on Windows is either uninitialized, or contains
+ * garbage. The value shouldn't matter for *loops <= 1, so no need to
+ * reproduce that. */
+ *begin = first;
+ *end = last;
+ *next = 0;
+ *lastchunk = first;
+ }
+ return thread_num ? 0 : VCOMP_FOR_STATIC_BROKEN_NEXT;
+ }
+
+ if (step <= 0)
+ {
+ /* The total number of iterations depends on the number of threads here,
+ * which doesn't make any sense. This is most likely a bug in the Windows
+ * implementation. */
+ return VCOMP_FOR_STATIC_BROKEN_LOOP;
+ }
+
+ if (first < last)
+ iterations = 1 + (last - first) / step;
+ else
+ {
+ iterations = 1 + (first - last) / step;
+ step *= -1;
+ }
+
+ if (chunksize < 1)
+ chunksize = 1;
+
+ num_chunks = ((DWORD64)iterations + chunksize - 1) / chunksize;
+ per_thread = num_chunks / num_threads;
+ remaining = num_chunks - per_thread * num_threads;
+
+ *loops = per_thread + (thread_num < remaining);
+ *begin = first + thread_num * chunksize * step;
+ *end = *begin + (chunksize - 1) * step;
+ *next = chunksize * num_threads * step;
+ *lastchunk = first + (num_chunks - 1) * chunksize * step;
+ return 0;
+}
+
+static void CDECL for_static_cb(void)
+{
+ static const struct
+ {
+ int first;
+ int last;
+ int step;
+ int chunksize;
+ }
+ tests[] =
+ {
+ { 0, 0, 1, 1 },
+ { 0, 0, 5, 1 },
+ { 0, 1, 1, 1 },
+ { 0, 2, 1, 1 },
+ { 0, 3, 1, 1 },
+ { 0, 100, 1, 1 },
+ { 0, 100, 1, 5 },
+ { 0, 100, 1, 10 },
+ { 0, 100, 1, 50 },
+ { 0, 100, 1, 100 },
+ { 0, 100, 1, 150 },
+ { 0, 100, 5, 1 },
+ { 0, 100, 7, 0 },
+ { 0, 100, 7, 1 },
+ { 0, 100, 7, 5 },
+ { 0, 100, 7, 10 },
+ { 0, 100, 7, 50 },
+ { 0, 100, 7, 100 },
+ { 0, 100, 7, 150 },
+ { 0, 100, -7, 0 },
+ { 0, 100, -7, 1 },
+ { 0, 100, -7, 5 },
+ { 0, 100, -7, 10 },
+ { 0, 100, -7, 50 },
+ { 0, 100, -7, 100 },
+ { 0, 100, -7, 150 },
+ { 0, 100, 10, 1 },
+ { 0, 100, 50, 1 },
+ { 0, 100, 100, 1 },
+ { 0, 100, 150, 1 },
+ { 0, 100, -150, -5 },
+ { 0, 0x10000000, 1, 1 },
+ { 0, 0x10000000, 1, -500 },
+ { 0, 0x20000000, 1, 1 },
+ { 0, 0x20000000, 1, -500 },
+ { 0, 0x20000000, -1, 1 },
+ { 0, 0x20000000, -100, 1 },
+ { 0, 0x20000000, -0x80000000, 1 },
+ { 0, 0x40000000, 1, 1 },
+ { 0, 0x40000000, 1, -500 },
+ { 0, -0x80000000, 1, 1 },
+ { 0, -0x80000000, 1, -500 },
+ { 50, 50, 1, 1 },
+ { 50, 50, 1, -1 },
+ { 50, 50, 2, 1 },
+ { 50, 50, 2, -1 },
+ { 50, 50, 3, 1 },
+ { 50, 50, 3, -1 },
+ { 50, 50, -1, 1 },
+ { 50, 50, -1, -1 },
+ { 50, 50, -2, 1 },
+ { 50, 50, -2, -1 },
+ { 50, 50, -3, 1 },
+ { 50, 50, -3, -1 },
+ { 50, 50, -100, 1 },
+ { 50, 50, -100, -1 },
+ { 100, 200, 13, 1 },
+ { 100, 200, 13, 5 },
+ { 0x10000000, 0x20000000, -1, 1 },
+ { 0x10000000, 0x20000000, -100, 1 },
+ { 0x10000000, 0x20000000, -0x80000000, 1 },
+ { 0x20000000, 0, 1, 1 },
+ { 0x40000000, 0, 1, 1 },
+ { 0x7FFFFFFE, -0x80000000, 1, 0x1000 },
+ { 0x7FFFFFFF, -0x80000000, 1, 0x1000 },
+ { -0x10000000, -0x20000000, -0x80000000, -1 },
+ { -0x80000000, 0, 1, 1 },
+ };
+ int num_threads = pomp_get_num_threads();
+ int thread_num = pomp_get_thread_num();
+ int i;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ {
+ int my_begin, my_end, my_next, my_lastchunk;
+ int begin, end, next, lastchunk;
+ unsigned int my_loops, loops;
+ DWORD broken_flags;
+
+ my_loops = my_begin = my_end = my_next = my_lastchunk = 0xdeadbeef;
+ loops = begin = end = next = lastchunk = 0xdeadbeef;
+ broken_flags = my_for_static_init(tests[i].first, tests[i].last, tests[i].step, tests[i].chunksize,
+ &my_loops, &my_begin, &my_end, &my_next, &my_lastchunk);
+ p_vcomp_for_static_init(tests[i].first, tests[i].last, tests[i].step, tests[i].chunksize,
+ &loops, &begin, &end, &next, &lastchunk);
+
+ if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
+ {
+ ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %d\n",
+ i, thread_num, num_threads, loops);
+ }
+ else
+ {
+ ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %d, got %d\n",
+ i, thread_num, num_threads, my_loops, loops);
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
+ i, thread_num, num_threads, my_begin, begin);
+ ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+ ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
+ "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
+ ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
+ i, thread_num, num_threads, my_lastchunk, lastchunk);
+ }
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+
+ if (tests[i].first == tests[i].last) continue;
+
+ my_loops = my_begin = my_end = my_next = my_lastchunk = 0xdeadbeef;
+ loops = begin = end = next = lastchunk = 0xdeadbeef;
+ broken_flags = my_for_static_init(tests[i].last, tests[i].first, tests[i].step, tests[i].chunksize,
+ &my_loops, &my_begin, &my_end, &my_next, &my_lastchunk);
+ p_vcomp_for_static_init(tests[i].last, tests[i].first, tests[i].step, tests[i].chunksize,
+ &loops, &begin, &end, &next, &lastchunk);
+
+ if (broken_flags & VCOMP_FOR_STATIC_BROKEN_LOOP)
+ {
+ ok(loops == 0 || loops == 1, "test %d, thread %d/%d: expected loops == 0 or 1, got %d\n",
+ i, thread_num, num_threads, loops);
+ }
+ else
+ {
+ ok(loops == my_loops, "test %d, thread %d/%d: expected loops == %d, got %d\n",
+ i, thread_num, num_threads, my_loops, loops);
+ ok(begin == my_begin, "test %d, thread %d/%d: expected begin == %d, got %d\n",
+ i, thread_num, num_threads, my_begin, begin);
+ ok(end == my_end, "test %d, thread %d/%d: expected end == %u, got %u\n",
+ i, thread_num, num_threads, my_end, end);
+ ok(next == my_next || broken(broken_flags & VCOMP_FOR_STATIC_BROKEN_NEXT),
+ "test %d, thread %d/%d: expected next == %d, got %d\n", i, thread_num, num_threads, my_next, next);
+ ok(lastchunk == my_lastchunk, "test %d, thread %d/%d: expected lastchunk == %d, got %d\n",
+ i, thread_num, num_threads, my_lastchunk, lastchunk);
+ }
+
+ p_vcomp_for_static_end();
+ p_vcomp_barrier();
+ }
+}
+
+#undef VCOMP_FOR_STATIC_BROKEN_LOOP
+#undef VCOMP_FOR_STATIC_BROKEN_NEXT
+
+static void test_vcomp_for_static_init(void)
+{
+ int max_threads = pomp_get_max_threads();
+ int i;
+
+ for_static_cb();
+
+ for (i = 1; i <= 4; i++)
+ {
+ pomp_set_num_threads(i);
+ p_vcomp_fork(TRUE, 0, for_static_cb);
+ p_vcomp_fork(FALSE, 0, for_static_cb);
+ }
+
+ pomp_set_num_threads(max_threads);
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -642,6 +884,7 @@ START_TEST(vcomp)
test_vcomp_fork();
test_vcomp_sections_init();
test_vcomp_for_static_simple_init();
+ test_vcomp_for_static_init();
release_vcomp();
}
--
2.4.5

View File

@ -0,0 +1,207 @@
From 669a548a8daa2c8477a81160cfc473844e0a2e1d Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 19 Jul 2015 01:01:28 +0200
Subject: vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next.
---
dlls/vcomp/main.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 +--
dlls/vcomp100/vcomp100.spec | 4 +--
dlls/vcomp90/vcomp90.spec | 4 +--
4 files changed, 83 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 0148c8b..c565dc8 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -63,6 +63,9 @@ struct vcomp_thread_data
/* section */
unsigned int section;
+
+ /* dynamic */
+ unsigned int dynamic;
};
struct vcomp_team_data
@@ -87,6 +90,14 @@ struct vcomp_task_data
unsigned int section;
int num_sections;
int section_index;
+
+ /* dynamic */
+ unsigned int dynamic;
+ unsigned int dynamic_first;
+ unsigned int dynamic_iterations;
+ int dynamic_step;
+ unsigned int dynamic_chunksize;
+ unsigned int dynamic_min_chunksize;
};
#if defined(__i386__)
@@ -202,6 +213,7 @@ static struct vcomp_thread_data *vcomp_init_thread_data(void)
task_data = &((struct vcomp_thread_and_task_data *)thread_data)->task;
task_data->section = 0;
+ task_data->dynamic = 0;
thread_data->team = NULL;
thread_data->task = task_data;
@@ -209,6 +221,7 @@ static struct vcomp_thread_data *vcomp_init_thread_data(void)
thread_data->parallel = FALSE;
thread_data->fork_threads = 0;
thread_data->section = 1;
+ thread_data->dynamic = 1;
vcomp_set_thread_data(thread_data);
return thread_data;
@@ -483,6 +496,66 @@ void CDECL _vcomp_for_static_end(void)
/* nothing to do here */
}
+void CDECL _vcomp_for_dynamic_init(unsigned int flags, unsigned int first, unsigned int last,
+ int step, unsigned int chunksize)
+{
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_task_data *task_data = thread_data->task;
+
+ TRACE("(%u, %u, %u, %d, %u)\n", flags, first, last, step, chunksize);
+
+ EnterCriticalSection(&vcomp_section);
+ thread_data->dynamic++;
+ if ((int)(thread_data->dynamic - task_data->dynamic) > 0)
+ {
+ struct vcomp_team_data *team_data = thread_data->team;
+ int num_threads = team_data ? team_data->num_threads : 1;
+ unsigned int iterations;
+
+ if (flags & 0x40)
+ iterations = 1 + (last - first) / step;
+ else
+ {
+ iterations = 1 + (first - last) / step;
+ step *= -1;
+ }
+
+ task_data->dynamic = thread_data->dynamic;
+ task_data->dynamic_first = first;
+ task_data->dynamic_iterations = iterations;
+ task_data->dynamic_step = step;
+ task_data->dynamic_chunksize = max(1, iterations / num_threads);
+ task_data->dynamic_min_chunksize = max(1, chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+}
+
+BOOL CDECL _vcomp_for_dynamic_next(unsigned int *begin, unsigned int *end)
+{
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_task_data *task_data = thread_data->task;
+ unsigned int iterations = 0;
+
+ TRACE("(%p, %p)\n", begin, end);
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_data->dynamic == task_data->dynamic &&
+ task_data->dynamic_iterations != 0)
+ {
+ iterations = min(task_data->dynamic_iterations, task_data->dynamic_chunksize);
+ *begin = task_data->dynamic_first;
+ *end = task_data->dynamic_first + (iterations - 1) * task_data->dynamic_step;
+
+ task_data->dynamic_iterations -= iterations;
+ task_data->dynamic_first += iterations * task_data->dynamic_step;
+ task_data->dynamic_chunksize = max((task_data->dynamic_chunksize * 3 + 2)/4,
+ task_data->dynamic_min_chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+
+ return (iterations != 0);
+}
+
BOOL CDECL omp_in_parallel(void)
{
TRACE("()\n");
@@ -560,6 +633,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_data.barrier_count = 0;
task_data.section = 0;
+ task_data.dynamic = 0;
thread_data.team = &team_data;
thread_data.task = &task_data;
@@ -567,6 +641,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
thread_data.parallel = ifval || prev_thread_data->parallel;
thread_data.fork_threads = 0;
thread_data.section = 1;
+ thread_data.dynamic = 1;
list_init(&thread_data.entry);
InitializeConditionVariable(&thread_data.cond);
@@ -585,6 +660,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->parallel = thread_data.parallel;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
list_remove(&data->entry);
list_add_tail(&thread_data.entry, &data->entry);
WakeAllConditionVariable(&data->cond);
@@ -606,6 +682,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->parallel = thread_data.parallel;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
InitializeConditionVariable(&data->cond);
thread = CreateThread(NULL, 0, _vcomp_fork_worker, data, 0, NULL);
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 7083ce4..1b02a65 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long)
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr)
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end()
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr)
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 56c7ae3..ab93ec2 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long) vcomp._vcomp_for_dynamic_init
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr) vcomp._vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 56c7ae3..ab93ec2 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -55,9 +55,9 @@
@ stub _vcomp_copyprivate_receive
@ stub _vcomp_enter_critsect
@ stub _vcomp_flush
-@ stub _vcomp_for_dynamic_init
+@ cdecl _vcomp_for_dynamic_init(long long long long long) vcomp._vcomp_for_dynamic_init
@ stub _vcomp_for_dynamic_init_i8
-@ stub _vcomp_for_dynamic_next
+@ cdecl _vcomp_for_dynamic_next(ptr ptr) vcomp._vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
--
2.4.5

View File

@ -0,0 +1,112 @@
From 23a2077048d54113d81a05a475d63c2df37c2d63 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 19 Jul 2015 01:05:02 +0200
Subject: vcomp/tests: Add tests for _vcomp_for_dynamic_init.
---
dlls/vcomp/tests/vcomp.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 205899d..c7a0e60 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -32,6 +32,9 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
+static void (CDECL *p_vcomp_for_dynamic_init)(unsigned int flags, unsigned int first, unsigned int last,
+ int step, unsigned int chunksize);
+static BOOL (CDECL *p_vcomp_for_dynamic_next)(unsigned int *begin, unsigned int *end);
static void (CDECL *p_vcomp_for_static_end)(void);
static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
int *begin, int *end, int *next, int *lastchunk);
@@ -176,6 +179,8 @@ static BOOL init_vcomp(void)
}
VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_for_dynamic_init);
+ VCOMP_GET_PROC(_vcomp_for_dynamic_next);
VCOMP_GET_PROC(_vcomp_for_static_end);
VCOMP_GET_PROC(_vcomp_for_static_init);
VCOMP_GET_PROC(_vcomp_for_static_simple_init);
@@ -874,6 +879,68 @@ static void test_vcomp_for_static_init(void)
pomp_set_num_threads(max_threads);
}
+static void CDECL for_dynamic_cb(LONG *a, LONG *b, LONG *c)
+{
+ unsigned int begin, end;
+
+ p_vcomp_for_dynamic_init(0x40, 1, 100000, 1, 30);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ InterlockedExchangeAdd(a, end - begin + 1);
+ Sleep(1);
+ }
+
+ p_vcomp_for_dynamic_init(0, 1337, 1, 1, 50);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ InterlockedExchangeAdd(b, begin - end + 1);
+ Sleep(1);
+ }
+
+ p_vcomp_for_dynamic_init(0x40, 1, 100000, 7, 30);
+ while (p_vcomp_for_dynamic_next(&begin, &end))
+ {
+ while (begin <= end)
+ {
+ InterlockedIncrement(c);
+ begin += 7;
+ }
+ Sleep(1);
+ }
+}
+
+static void test_vcomp_for_dynamic_init(void)
+{
+ int max_threads = pomp_get_max_threads();
+ LONG a, b, c;
+ int i;
+
+ a = b = c = 0;
+ for_dynamic_cb(&a, &b, &c);
+ ok(a == 100000, "expected a = 100000, got %d\n", a);
+ ok(b == 1337, "expected b = 1337, got %d\n", b);
+ ok(c == 14286, "expected c = 14286, got %d\n", c);
+
+ for (i = 1; i <= 4; i++)
+ {
+ pomp_set_num_threads(i);
+
+ a = b = c = 0;
+ p_vcomp_fork(TRUE, 3, for_dynamic_cb, &a, &b, &c);
+ ok(a == 100000, "expected a = 100000, got %d\n", a);
+ ok(b == 1337, "expected b = 1337, got %d\n", b);
+ ok(c == 14286, "expected c = 14286, got %d\n", c);
+
+ a = b = c = 0;
+ p_vcomp_fork(FALSE, 3, for_dynamic_cb, &a, &b, &c);
+ ok(a == 100000, "expected a = 100000, got %d\n", a);
+ ok(b == 1337, "expected b = 1337, got %d\n", b);
+ ok(c == 14286, "expected c = 14286, got %d\n", c);
+ }
+
+ pomp_set_num_threads(max_threads);
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -885,6 +952,7 @@ START_TEST(vcomp)
test_vcomp_sections_init();
test_vcomp_for_static_simple_init();
test_vcomp_for_static_init();
+ test_vcomp_for_dynamic_init();
release_vcomp();
}
--
2.4.5