vcomp: Allow calls to _vcomp_sections_init outside of parallel environment.

This commit is contained in:
Sebastian Lackner 2015-07-20 05:15:27 +02:00 committed by Alexandre Julliard
parent 457c5f1977
commit 889eba36e9
2 changed files with 56 additions and 17 deletions

View File

@ -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;

View File

@ -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);