From 889eba36e93918e7957cb3fda142d87abc2b9c84 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 20 Jul 2015 05:15:27 +0200 Subject: [PATCH] vcomp: Allow calls to _vcomp_sections_init outside of parallel environment. --- dlls/vcomp/main.c | 47 ++++++++++++++++++++++++++++------------ dlls/vcomp/tests/vcomp.c | 26 +++++++++++++++++++--- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c index 0f8a27294b2..6e99d21679d 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; @@ -180,17 +184,27 @@ static inline void vcomp_set_thread_data(struct vcomp_thread_data *thread_data) static struct vcomp_thread_data *vcomp_init_thread_data(void) { struct vcomp_thread_data *thread_data = vcomp_get_thread_data(); - if (thread_data) return thread_data; + struct + { + struct vcomp_thread_data thread; + struct vcomp_task_data task; + } *data; - if (!(thread_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*thread_data)))) + if (thread_data) return thread_data; + if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)))) { ERR("could not create thread data\n"); ExitProcess(1); } + data->task.section = 0; + + thread_data = &data->thread; thread_data->team = NULL; + thread_data->task = &data->task; 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 +325,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 +405,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 +427,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 +448,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 +468,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 c433991efdc..a96f9575c5e 100644 --- a/dlls/vcomp/tests/vcomp.c +++ b/dlls/vcomp/tests/vcomp.c @@ -378,15 +378,35 @@ 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); a = b = c = 0; p_vcomp_fork(TRUE, 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); + 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);