Added initial set of patches for multithreaded vcomp implementation.

This commit is contained in:
Sebastian Lackner 2015-07-12 00:08:14 +02:00
parent d709879134
commit 65c559753a
23 changed files with 2229 additions and 1663 deletions

View File

@ -178,7 +178,6 @@ for more details.*
* Implement ID3DXEffect::FindNextValidTechnique ([Wine Bug #34101](https://bugs.winehq.org/show_bug.cgi?id=34101))
* Implement IDXGIOutput::GetDesc
* Implement a Microsoft Yahei replacement font ([Wine Bug #13829](https://bugs.winehq.org/show_bug.cgi?id=13829))
* Implement additional stubs for vcomp dlls ([Wine Bug #31640](https://bugs.winehq.org/show_bug.cgi?id=31640))
* Implement an Arial replacement font ([Wine Bug #32323](https://bugs.winehq.org/show_bug.cgi?id=32323))
* Implement combase.WindowsSubstring function
* Implement default homepage button in inetcpl.cpl
@ -197,6 +196,7 @@ for more details.*
* ~~Implement threadpool timers~~ ([Wine Bug #37306](https://bugs.winehq.org/show_bug.cgi?id=37306))
* ~~Implement threadpool wait objects~~
* ~~Implement threadpool work items~~ ([Wine Bug #32531](https://bugs.winehq.org/show_bug.cgi?id=32531))
* Implement various vcomp functions ([Wine Bug #31640](https://bugs.winehq.org/show_bug.cgi?id=31640))
* Improve ReadDataAvailable handling in FilePipeLocalInformation class
* Improve stub for AEV_GetVolumeRange ([Wine Bug #35658](https://bugs.winehq.org/show_bug.cgi?id=35658))
* Improve stub for ID3DXEffectImpl_CloneEffect

1
debian/changelog vendored
View File

@ -7,6 +7,7 @@ wine-staging (1.7.47) UNRELEASED; urgency=low
* Revert security cookie patch causing regression in multiple applications.
* Added patch to use GLX_MESA_query_renderer extension to get more exact GPU
infos.
* Added initial set of patches for multithreaded vcomp implementation.
* Removed patch to implement kernel32.GetNumaProcessorNode (accepted
upstream).
* Removed patch to initialize *end with NULL on failure in msvcrt.strtod

View File

@ -234,7 +234,7 @@ patch_enable_all ()
enable_user32_Painting="$1"
enable_user32_ScrollWindowEx="$1"
enable_user32_WndProc="$1"
enable_vcomp_Stub_Functions="$1"
enable_vcomp_Functions="$1"
enable_version_VerQueryValue="$1"
enable_wbemdisp_ISWbemSecurity="$1"
enable_wbemdisp_Timeout="$1"
@ -778,8 +778,8 @@ patch_enable ()
user32-WndProc)
enable_user32_WndProc="$2"
;;
vcomp-Stub_Functions)
enable_vcomp_Stub_Functions="$2"
vcomp-Functions)
enable_vcomp_Functions="$2"
;;
version-VerQueryValue)
enable_version_VerQueryValue="$2"
@ -4598,33 +4598,40 @@ if test "$enable_user32_WndProc" -eq 1; then
) >> "$patchlist"
fi
# Patchset vcomp-Stub_Functions
# Patchset vcomp-Functions
# |
# | This patchset fixes the following Wine bugs:
# | * [#31640] Implement additional stubs for vcomp dlls
# | * [#31640] Implement various vcomp functions
# |
# | Modified files:
# | * configure.ac, dlls/vcomp/Makefile.in, dlls/vcomp/fork.c, dlls/vcomp/main.c, dlls/vcomp/tests/Makefile.in,
# | dlls/vcomp/tests/fork.c, dlls/vcomp/tests/vcomp.manifest, dlls/vcomp/tests/vcomp.rc, dlls/vcomp/tests/work.c,
# | dlls/vcomp/vcomp.spec, dlls/vcomp/vcomp_private.h, dlls/vcomp/work.c, dlls/vcomp100/vcomp100.spec,
# | * configure.ac, dlls/vcomp/main.c, dlls/vcomp/tests/Makefile.in, dlls/vcomp/tests/vcomp.c,
# | dlls/vcomp/tests/vcomp.manifest, dlls/vcomp/tests/vcomp.rc, dlls/vcomp/vcomp.spec, dlls/vcomp100/vcomp100.spec,
# | dlls/vcomp90/vcomp90.spec
# |
if test "$enable_vcomp_Stub_Functions" -eq 1; then
patch_apply vcomp-Stub_Functions/0001-vcomp-single-threaded-implementation-of-_vcomp_fork.patch
patch_apply vcomp-Stub_Functions/0002-vcomp-better-stubs-for-_vcomp_for_static_simple_init.patch
patch_apply vcomp-Stub_Functions/0003-vcomp-better-stub-for-_vcomp_for_static_init.patch
patch_apply vcomp-Stub_Functions/0004-vcomp-implement-omp_in_parallel.patch
patch_apply vcomp-Stub_Functions/0005-vcomp-better-stubs-for-_vcomp_for_dynamic_init-_vcom.patch
patch_apply vcomp-Stub_Functions/0006-vcomp-better-stubs-for-_vcomp_sections_init-_vcomp_s.patch
patch_apply vcomp-Stub_Functions/0007-vcomp-Add-a-warning-that-multithreading-is-not-yet-s.patch
if test "$enable_vcomp_Functions" -eq 1; then
patch_apply vcomp-Functions/0001-vcomp-Implement-stub-for-_vcomp_fork.patch
patch_apply vcomp-Functions/0002-vcomp-Add-basic-worker-thread-infrastructure.patch
patch_apply vcomp-Functions/0003-vcomp-tests-Add-initial-tests-for-_vcomp_fork.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_barrier.patch
patch_apply vcomp-Functions/0009-vcomp-Implement-omp_in_parallel.patch
patch_apply vcomp-Functions/0010-vcomp-Implement-_vcomp_sections_init-and-_vcomp_sect.patch
patch_apply vcomp-Functions/0011-vcomp-Implement-_vcomp_for_dynamic_init-and-_vcomp_f.patch
(
echo '+ { "Dan Kegel", "vcomp: single-threaded implementation of _vcomp_fork.", 1 },';
echo '+ { "Dan Kegel", "vcomp: better stubs for _vcomp_for_static_simple_init, _vcomp_for_static_end.", 1 },';
echo '+ { "Dan Kegel", "vcomp: better stub for _vcomp_for_static_init.", 1 },';
echo '+ { "Dan Kegel", "vcomp: implement omp_in_parallel.", 1 },';
echo '+ { "Dan Kegel", "vcomp: better stubs for _vcomp_for_dynamic_init, _vcomp_for_dynamic_next.", 1 },';
echo '+ { "Dan Kegel", "vcomp: better stubs for _vcomp_sections_init, _vcomp_sections_next.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Add a warning that multithreading is not yet supported.", 1 },';
echo '+ { "Dan Kegel", "vcomp: Implement stub for _vcomp_fork.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Add basic worker thread infrastructure.", 1 },';
echo '+ { "Dan Kegel", "vcomp/tests: Add initial tests for _vcomp_fork.", 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 _vcomp_barrier.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement omp_in_parallel.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_sections_init and _vcomp_sections_next and add tests.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next and add tests.", 1 },';
) >> "$patchlist"
fi

View File

@ -0,0 +1,165 @@
From 6404654fd885acbf0e563d9b5070d321986b5b8d Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Sat, 11 Jul 2015 06:50:26 +0200
Subject: vcomp: Implement stub for _vcomp_fork.
---
dlls/vcomp/main.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
4 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index ab2a372..26f6c67 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -3,6 +3,7 @@
* vcomp implementation
*
* Copyright 2011 Austin English
+ * Copyright 2012 Dan Kegel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -107,6 +108,98 @@ void CDECL _vcomp_single_end(void)
TRACE("stub\n");
}
+void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
+
+void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
+{
+ __ms_va_list valist;
+
+ TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
+
+ __ms_va_start(valist, wrapper);
+ _vcomp_fork_call_wrapper(wrapper, nargs, valist);
+ __ms_va_end(valist);
+}
+
+#if defined(__i386__)
+__ASM_GLOBAL_FUNC( _vcomp_fork_call_wrapper,
+ "pushl %ebp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+ __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+ "movl %esp,%ebp\n\t"
+ __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+ "pushl %esi\n\t"
+ __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
+ "pushl %edi\n\t"
+ __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
+ "movl 12(%ebp),%edx\n\t"
+ "movl %esp,%edi\n\t"
+ "shll $2,%edx\n\t"
+ "jz 1f\n\t"
+ "subl %edx,%edi\n\t"
+ "andl $~15,%edi\n\t"
+ "movl %edi,%esp\n\t"
+ "movl 12(%ebp),%ecx\n\t"
+ "movl 16(%ebp),%esi\n\t"
+ "cld\n\t"
+ "rep; movsl\n"
+ "1:\tcall *8(%ebp)\n\t"
+ "leal -8(%ebp),%esp\n\t"
+ "popl %edi\n\t"
+ __ASM_CFI(".cfi_same_value %edi\n\t")
+ "popl %esi\n\t"
+ __ASM_CFI(".cfi_same_value %esi\n\t")
+ "popl %ebp\n\t"
+ __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+ __ASM_CFI(".cfi_same_value %ebp\n\t")
+ "ret" )
+
+#elif defined(__x86_64__)
+
+__ASM_GLOBAL_FUNC( _vcomp_fork_call_wrapper,
+ "pushq %rbp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
+ __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
+ "movq %rsp,%rbp\n\t"
+ __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
+ "pushq %rsi\n\t"
+ __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
+ "pushq %rdi\n\t"
+ __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
+ "movq %rcx,%rax\n\t"
+ "movq $4,%rcx\n\t"
+ "cmp %rcx,%rdx\n\t"
+ "cmovgq %rdx,%rcx\n\t"
+ "leaq 0(,%rcx,8),%rdx\n\t"
+ "subq %rdx,%rsp\n\t"
+ "andq $~15,%rsp\n\t"
+ "movq %rsp,%rdi\n\t"
+ "movq %r8,%rsi\n\t"
+ "rep; movsq\n\t"
+ "movq 0(%rsp),%rcx\n\t"
+ "movq 8(%rsp),%rdx\n\t"
+ "movq 16(%rsp),%r8\n\t"
+ "movq 24(%rsp),%r9\n\t"
+ "callq *%rax\n\t"
+ "leaq -16(%rbp),%rsp\n\t"
+ "popq %rdi\n\t"
+ __ASM_CFI(".cfi_same_value %rdi\n\t")
+ "popq %rsi\n\t"
+ __ASM_CFI(".cfi_same_value %rsi\n\t")
+ __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
+ "popq %rbp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
+ __ASM_CFI(".cfi_same_value %rbp\n\t")
+ "ret")
+#else
+
+void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args)
+{
+ ERR("Not implemented for this architecture\n");
+}
+
+#endif
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 306dd15..d446574 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr)
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 39cf91c..2c04e91 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 39cf91c..2c04e91 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
--
2.4.5

View File

@ -0,0 +1,311 @@
From e3f58ae29d504bd1f2287566878b7d6674bd5484 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 18:53:41 +0200
Subject: vcomp: Add basic worker thread infrastructure.
---
dlls/vcomp/main.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 211 insertions(+), 10 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 26f6c67..9de9721 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -4,6 +4,7 @@
*
* Copyright 2011 Austin English
* Copyright 2012 Dan Kegel
+ * Copyright 2015 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,13 +24,68 @@
#include "config.h"
#include <stdarg.h>
+#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+static HMODULE vcomp_module;
+static struct list vcomp_idle_threads = LIST_INIT(vcomp_idle_threads);
+static DWORD vcomp_context_tls = TLS_OUT_OF_INDEXES;
+static DWORD vcomp_max_threads = 32;
+static DWORD vcomp_num_threads = 1;
+
+static RTL_CRITICAL_SECTION vcomp_section;
+static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &vcomp_section,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": vcomp_section") }
+};
+static RTL_CRITICAL_SECTION vcomp_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+struct vcomp_thread_info
+{
+ struct list entry;
+ CONDITION_VARIABLE cond;
+
+ /* current task */
+ struct vcomp_team_info *team;
+ DWORD thread_num;
+};
+
+struct vcomp_team_info
+{
+ CONDITION_VARIABLE cond;
+ DWORD num_threads;
+ DWORD finished_threads;
+
+ /* callback arguments */
+ unsigned int nargs;
+ void *wrapper;
+ __ms_va_list valist;
+};
+
+static inline struct vcomp_thread_info *vcomp_get_thread_info(void)
+{
+ return (struct vcomp_thread_info *)TlsGetValue(vcomp_context_tls);
+}
+
+static inline struct vcomp_team_info *vcomp_get_team_info(void)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ return thread_info ? thread_info->team : NULL;
+}
+
+static inline void vcomp_set_thread_info(struct vcomp_thread_info *thread_info)
+{
+ TlsSetValue(vcomp_context_tls, thread_info);
+}
+
int CDECL omp_get_dynamic(void)
{
TRACE("stub\n");
@@ -39,7 +95,7 @@ int CDECL omp_get_dynamic(void)
int CDECL omp_get_max_threads(void)
{
TRACE("stub\n");
- return 1;
+ return vcomp_max_threads;
}
int CDECL omp_get_nested(void)
@@ -56,14 +112,22 @@ int CDECL omp_get_num_procs(void)
int CDECL omp_get_num_threads(void)
{
- TRACE("stub\n");
- return 1;
+ struct vcomp_team_info *team_info;
+
+ TRACE("()\n");
+
+ team_info = vcomp_get_team_info();
+ return team_info ? team_info->num_threads : 1;
}
int CDECL omp_get_thread_num(void)
{
- TRACE("stub\n");
- return 0;
+ struct vcomp_thread_info *thread_info;
+
+ TRACE("()\n");
+
+ thread_info = vcomp_get_thread_info();
+ return thread_info ? thread_info->thread_num : 0;
}
/* Time in seconds since "some time in the past" */
@@ -85,6 +149,7 @@ void CDECL omp_set_nested(int nested)
void CDECL omp_set_num_threads(int num_threads)
{
TRACE("(%d): stub\n", num_threads);
+ vcomp_num_threads = max(1, min(num_threads, vcomp_max_threads));
}
void CDECL _vcomp_barrier(void)
@@ -94,7 +159,8 @@ void CDECL _vcomp_barrier(void)
void CDECL _vcomp_set_num_threads(int num_threads)
{
- TRACE("(%d): stub\n", num_threads);
+ TRACE("(%d)\n", num_threads);
+ vcomp_num_threads = max(1, min(num_threads, vcomp_max_threads));
}
int CDECL _vcomp_single_begin(int flags)
@@ -110,15 +176,139 @@ void CDECL _vcomp_single_end(void)
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
+static DWORD WINAPI _vcomp_fork_worker(void *param)
+{
+ struct vcomp_thread_info *thread_info = param;
+ vcomp_set_thread_info(thread_info);
+
+ TRACE("starting worker thread %p\n", thread_info);
+
+ EnterCriticalSection(&vcomp_section);
+ for (;;)
+ {
+ struct vcomp_team_info *team = thread_info->team;
+ if (team != NULL)
+ {
+ /* Leave critical section and execute callback. */
+ LeaveCriticalSection(&vcomp_section);
+ _vcomp_fork_call_wrapper(team->wrapper, team->nargs, team->valist);
+ EnterCriticalSection(&vcomp_section);
+
+ /* Detach current thread from team. */
+ thread_info->team = NULL;
+ list_remove(&thread_info->entry);
+ list_add_tail(&vcomp_idle_threads, &thread_info->entry);
+ if (++team->finished_threads >= team->num_threads)
+ WakeAllConditionVariable(&team->cond);
+ }
+
+ if (!SleepConditionVariableCS(&thread_info->cond, &vcomp_section, 5000) &&
+ GetLastError() == ERROR_TIMEOUT && !thread_info->team)
+ {
+ break;
+ }
+ }
+ list_remove(&thread_info->entry);
+ LeaveCriticalSection(&vcomp_section);
+
+ TRACE("terminating worker thread %p\n", thread_info);
+ HeapFree(GetProcessHeap(), 0, thread_info);
+ FreeLibraryAndExitThread(vcomp_module, 0);
+ return 0;
+}
+
void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
{
- __ms_va_list valist;
+ struct vcomp_thread_info thread_info, *prev_thread_info;
+ struct vcomp_team_info team_info;
+ DWORD num_threads = vcomp_num_threads; /* FIXME */
+ BOOL parallel = ifval;
TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
- __ms_va_start(valist, wrapper);
- _vcomp_fork_call_wrapper(wrapper, nargs, valist);
- __ms_va_end(valist);
+ /* Initialize members of team_info. */
+ InitializeConditionVariable(&team_info.cond);
+ team_info.num_threads = 1;
+ team_info.finished_threads = 0;
+ team_info.nargs = nargs;
+ team_info.wrapper = wrapper;
+ __ms_va_start(team_info.valist, wrapper);
+
+ /* Initialize members of thread_info. */
+ list_init(&thread_info.entry);
+ InitializeConditionVariable(&thread_info.cond);
+ thread_info.team = &team_info;
+ thread_info.thread_num = 0;
+
+ if (parallel)
+ {
+ struct list *ptr;
+ EnterCriticalSection(&vcomp_section);
+
+ /* Try to reuse idle threads. */
+ while (team_info.num_threads < num_threads &&
+ (ptr = list_head( &vcomp_idle_threads )))
+ {
+ struct vcomp_thread_info *info = LIST_ENTRY(ptr, struct vcomp_thread_info, entry);
+ list_remove(&info->entry);
+ list_add_tail(&thread_info.entry, &info->entry);
+ info->team = &team_info;
+ info->thread_num = team_info.num_threads++;
+ WakeAllConditionVariable(&info->cond);
+ }
+
+ /* Spawn additional new threads. */
+ while (team_info.num_threads < num_threads)
+ {
+ struct vcomp_thread_info *info;
+ HMODULE module;
+ HANDLE thread;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(*info));
+ if (!info) break;
+
+ InitializeConditionVariable(&info->cond);
+ info->team = &team_info;
+ info->thread_num = team_info.num_threads;
+
+ thread = CreateThread(NULL, 0, _vcomp_fork_worker, info, 0, NULL);
+ if (!thread)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ break;
+ }
+
+ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (const WCHAR *)vcomp_module, &module);
+
+ list_add_tail(&thread_info.entry, &info->entry);
+ team_info.num_threads++;
+ CloseHandle(thread);
+ }
+
+ LeaveCriticalSection(&vcomp_section);
+ }
+
+ /* Call the callback in the context of the new team. */
+ prev_thread_info = vcomp_get_thread_info();
+ vcomp_set_thread_info(&thread_info);
+ _vcomp_fork_call_wrapper(team_info.wrapper, team_info.nargs, team_info.valist);
+ vcomp_set_thread_info(prev_thread_info);
+
+ /* Implicit join, wait for other tasks. */
+ if (parallel)
+ {
+ EnterCriticalSection(&vcomp_section);
+
+ team_info.finished_threads++;
+ while (team_info.finished_threads < team_info.num_threads)
+ SleepConditionVariableCS(&team_info.cond, &vcomp_section, INFINITE);
+
+ LeaveCriticalSection(&vcomp_section);
+ assert(list_empty(&thread_info.entry));
+ }
+
+ __ms_va_end(team_info.valist);
}
#if defined(__i386__)
@@ -208,8 +398,19 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
+
case DLL_PROCESS_ATTACH:
+ vcomp_module = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
+ if ((vcomp_context_tls = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {
+ ERR("Failed to allocate TLS index\n");
+ return FALSE;
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ TlsFree(vcomp_context_tls);
break;
}
--
2.4.5

View File

@ -0,0 +1,230 @@
From 92cd559115925b61b980a784efacb0ccdd7029d0 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Sat, 11 Jul 2015 03:56:04 +0200
Subject: vcomp/tests: Add initial tests for _vcomp_fork.
---
configure.ac | 3 +-
dlls/vcomp/tests/Makefile.in | 7 +++
dlls/vcomp/tests/vcomp.c | 122 ++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/vcomp.manifest | 21 +++++++
dlls/vcomp/tests/vcomp.rc | 22 ++++++++
5 files changed, 174 insertions(+), 1 deletion(-)
create mode 100644 dlls/vcomp/tests/Makefile.in
create mode 100644 dlls/vcomp/tests/vcomp.c
create mode 100644 dlls/vcomp/tests/vcomp.manifest
create mode 100644 dlls/vcomp/tests/vcomp.rc
diff --git a/configure.ac b/configure.ac
index 3eaec29..a36fc4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3321,7 +3321,8 @@ WINE_CONFIG_DLL(uxtheme,,[implib])
WINE_CONFIG_TEST(dlls/uxtheme/tests)
WINE_CONFIG_DLL(vbscript,,[clean])
WINE_CONFIG_TEST(dlls/vbscript/tests,[clean])
-WINE_CONFIG_DLL(vcomp)
+WINE_CONFIG_DLL(vcomp,,[implib])
+WINE_CONFIG_TEST(dlls/vcomp/tests)
WINE_CONFIG_DLL(vcomp100)
WINE_CONFIG_DLL(vcomp90)
WINE_CONFIG_DLL(vdhcp.vxd,enable_win16)
diff --git a/dlls/vcomp/tests/Makefile.in b/dlls/vcomp/tests/Makefile.in
new file mode 100644
index 0000000..08a5b7f
--- /dev/null
+++ b/dlls/vcomp/tests/Makefile.in
@@ -0,0 +1,7 @@
+TESTDLL = vcomp.dll
+
+C_SRCS = \
+ vcomp.c
+
+RC_SRCS = \
+ vcomp.rc
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
new file mode 100644
index 0000000..5c6a861
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.c
@@ -0,0 +1,122 @@
+/*
+ * Unit test suite for vcomp fork/join implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+
+static const int is_win64 = (sizeof(void *) > sizeof(int));
+
+static HMODULE hvcomp = 0;
+static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
+static int (CDECL *pomp_get_max_threads)(void);
+
+#define VCOMP_GET_PROC(func) \
+ do \
+ { \
+ p ## func = (void *)GetProcAddress(hvcomp, #func); \
+ if (!p ## func) trace("Failed to get address for %s\n", #func); \
+ } \
+ while (0)
+
+static BOOL init_vcomp(void)
+{
+ hvcomp = LoadLibraryA("vcomp.dll");
+ if (!hvcomp)
+ {
+ win_skip("vcomp.dll not installed\n");
+ return FALSE;
+ }
+
+ VCOMP_GET_PROC(_vcomp_fork);
+ VCOMP_GET_PROC(omp_get_max_threads);
+
+ return TRUE;
+}
+
+#undef VCOMP_GET_PROC
+
+static void CDECL _test_vcomp_fork_ptr(LONG *a, LONG *b, LONG *c, LONG *d, LONG *e)
+{
+ InterlockedIncrement(a);
+ InterlockedIncrement(b);
+ InterlockedIncrement(c);
+ InterlockedIncrement(d);
+ InterlockedIncrement(e);
+}
+
+static void CDECL _test_vcomp_fork_uintptr(UINT_PTR a, UINT_PTR b, UINT_PTR c, UINT_PTR d, UINT_PTR e)
+{
+ ok(a == 1, "expected a = 1, got %p\n", (void *)a);
+ ok(b == MAXUINT_PTR - 2, "expected b = MAXUINT_PTR - 2, got %p\n", (void *)b);
+ ok(c == 3, "expected c = 3, got %p\n", (void *)c);
+ ok(d == MAXUINT_PTR - 4, "expected d = MAXUINT_PTR - 4, got %p\n", (void *)d);
+ ok(e == 5, "expected e = 5, got %p\n", (void *)e);
+}
+
+static void CDECL _test_vcomp_fork_float(float a, float b, float c, float d, float e)
+{
+ ok(1.4999 < a && a < 1.5001, "expected a = 1.5, got %f\n", a);
+ ok(2.4999 < b && b < 2.5001, "expected b = 2.5, got %f\n", b);
+ ok(3.4999 < c && c < 3.5001, "expected c = 3.5, got %f\n", c);
+ ok(4.4999 < d && d < 4.5001, "expected d = 4.5, got %f\n", d);
+ ok(5.4999 < e && e < 5.5001, "expected e = 5.5, got %f\n", e);
+}
+
+static void test_vcomp_fork(void)
+{
+ LONG a, b, c, d, e;
+ int n = pomp_get_max_threads();
+
+ a = 0; b = 1; c = 2; d = 3; e = 4;
+ p_vcomp_fork(FALSE, 5, _test_vcomp_fork_ptr, &a, &b, &c, &d, &e);
+ ok(a == 1, "expected a = 1, got %u\n", a);
+ ok(b == 2, "expected b = 2, got %u\n", b);
+ ok(c == 3, "expected c = 3, got %u\n", c);
+ ok(d == 4, "expected d = 4, got %u\n", d);
+ ok(e == 5, "expected e = 5, got %u\n", e);
+
+ a = 0; b = 1; c = 2; d = 3; e = 4;
+ p_vcomp_fork(TRUE, 5, _test_vcomp_fork_ptr, &a, &b, &c, &d, &e);
+ ok(a > 0 && a <= (n + 0), "expected a > 0 && a <= (n + 0), got %u\n", a);
+ ok(b > 1 && b <= (n + 1), "expected b > 1 && b <= (n + 1), got %u\n", b);
+ ok(c > 2 && c <= (n + 2), "expected c > 2 && c <= (n + 2), got %u\n", c);
+ ok(d > 3 && d <= (n + 3), "expected d > 3 && d <= (n + 3), got %u\n", d);
+ ok(e > 4 && e <= (n + 4), "expected e > 4 && e <= (n + 4), got %u\n", e);
+
+ p_vcomp_fork(TRUE, 5, _test_vcomp_fork_uintptr, (UINT_PTR)1, (UINT_PTR)(MAXUINT_PTR - 2),
+ (UINT_PTR)3, (UINT_PTR)(MAXUINT_PTR - 4), (UINT_PTR)5);
+
+ if (is_win64)
+ skip("skipping float test on x86_64\n");
+ else
+ {
+ void (CDECL *func)(BOOL, int, void *, float, float, float, float, float) = (void *)p_vcomp_fork;
+ func(TRUE, 5, _test_vcomp_fork_float, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f);
+ }
+}
+
+START_TEST(vcomp)
+{
+ if (!init_vcomp())
+ return;
+
+ test_vcomp_fork();
+
+ FreeLibrary(hvcomp);
+}
diff --git a/dlls/vcomp/tests/vcomp.manifest b/dlls/vcomp/tests/vcomp.manifest
new file mode 100644
index 0000000..6c8bd91
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.manifest
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity
+ type="win32"
+ name="Wine.vcomp.Test"
+ version="1.0.0.0"
+ processorArchitecture="*"
+ />
+<description>Wine vcomp test suite</description>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.VC80.OpenMP"
+ version="8.0.50608.0"
+ processorArchitecture="*"
+ publicKeyToken="1fc8b3b9a1e18e3b"
+ />
+ </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/dlls/vcomp/tests/vcomp.rc b/dlls/vcomp/tests/vcomp.rc
new file mode 100644
index 0000000..c5f1d25
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.rc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "winuser.h"
+
+/* @makedep: vcomp.manifest */
+1 RT_MANIFEST vcomp.manifest
--
2.4.5

View File

@ -0,0 +1,168 @@
From f455eb53b0d527874fb95bdc652d1a31cd8fa93a 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(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 9de9721..400f93a 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -174,6 +174,96 @@ void CDECL _vcomp_single_end(void)
TRACE("stub\n");
}
+void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last, int step, BOOL forward,
+ unsigned int *begin, unsigned int *end)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+ unsigned int iterations, per_thread, remaining;
+ DWORD num_threads, thread_num;
+
+ TRACE("(%d, %d, %d, %d, %p, %p)\n", first, last, step, forward, begin, end);
+
+ num_threads = team_info->num_threads;
+ thread_num = thread_info->thread_num;
+
+ if (num_threads == 1)
+ {
+ *begin = first;
+ *end = last;
+ return;
+ }
+
+ if (step <= 0)
+ {
+ *begin = 0;
+ *end = forward ? -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;
+ }
+ 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;
+ }
+}
+
+void CDECL _vcomp_for_static_end(void)
+{
+ TRACE("()\n");
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
static DWORD WINAPI _vcomp_fork_worker(void *param)
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index d446574..b14edca 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end()
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ cdecl _vcomp_for_static_simple_init(long long long long ptr ptr)
@ stub _vcomp_for_static_simple_init_i8
@ varargs _vcomp_fork(long long ptr)
@ stub _vcomp_get_thread_num
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 2c04e91..89e0972 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ 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
@ 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 2c04e91..89e0972 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ 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
@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
--
2.4.5

View File

@ -0,0 +1,275 @@
From af8411c2c51708c2edbc620b3d775bf5a08144f9 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 | 228 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 228 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 5c6a861..1971b6d 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -23,8 +23,15 @@
static const int is_win64 = (sizeof(void *) > sizeof(int));
static HMODULE hvcomp = 0;
+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 int (CDECL *pomp_get_max_threads)(void);
+static int (CDECL *pomp_get_num_threads)(void);
+static int (CDECL *pomp_get_thread_num)(void);
+static void (CDECL *pomp_set_num_threads)(int num_threads);
#define VCOMP_GET_PROC(func) \
do \
@@ -43,8 +50,14 @@ static BOOL init_vcomp(void)
return FALSE;
}
+ 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(omp_get_max_threads);
+ VCOMP_GET_PROC(omp_get_num_threads);
+ VCOMP_GET_PROC(omp_get_thread_num);
+ VCOMP_GET_PROC(omp_set_num_threads);
return TRUE;
}
@@ -111,12 +124,227 @@ static void test_vcomp_fork(void)
}
}
+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())
return;
test_vcomp_fork();
+ test_vcomp_for_static_simple_init();
FreeLibrary(hvcomp);
}
--
2.4.5

View File

@ -0,0 +1,127 @@
From 721c89ed7aec4a9ae8f0a5f7b0efeee838c08985 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 19:19:00 +0200
Subject: vcomp: Implement _vcomp_for_static_init.
---
dlls/vcomp/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
4 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 400f93a..2eeea3b 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -259,6 +259,68 @@ void CDECL _vcomp_for_static_simple_init(unsigned int first, unsigned int last,
}
}
+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_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+ unsigned int iterations, num_chunks, per_thread, remaining;
+ DWORD num_threads, 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_info->num_threads;
+ thread_num = thread_info->thread_num;
+
+ 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;
+
+ *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;
+ }
+}
+
void CDECL _vcomp_for_static_end(void)
{
TRACE("()\n");
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index b14edca..8bc66e8 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end()
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr)
@ stub _vcomp_for_static_init_i8
@ 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 89e0972..f008e2e 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
@ 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 89e0972..f008e2e 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
@ 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
--
2.4.5

View File

@ -0,0 +1,243 @@
From 9cea1ba140eb5d8ecd70eab4a68e309cd80fd454 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 1971b6d..96806fd 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -25,6 +25,8 @@ static const int is_win64 = (sizeof(void *) > sizeof(int));
static HMODULE hvcomp = 0;
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, ...);
@@ -52,6 +54,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(omp_get_max_threads);
@@ -338,6 +341,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())
@@ -345,6 +543,7 @@ START_TEST(vcomp)
test_vcomp_fork();
test_vcomp_for_static_simple_init();
+ test_vcomp_for_static_init();
FreeLibrary(hvcomp);
}
--
2.4.5

View File

@ -0,0 +1,66 @@
From 8732b345bcab27edc68eda1ab35095d72a817899 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 19:38:24 +0200
Subject: vcomp: Implement _vcomp_barrier.
---
dlls/vcomp/main.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 2eeea3b..4f3471a 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -68,6 +68,10 @@ struct vcomp_team_info
unsigned int nargs;
void *wrapper;
__ms_va_list valist;
+
+ /* barrier */
+ DWORD barrier;
+ DWORD barrier_count;
};
static inline struct vcomp_thread_info *vcomp_get_thread_info(void)
@@ -154,7 +158,28 @@ void CDECL omp_set_num_threads(int num_threads)
void CDECL _vcomp_barrier(void)
{
- TRACE("stub\n");
+ struct vcomp_team_info *team_info;
+
+ TRACE("()\n");
+
+ team_info = vcomp_get_team_info();
+ EnterCriticalSection(&vcomp_section);
+
+ team_info->barrier_count++;
+ if (team_info->barrier_count >= team_info->num_threads)
+ {
+ team_info->barrier++;
+ team_info->barrier_count = 0;
+ WakeAllConditionVariable(&team_info->cond);
+ }
+ else
+ {
+ DWORD barrier = team_info->barrier;
+ while (team_info->barrier == barrier)
+ SleepConditionVariableCS(&team_info->cond, &vcomp_section, INFINITE);
+ }
+
+ LeaveCriticalSection(&vcomp_section);
}
void CDECL _vcomp_set_num_threads(int num_threads)
@@ -385,6 +410,8 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_info.nargs = nargs;
team_info.wrapper = wrapper;
__ms_va_start(team_info.valist, wrapper);
+ team_info.barrier = 0;
+ team_info.barrier_count = 0;
/* Initialize members of thread_info. */
list_init(&thread_info.entry);
--
2.4.5

View File

@ -0,0 +1,71 @@
From aad24232add010020898eaa1a0934cb353c123f2 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 4f3471a..fccad93 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -351,6 +351,12 @@ void CDECL _vcomp_for_static_end(void)
TRACE("()\n");
}
+int CDECL omp_in_parallel(void)
+{
+ TRACE("()\n");
+ return vcomp_get_team_info() != NULL;
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
static DWORD WINAPI _vcomp_fork_worker(void *param)
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 8bc66e8..156233f 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 f008e2e..dd276d0 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 f008e2e..dd276d0 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,244 @@
From 77d6daebca21cfb4209a8281abac2b9db0d7a1b4 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 11 Jul 2015 21:29:41 +0200
Subject: vcomp: Implement _vcomp_sections_init and _vcomp_sections_next and
add tests.
---
dlls/vcomp/main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/vcomp.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 ++--
dlls/vcomp100/vcomp100.spec | 4 ++--
dlls/vcomp90/vcomp90.spec | 4 ++--
5 files changed, 104 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index fccad93..db47ff6 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -56,6 +56,9 @@ struct vcomp_thread_info
/* current task */
struct vcomp_team_info *team;
DWORD thread_num;
+
+ /* section */
+ DWORD section;
};
struct vcomp_team_info
@@ -72,6 +75,11 @@ struct vcomp_team_info
/* barrier */
DWORD barrier;
DWORD barrier_count;
+
+ /* section */
+ DWORD section;
+ DWORD num_sections;
+ DWORD section_index;
};
static inline struct vcomp_thread_info *vcomp_get_thread_info(void)
@@ -357,6 +365,43 @@ int CDECL omp_in_parallel(void)
return vcomp_get_team_info() != NULL;
}
+void CDECL _vcomp_sections_init(int n)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+
+ TRACE("(%d)\n", n);
+
+ EnterCriticalSection(&vcomp_section);
+ thread_info->section++;
+ if ((int)(thread_info->section - team_info->section) > 0)
+ {
+ /* first thread in a new section */
+ team_info->section = thread_info->section;
+ team_info->num_sections = n;
+ team_info->section_index = 0;
+ }
+ LeaveCriticalSection(&vcomp_section);
+}
+
+int CDECL _vcomp_sections_next(void)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+ int i = -1;
+
+ TRACE("()\n");
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_info->section == team_info->section &&
+ team_info->section_index < team_info->num_sections)
+ {
+ i = team_info->section_index++;
+ }
+ LeaveCriticalSection(&vcomp_section);
+ return i;
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
static DWORD WINAPI _vcomp_fork_worker(void *param)
@@ -418,12 +463,14 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
__ms_va_start(team_info.valist, wrapper);
team_info.barrier = 0;
team_info.barrier_count = 0;
+ team_info.section = -1;
/* Initialize members of thread_info. */
list_init(&thread_info.entry);
InitializeConditionVariable(&thread_info.cond);
thread_info.team = &team_info;
thread_info.thread_num = 0;
+ thread_info.section = 0;
if (parallel)
{
@@ -439,6 +486,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
list_add_tail(&thread_info.entry, &info->entry);
info->team = &team_info;
info->thread_num = team_info.num_threads++;
+ info->section = 0;
WakeAllConditionVariable(&info->cond);
}
@@ -455,6 +503,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
InitializeConditionVariable(&info->cond);
info->team = &team_info;
info->thread_num = team_info.num_threads;
+ info->section = 0;
thread = CreateThread(NULL, 0, _vcomp_fork_worker, info, 0, NULL);
if (!thread)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 96806fd..902a836 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -30,6 +30,8 @@ static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, i
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);
static int (CDECL *pomp_get_max_threads)(void);
static int (CDECL *pomp_get_num_threads)(void);
static int (CDECL *pomp_get_thread_num)(void);
@@ -57,6 +59,8 @@ static BOOL init_vcomp(void)
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);
+ VCOMP_GET_PROC(_vcomp_sections_next);
VCOMP_GET_PROC(omp_get_max_threads);
VCOMP_GET_PROC(omp_get_num_threads);
VCOMP_GET_PROC(omp_get_thread_num);
@@ -536,6 +540,50 @@ static void test_vcomp_for_static_init(void)
}
}
+static void CDECL _test_vcomp_sections_init(LONG *a, LONG *b, LONG *c)
+{
+ int i;
+
+ p_vcomp_sections_init(20);
+ while ((i = p_vcomp_sections_next()) != -1)
+ {
+ InterlockedIncrement(a);
+ Sleep(50);
+ }
+
+ p_vcomp_sections_init(30);
+ while ((i = p_vcomp_sections_next()) != -1)
+ {
+ InterlockedIncrement(b);
+ Sleep(50);
+ }
+
+ p_vcomp_sections_init(40);
+ while ((i = p_vcomp_sections_next()) != -1)
+ {
+ InterlockedIncrement(c);
+ Sleep(50);
+ }
+}
+
+static void test_vcomp_sections_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_sections_init, &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);
+ }
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -544,6 +592,7 @@ START_TEST(vcomp)
test_vcomp_fork();
test_vcomp_for_static_simple_init();
test_vcomp_for_static_init();
+ test_vcomp_sections_init();
FreeLibrary(hvcomp);
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 156233f..7083ce4 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long)
+@ cdecl _vcomp_sections_next()
@ cdecl _vcomp_set_num_threads(long)
@ cdecl _vcomp_single_begin(long)
@ cdecl _vcomp_single_end()
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index dd276d0..56c7ae3 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long) vcomp._vcomp_sections_init
+@ cdecl _vcomp_sections_next() vcomp._vcomp_sections_next
@ cdecl _vcomp_set_num_threads(long) vcomp._vcomp_set_num_threads
@ cdecl _vcomp_single_begin(long) vcomp._vcomp_single_begin
@ cdecl _vcomp_single_end() vcomp._vcomp_single_end
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index dd276d0..56c7ae3 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long) vcomp._vcomp_sections_init
+@ cdecl _vcomp_sections_next() vcomp._vcomp_sections_next
@ cdecl _vcomp_set_num_threads(long) vcomp._vcomp_set_num_threads
@ cdecl _vcomp_single_begin(long) vcomp._vcomp_single_begin
@ cdecl _vcomp_single_end() vcomp._vcomp_single_end
--
2.4.5

View File

@ -0,0 +1,296 @@
From f29610acbf9ce393b772520f6041acce9d1aefd8 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 db47ff6..3a1e9ee 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -59,6 +59,9 @@ struct vcomp_thread_info
/* section */
DWORD section;
+
+ /* dynamic */
+ DWORD dynamic;
};
struct vcomp_team_info
@@ -80,6 +83,15 @@ struct vcomp_team_info
DWORD section;
DWORD num_sections;
DWORD section_index;
+
+ /* dynamic */
+ DWORD dynamic;
+ DWORD dynamic_forward;
+ DWORD dynamic_first;
+ DWORD dynamic_iterations;
+ int dynamic_step;
+ DWORD dynamic_chunksize;
+ DWORD dynamic_min_chunksize;
};
static inline struct vcomp_thread_info *vcomp_get_thread_info(void)
@@ -402,6 +414,83 @@ int CDECL _vcomp_sections_next(void)
return i;
}
+void CDECL _vcomp_for_dynamic_init(int flags, int first, int last, int step, int chunksize)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->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_info->dynamic++;
+ if ((int)(thread_info->dynamic - team_info->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_info->dynamic = thread_info->dynamic;
+ team_info->dynamic_forward = forward;
+ team_info->dynamic_first = first;
+ team_info->dynamic_iterations = iterations;
+ team_info->dynamic_step = step;
+ team_info->dynamic_chunksize = max(1, iterations / team_info->num_threads);
+ team_info->dynamic_min_chunksize = max(1, chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+}
+
+int CDECL _vcomp_for_dynamic_next(int *begin, int *end)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+ unsigned int iterations = 0;
+
+ TRACE("(%p, %p)\n", begin, end);
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_info->dynamic == team_info->dynamic &&
+ team_info->dynamic_iterations != 0)
+ {
+ iterations = min(team_info->dynamic_iterations, team_info->dynamic_chunksize);
+ team_info->dynamic_iterations -= iterations;
+
+ if (team_info->dynamic_forward)
+ {
+ *begin = team_info->dynamic_first;
+ *end = team_info->dynamic_first + (iterations - 1) * team_info->dynamic_step;
+ team_info->dynamic_first += iterations * team_info->dynamic_step;
+ }
+ else
+ {
+ *begin = team_info->dynamic_first;
+ *end = team_info->dynamic_first - (iterations - 1) * team_info->dynamic_step;
+ team_info->dynamic_first -= iterations * team_info->dynamic_step;
+ }
+
+ team_info->dynamic_chunksize =
+ max((team_info->dynamic_chunksize * 3 + 2)/4, team_info->dynamic_min_chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+
+ return (iterations != 0);
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
static DWORD WINAPI _vcomp_fork_worker(void *param)
@@ -464,6 +553,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_info.barrier = 0;
team_info.barrier_count = 0;
team_info.section = -1;
+ team_info.dynamic = -1;
/* Initialize members of thread_info. */
list_init(&thread_info.entry);
@@ -471,6 +561,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
thread_info.team = &team_info;
thread_info.thread_num = 0;
thread_info.section = 0;
+ thread_info.dynamic = 0;
if (parallel)
{
@@ -487,6 +578,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
info->team = &team_info;
info->thread_num = team_info.num_threads++;
info->section = 0;
+ info->dynamic = 0;
WakeAllConditionVariable(&info->cond);
}
@@ -504,6 +596,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
info->team = &team_info;
info->thread_num = team_info.num_threads;
info->section = 0;
+ info->dynamic = 0;
thread = CreateThread(NULL, 0, _vcomp_fork_worker, info, 0, NULL);
if (!thread)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 902a836..4273680 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -24,6 +24,8 @@ static const int is_win64 = (sizeof(void *) > sizeof(int));
static HMODULE hvcomp = 0;
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);
@@ -55,6 +57,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);
@@ -584,6 +588,54 @@ static void test_vcomp_sections_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())
@@ -593,6 +645,7 @@ START_TEST(vcomp)
test_vcomp_for_static_simple_init();
test_vcomp_for_static_init();
test_vcomp_sections_init();
+ test_vcomp_for_dynamic_init();
FreeLibrary(hvcomp);
}
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 @@
Fixes: [31640] Implement various vcomp functions

View File

@ -1,484 +0,0 @@
From 90156f8a04061c7d0629f46dd640c09bccb0122c Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Fri, 12 Oct 2012 22:31:39 -0700
Subject: vcomp: single-threaded implementation of _vcomp_fork
---
configure.ac | 3 +-
dlls/vcomp/Makefile.in | 1 +
dlls/vcomp/fork.c | 161 ++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/Makefile.in | 8 ++
dlls/vcomp/tests/fork.c | 153 ++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/vcomp.manifest | 21 ++++++
dlls/vcomp/tests/vcomp.rc | 22 ++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
10 files changed, 371 insertions(+), 4 deletions(-)
create mode 100644 dlls/vcomp/fork.c
create mode 100644 dlls/vcomp/tests/Makefile.in
create mode 100644 dlls/vcomp/tests/fork.c
create mode 100644 dlls/vcomp/tests/vcomp.manifest
create mode 100644 dlls/vcomp/tests/vcomp.rc
diff --git a/configure.ac b/configure.ac
index a931730..8c51410 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3290,7 +3290,8 @@ WINE_CONFIG_DLL(uxtheme,,[implib])
WINE_CONFIG_TEST(dlls/uxtheme/tests)
WINE_CONFIG_DLL(vbscript,,[clean])
WINE_CONFIG_TEST(dlls/vbscript/tests,[clean])
-WINE_CONFIG_DLL(vcomp)
+WINE_CONFIG_DLL(vcomp,,[implib])
+WINE_CONFIG_TEST(dlls/vcomp/tests)
WINE_CONFIG_DLL(vcomp100)
WINE_CONFIG_DLL(vcomp90)
WINE_CONFIG_DLL(vdhcp.vxd,enable_win16)
diff --git a/dlls/vcomp/Makefile.in b/dlls/vcomp/Makefile.in
index a54a86f..5bd0074 100644
--- a/dlls/vcomp/Makefile.in
+++ b/dlls/vcomp/Makefile.in
@@ -1,4 +1,5 @@
MODULE = vcomp.dll
C_SRCS = \
+ fork.c \
main.c
diff --git a/dlls/vcomp/fork.c b/dlls/vcomp/fork.c
new file mode 100644
index 0000000..13a7b56
--- /dev/null
+++ b/dlls/vcomp/fork.c
@@ -0,0 +1,161 @@
+/*
+ * vcomp fork/join implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+
+void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
+
+/* When Visual C encounters a '#pragma omp parallel' directive,
+ * it wraps the next statement in a function, and passes the address
+ * of the wrapper function to _vcomp_fork, which calls that function--
+ * possibly after spawning extra copies on new threads.
+ *
+ * If the directive has an if() clause, the value passed to the if clause
+ * is passed as the first argument to _vcomp_fork; if it is false,
+ * or if OMP_NUM_THREADS is 1, or omp_set_num_threads(1) has been called,
+ * or if too many threads are already in use, native _vcomp_fork doesn't spawn
+ * any extra threads, it just calls the wrapper function.
+ *
+ * The OpenMP standard allows implementations to fall back to executing
+ * everything on a single thread, so that's what we'll do for now;
+ * our _vcomp_fork will simply call the wrapper function.
+ * That's enough to make many, but not all, apps run correctly.
+ *
+ * If the statement being wrapped refers to variables from an outer scope,
+ * Visual C passes them to _vcomp_fork and thence the wrapper as follows:
+ * - Unchanging ints are always passed by value
+ * - Unchanging floats are passed by value on i386, but by reference on amd64
+ * - Everything else is passed by reference
+ *
+ * The call to _vcomp_fork is synthesized by the compiler;
+ * user code isn't even aware that a call is being made. And the callee
+ * (_vcomp_fork) is also under Visual C's control. Thus the compiler
+ * is free to use a nonstandard ABI for this call. And it does, in that
+ * float arguments are not promoted to double. (Some apps
+ * that use floats would probably be very annoyed if they were silently
+ * promoted to doubles by "#pragma omp parallel".)
+ *
+ * The call from _vcomp_fork to the wrapper function also doesn't quite
+ * follow the normal win32/win64 calling conventions:
+ * 1) Since Visual C never passes floats or doubles by value to the
+ * wrapper on amd64, native vcomp.dll does not copy floating point parameters
+ * to registers, contrary to the win64 ABI. Manual tests confirm this.
+ * 2) Since the wrapper itself doesn't use varargs at all, _vcomp_fork can't
+ * just pass an __ms_va_list; it has to push the arguments onto the stack again.
+ * This can't be done in C, so we use assembly in _vcomp_fork_call_wrapper.
+ * (That function is a close copy of call_method in oleaut32/typelib.c,
+ * with unneeded instructions removed.)
+ */
+
+void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
+{
+ __ms_va_list valist;
+ TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
+ __ms_va_start(valist, wrapper);
+ _vcomp_fork_call_wrapper(wrapper, nargs, valist);
+ __ms_va_end(valist);
+}
+
+#if defined(__i386__)
+__ASM_GLOBAL_FUNC( _vcomp_fork_call_wrapper,
+ "pushl %ebp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+ __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+ "movl %esp,%ebp\n\t"
+ __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+ "pushl %esi\n\t"
+ __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
+ "pushl %edi\n\t"
+ __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
+ "movl 12(%ebp),%edx\n\t"
+ "movl %esp,%edi\n\t"
+ "shll $2,%edx\n\t"
+ "jz 1f\n\t"
+ "subl %edx,%edi\n\t"
+ "andl $~15,%edi\n\t"
+ "movl %edi,%esp\n\t"
+ "movl 12(%ebp),%ecx\n\t"
+ "movl 16(%ebp),%esi\n\t"
+ "cld\n\t"
+ "rep; movsl\n"
+ "1:\tcall *8(%ebp)\n\t"
+ "leal -8(%ebp),%esp\n\t"
+ "popl %edi\n\t"
+ __ASM_CFI(".cfi_same_value %edi\n\t")
+ "popl %esi\n\t"
+ __ASM_CFI(".cfi_same_value %esi\n\t")
+ "popl %ebp\n\t"
+ __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+ __ASM_CFI(".cfi_same_value %ebp\n\t")
+ "ret" )
+
+#elif defined(__x86_64__)
+
+__ASM_GLOBAL_FUNC( _vcomp_fork_call_wrapper,
+ "pushq %rbp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
+ __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
+ "movq %rsp,%rbp\n\t"
+ __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
+ "pushq %rsi\n\t"
+ __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
+ "pushq %rdi\n\t"
+ __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
+ "movq %rcx,%rax\n\t"
+ "movq $4,%rcx\n\t"
+ "cmp %rcx,%rdx\n\t"
+ "cmovgq %rdx,%rcx\n\t"
+ "leaq 0(,%rcx,8),%rdx\n\t"
+ "subq %rdx,%rsp\n\t"
+ "andq $~15,%rsp\n\t"
+ "movq %rsp,%rdi\n\t"
+ "movq %r8,%rsi\n\t"
+ "rep; movsq\n\t"
+ "movq 0(%rsp),%rcx\n\t"
+ "movq 8(%rsp),%rdx\n\t"
+ "movq 16(%rsp),%r8\n\t"
+ "movq 24(%rsp),%r9\n\t"
+ "callq *%rax\n\t"
+ "leaq -16(%rbp),%rsp\n\t"
+ "popq %rdi\n\t"
+ __ASM_CFI(".cfi_same_value %rdi\n\t")
+ "popq %rsi\n\t"
+ __ASM_CFI(".cfi_same_value %rsi\n\t")
+ __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
+ "popq %rbp\n\t"
+ __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
+ __ASM_CFI(".cfi_same_value %rbp\n\t")
+ "ret")
+#else
+
+void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args)
+{
+ ERR("Not implemented for this architecture\n");
+}
+
+#endif
diff --git a/dlls/vcomp/tests/Makefile.in b/dlls/vcomp/tests/Makefile.in
new file mode 100644
index 0000000..81430a3
--- /dev/null
+++ b/dlls/vcomp/tests/Makefile.in
@@ -0,0 +1,8 @@
+TESTDLL = vcomp.dll
+IMPORTS = vcomp
+
+C_SRCS = \
+ fork.c
+
+RC_SRCS = \
+ vcomp.rc
diff --git a/dlls/vcomp/tests/fork.c b/dlls/vcomp/tests/fork.c
new file mode 100644
index 0000000..a6f176c
--- /dev/null
+++ b/dlls/vcomp/tests/fork.c
@@ -0,0 +1,153 @@
+/*
+ * Unit test suite for vcomp fork/join implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+
+static const int is_win64 = (sizeof(void *) > sizeof(int));
+
+static void WINAPIV (*p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
+static int CDECL (*pomp_get_max_threads)(void);
+
+#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
+
+static BOOL init(void)
+{
+ HMODULE vcomp = LoadLibraryA("vcomp.dll");
+ if (!vcomp)
+ {
+ win_skip("vcomp.dll not installed\n");
+ return FALSE;
+ }
+
+ GETFUNC(_vcomp_fork);
+ GETFUNC(omp_get_max_threads);
+
+ return TRUE;
+}
+
+/* Test whether a variety of types are passed correctly.
+ * Pass five of each because the first four parameters are
+ * handled differently on amd64, and we want to test both
+ * ways.
+ */
+
+static void CDECL _test_vcomp_fork_ptr_worker(LONG volatile *a, LONG volatile *b, LONG volatile *c, LONG volatile *d, LONG volatile *e)
+{
+ InterlockedIncrement(a);
+ InterlockedIncrement(b);
+ InterlockedIncrement(c);
+ InterlockedIncrement(d);
+ InterlockedIncrement(e);
+}
+
+static void test_vcomp_fork_ptr(void)
+{
+ LONG volatile a, b, c, d, e;
+ int n;
+
+ /* #pragma omp parallel if(FALSE) shared(a, b, c, d, e)
+ * { InterlockedIncrement(&a); ... InterlockedIncrement(&e); }
+ */
+ a=0; b=1; c=2; d=3; e=4;
+ p_vcomp_fork(FALSE, 5, _test_vcomp_fork_ptr_worker, &a, &b, &c, &d, &e);
+ ok(a == 1, "a == 1\n");
+ ok(b == 2, "a == 2\n");
+ ok(c == 3, "a == 3\n");
+ ok(d == 4, "a == 4\n");
+ ok(e == 5, "a == 5\n");
+
+ /* #pragma omp parallel if(TRUE) shared(a, b, c, d, e)
+ * { InterlockedIncrement(&a); ... InterlockedIncrement(&e); }
+ */
+ a=0; b=1; c=2; d=3; e=4;
+ n = pomp_get_max_threads();
+ p_vcomp_fork(TRUE, 5, _test_vcomp_fork_ptr_worker, &a, &b, &c, &d, &e);
+ ok(a > 0 && a <= (n+0), "a > 0 && a <= (n+0)\n");
+ ok(b > 1 && b <= (n+1), "b > 1 && b <= (n+1)\n");
+ ok(c > 2 && c <= (n+2), "c > 2 && c <= (n+2)\n");
+ ok(d > 3 && d <= (n+3), "d > 3 && d <= (n+3)\n");
+ ok(e > 4 && e <= (n+4), "e > 4 && e <= (n+4)\n");
+}
+
+static void CDECL _test_vcomp_fork_uintptr_worker(UINT_PTR a, UINT_PTR b, UINT_PTR c, UINT_PTR d, UINT_PTR e)
+{
+ ok(a == 1, "expected a == 1\n");
+ ok(b == MAXUINT_PTR-2, "expected b == MAXUINT_PTR-2\n");
+ ok(c == 3, "expected c == 3\n");
+ ok(d == MAXUINT_PTR-4, "expected d == MAXUINT_PTR-4\n");
+ ok(e == 5, "expected e == 5\n");
+}
+
+static void test_vcomp_fork_uintptr(void)
+{
+ /* test_vcomp_fork_ptr ought to have been enough, but probably
+ * didn't vary all the bits of the high word, so do that here.
+ */
+ p_vcomp_fork(TRUE, 5, _test_vcomp_fork_uintptr_worker, \
+ (UINT_PTR)1, (UINT_PTR)(MAXUINT_PTR-2), \
+ (UINT_PTR)3, (UINT_PTR)(MAXUINT_PTR)-4, (UINT_PTR) 5);
+}
+
+static void CDECL _test_vcomp_fork_float_worker(float a, float b, float c, float d, float e)
+{
+ ok(1.4999 < a && a < 1.5001, "expected a == 1.5, got %f\n", a);
+ ok(2.4999 < b && b < 2.5001, "expected b == 2.5, got %f\n", b);
+ ok(3.4999 < c && c < 3.5001, "expected c == 3.5, got %f\n", c);
+ ok(4.4999 < d && d < 4.5001, "expected d == 4.5, got %f\n", d);
+ ok(5.4999 < e && e < 5.5001, "expected e == 5.5, got %f\n", e);
+}
+
+static void test_vcomp_fork_float(void)
+{
+ static void CDECL (*p_vcomp_fork_f5)(BOOL, int, void *, float, float, float, float, float);
+
+ if (is_win64)
+ {
+ skip("Skipping float test on x86_64.\n");
+ return;
+ }
+
+ /*
+ * 32 bit Visual C sometimes passes 32 bit floats by value to
+ * the wrapper, so verify that here.
+ *
+ * x86-64 Visual C has not yet been observed passing 32 bit floats by
+ * value to the wrapper, and indeed _vcomp_fork does not even copy the
+ * first four args to floating point registers, so this test fails
+ * on x86-64 for the first four arguments even on native.
+ * Therefore don't run it. (It's hard to write a reliable test to show
+ * this, since the floating point registers might just happen
+ * to have the right values once in a blue moon.)
+ */
+
+ /* Avoid float promotion by using a prototype tailored for this call */
+ p_vcomp_fork_f5 = (void *)p_vcomp_fork;
+ p_vcomp_fork_f5(TRUE, 5, _test_vcomp_fork_float_worker, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f);
+}
+
+START_TEST(fork)
+{
+ if (!init())
+ return;
+
+ test_vcomp_fork_ptr();
+ test_vcomp_fork_uintptr();
+ test_vcomp_fork_float();
+}
diff --git a/dlls/vcomp/tests/vcomp.manifest b/dlls/vcomp/tests/vcomp.manifest
new file mode 100644
index 0000000..6c8bd91
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.manifest
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity
+ type="win32"
+ name="Wine.vcomp.Test"
+ version="1.0.0.0"
+ processorArchitecture="*"
+ />
+<description>Wine vcomp test suite</description>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.VC80.OpenMP"
+ version="8.0.50608.0"
+ processorArchitecture="*"
+ publicKeyToken="1fc8b3b9a1e18e3b"
+ />
+ </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/dlls/vcomp/tests/vcomp.rc b/dlls/vcomp/tests/vcomp.rc
new file mode 100644
index 0000000..c5f1d25
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.rc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "winuser.h"
+
+/* @makedep: vcomp.manifest */
+1 RT_MANIFEST vcomp.manifest
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 306dd15..d446574 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr)
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 39cf91c..2c04e91 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 39cf91c..2c04e91 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -64,7 +64,7 @@
@ stub _vcomp_for_static_init_i8
@ stub _vcomp_for_static_simple_init
@ stub _vcomp_for_static_simple_init_i8
-@ stub _vcomp_fork
+@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
@ stub _vcomp_leave_critsect
@ stub _vcomp_master_barrier
--
2.2.1

View File

@ -1,233 +0,0 @@
From c0369b34efc51c992be270a9e4eaef33b3cbf3d5 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Sun, 14 Oct 2012 20:40:31 -0700
Subject: vcomp: better stubs for _vcomp_for_static_simple_init,
_vcomp_for_static_end
---
dlls/vcomp/Makefile.in | 3 +-
dlls/vcomp/tests/Makefile.in | 3 +-
dlls/vcomp/tests/work.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 +--
dlls/vcomp/work.c | 41 ++++++++++++++++++++++
dlls/vcomp100/vcomp100.spec | 4 +--
dlls/vcomp90/vcomp90.spec | 4 +--
7 files changed, 134 insertions(+), 8 deletions(-)
create mode 100644 dlls/vcomp/tests/work.c
create mode 100644 dlls/vcomp/work.c
diff --git a/dlls/vcomp/Makefile.in b/dlls/vcomp/Makefile.in
index 5bd0074..dfff21a 100644
--- a/dlls/vcomp/Makefile.in
+++ b/dlls/vcomp/Makefile.in
@@ -2,4 +2,5 @@ MODULE = vcomp.dll
C_SRCS = \
fork.c \
- main.c
+ main.c \
+ work.c
diff --git a/dlls/vcomp/tests/Makefile.in b/dlls/vcomp/tests/Makefile.in
index 81430a3..f1479ab 100644
--- a/dlls/vcomp/tests/Makefile.in
+++ b/dlls/vcomp/tests/Makefile.in
@@ -2,7 +2,8 @@ TESTDLL = vcomp.dll
IMPORTS = vcomp
C_SRCS = \
- fork.c
+ fork.c \
+ work.c
RC_SRCS = \
vcomp.rc
diff --git a/dlls/vcomp/tests/work.c b/dlls/vcomp/tests/work.c
new file mode 100644
index 0000000..e8d3f2c
--- /dev/null
+++ b/dlls/vcomp/tests/work.c
@@ -0,0 +1,83 @@
+/*
+ * Unit test suite for vcomp work-sharing implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/test.h"
+
+static void WINAPIV (*p_vcomp_fork)(DWORD parallel, int nargs, void *helper, ...);
+static void CDECL (*p_vcomp_for_static_end)(void);
+static void CDECL (*p_vcomp_for_static_simple_init)(int first, int last, int mystep, int step, int *pfirst, int *plast);
+
+#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
+
+static BOOL init(void)
+{
+ HMODULE vcomp = LoadLibraryA("vcomp.dll");
+ if (!vcomp)
+ {
+ win_skip("vcomp.dll not installed\n");
+ return FALSE;
+ }
+
+ GETFUNC(_vcomp_fork);
+ GETFUNC(_vcomp_for_static_end);
+ GETFUNC(_vcomp_for_static_simple_init);
+
+ return TRUE;
+}
+
+static LONG volatile ncalls;
+static LONG volatile nsum;
+
+static void CDECL _test_vcomp_for_static_simple_init_worker(void)
+{
+ int i, my_limit;
+
+ InterlockedIncrement(&ncalls);
+
+ /* for (i=0; i<=12; i++) */
+ p_vcomp_for_static_simple_init(0, 12, 1, 1, &i, &my_limit);
+
+ while (i <= my_limit)
+ {
+ int j;
+ for (j=0; j<i; j++)
+ InterlockedIncrement(&nsum);
+ i++;
+ }
+
+ p_vcomp_for_static_end();
+}
+
+static void test_vcomp_for_static_simple_init(void)
+{
+ ncalls = 0;
+ nsum = 0;
+ p_vcomp_fork(1, 0, _test_vcomp_for_static_simple_init_worker);
+ ok(ncalls >= 1, "expected >= 1 call, got %d\n", ncalls);
+ ok(nsum == 6*13, "expected sum 6*13, got %d\n", nsum);
+}
+
+START_TEST(work)
+{
+ if (!init())
+ return;
+
+ test_vcomp_for_static_simple_init();
+}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index d446574..b14edca 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end()
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ cdecl _vcomp_for_static_simple_init(long long long long ptr ptr)
@ stub _vcomp_for_static_simple_init_i8
@ varargs _vcomp_fork(long long ptr)
@ stub _vcomp_get_thread_num
diff --git a/dlls/vcomp/work.c b/dlls/vcomp/work.c
new file mode 100644
index 0000000..0f9ff78
--- /dev/null
+++ b/dlls/vcomp/work.c
@@ -0,0 +1,41 @@
+/*
+ * vcomp work-sharing implementation
+ *
+ * Copyright 2012 Dan Kegel
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+
+void CDECL _vcomp_for_static_simple_init(int first, int last, int mystep, int step, int *pfirst, int *plast)
+{
+ TRACE("(%d, %d, %d, %d, %p, %p): stub\n", first, last, mystep, step, pfirst, plast);
+ *pfirst = first;
+ *plast = last;
+}
+
+void CDECL _vcomp_for_static_end(void)
+{
+ TRACE("stub\n");
+}
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 2c04e91..89e0972 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ 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
@ 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 2c04e91..89e0972 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -59,10 +59,10 @@
@ stub _vcomp_for_dynamic_init_i8
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
-@ stub _vcomp_for_static_end
+@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
@ stub _vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
-@ stub _vcomp_for_static_simple_init
+@ 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
@ varargs _vcomp_fork(long long ptr) vcomp._vcomp_fork
@ stub _vcomp_get_thread_num
--
2.2.1

View File

@ -1,153 +0,0 @@
From fadfe0d8a2483066f6f0137b2fb6d6efa3090db8 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Sun, 14 Oct 2012 20:42:35 -0700
Subject: vcomp: better stub for _vcomp_for_static_init
---
dlls/vcomp/tests/work.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp/work.c | 11 +++++++++++
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
5 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/tests/work.c b/dlls/vcomp/tests/work.c
index e8d3f2c..2a76227 100644
--- a/dlls/vcomp/tests/work.c
+++ b/dlls/vcomp/tests/work.c
@@ -22,6 +22,7 @@
static void WINAPIV (*p_vcomp_fork)(DWORD parallel, int nargs, void *helper, ...);
static void CDECL (*p_vcomp_for_static_end)(void);
+static void CDECL (*p_vcomp_for_static_init)(int first, int last, int mystep, int chunksize, int *pnloops, int *pfirst, int *plast, int *pchunksize, int *pfinalchunkstart);
static void CDECL (*p_vcomp_for_static_simple_init)(int first, int last, int mystep, int step, int *pfirst, int *plast);
#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
@@ -37,6 +38,7 @@ static BOOL init(void)
GETFUNC(_vcomp_fork);
GETFUNC(_vcomp_for_static_end);
+ GETFUNC(_vcomp_for_static_init);
GETFUNC(_vcomp_for_static_simple_init);
return TRUE;
@@ -45,6 +47,48 @@ static BOOL init(void)
static LONG volatile ncalls;
static LONG volatile nsum;
+static void CDECL _test_vcomp_for_static_init_worker(void)
+{
+ const int my_start = 0;
+ const int my_end = 12;
+ const int my_incr = 1;
+ const int my_chunksize = 1;
+ int nloops, chunkstart, chunkend, chunksize, finalchunkstart;
+
+ InterlockedIncrement(&ncalls);
+
+ /* for (i=0; i<=12; i++) */
+ p_vcomp_for_static_init(my_start, my_end, my_incr, my_chunksize,
+ &nloops, &chunkstart, &chunkend, &chunksize, &finalchunkstart);
+
+ do
+ {
+ int i;
+ if (chunkstart == finalchunkstart) chunkend = my_end;
+
+ for (i=chunkstart; i <= chunkend; i += my_incr)
+ {
+ int j;
+ for (j=0; j<i; j++)
+ InterlockedIncrement(&nsum);
+ }
+ chunkstart += chunksize;
+ chunkend += chunksize;
+ }
+ while (--nloops > 0);
+
+ p_vcomp_for_static_end();
+}
+
+static void test_vcomp_for_static_init(void)
+{
+ ncalls = 0;
+ nsum = 0;
+ p_vcomp_fork(1, 0, _test_vcomp_for_static_init_worker);
+ ok(ncalls >= 1, "expected >= 1 call, got %d\n", ncalls);
+ ok(nsum == 6*13, "expected sum 6*13, got %d\n", nsum);
+}
+
static void CDECL _test_vcomp_for_static_simple_init_worker(void)
{
int i, my_limit;
@@ -79,5 +123,6 @@ START_TEST(work)
if (!init())
return;
+ test_vcomp_for_static_init();
test_vcomp_for_static_simple_init();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index b14edca..8bc66e8 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end()
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr)
@ stub _vcomp_for_static_init_i8
@ cdecl _vcomp_for_static_simple_init(long long long long ptr ptr)
@ stub _vcomp_for_static_simple_init_i8
diff --git a/dlls/vcomp/work.c b/dlls/vcomp/work.c
index 0f9ff78..82df26e 100644
--- a/dlls/vcomp/work.c
+++ b/dlls/vcomp/work.c
@@ -28,6 +28,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+void CDECL _vcomp_for_static_init(int first, int last, int mystep, int chunksize, int *pnloops, int *pfirst, int *plast, int *pchunksize, int *pfinalchunkstart)
+{
+ TRACE("(%d, %d, %d, %d, %p, %p, %p, %p, %p): stub\n",
+ first, last, mystep, chunksize, pnloops, pfirst, plast, pchunksize, pfinalchunkstart);
+ *pfirst = first;
+ *plast = last;
+ *pfinalchunkstart = last;
+ *pnloops = 1;
+ *pchunksize = 0; /* moot, since nloops=1 */
+}
+
void CDECL _vcomp_for_static_simple_init(int first, int last, int mystep, int step, int *pfirst, int *plast)
{
TRACE("(%d, %d, %d, %d, %p, %p): stub\n", first, last, mystep, step, pfirst, plast);
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 89e0972..f008e2e 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
@ 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 89e0972..f008e2e 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -60,7 +60,7 @@
@ stub _vcomp_for_dynamic_next
@ stub _vcomp_for_dynamic_next_i8
@ cdecl _vcomp_for_static_end() vcomp._vcomp_for_static_end
-@ stub _vcomp_for_static_init
+@ cdecl _vcomp_for_static_init(long long long long ptr ptr ptr ptr ptr) vcomp._vcomp_for_static_init
@ stub _vcomp_for_static_init_i8
@ 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
--
2.2.1

View File

@ -1,254 +0,0 @@
From 659f7394d0c3e4c969e0b0f66689433fd133febd Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Wed, 17 Oct 2012 09:15:06 -0700
Subject: vcomp: implement omp_in_parallel
---
dlls/vcomp/fork.c | 32 +++++++++++++++++++++++++++++
dlls/vcomp/main.c | 12 +++++++++++
dlls/vcomp/tests/fork.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp/vcomp_private.h | 19 +++++++++++++++++
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
7 files changed, 116 insertions(+), 3 deletions(-)
create mode 100644 dlls/vcomp/vcomp_private.h
diff --git a/dlls/vcomp/fork.c b/dlls/vcomp/fork.c
index 13a7b56..49399c6 100644
--- a/dlls/vcomp/fork.c
+++ b/dlls/vcomp/fork.c
@@ -25,6 +25,22 @@
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
+#include "vcomp_private.h"
+
+struct vcomp_team
+{
+ struct vcomp_team *parent;
+};
+
+static inline struct vcomp_team *vcomp_get_team(void)
+{
+ return (struct vcomp_team *)TlsGetValue(vcomp_context_tls);
+}
+
+static inline void vcomp_set_team(struct vcomp_team *team)
+{
+ TlsSetValue(vcomp_context_tls, team);
+}
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
@@ -75,10 +91,18 @@ void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args)
void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
{
__ms_va_list valist;
+ struct vcomp_team team;
+
TRACE("(%d, %d, %p, ...)\n", ifval, nargs, wrapper);
+
+ team.parent = vcomp_get_team();
+ vcomp_set_team(&team);
+
__ms_va_start(valist, wrapper);
_vcomp_fork_call_wrapper(wrapper, nargs, valist);
__ms_va_end(valist);
+
+ vcomp_set_team(team.parent);
}
#if defined(__i386__)
@@ -159,3 +183,11 @@ void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args)
}
#endif
+
+int CDECL omp_in_parallel(void)
+{
+ int val = (vcomp_get_team() != NULL);
+
+ TRACE("returning %d\n", val);
+ return val;
+}
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index ab2a372..e37cf16 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -26,9 +26,12 @@
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
+#include "vcomp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+DWORD vcomp_context_tls;
+
int CDECL omp_get_dynamic(void)
{
TRACE("stub\n");
@@ -117,6 +120,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return FALSE; /* prefer native version */
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
+
+ if ((vcomp_context_tls = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ {
+ ERR("Failed to allocate TLS index\n");
+ return FALSE;
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ TlsFree(vcomp_context_tls);
break;
}
diff --git a/dlls/vcomp/tests/fork.c b/dlls/vcomp/tests/fork.c
index a6f176c..3d11504 100644
--- a/dlls/vcomp/tests/fork.c
+++ b/dlls/vcomp/tests/fork.c
@@ -24,6 +24,9 @@ static const int is_win64 = (sizeof(void *) > sizeof(int));
static void WINAPIV (*p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
static int CDECL (*pomp_get_max_threads)(void);
+static int CDECL (*pomp_get_num_threads)(void);
+static int CDECL (*pomp_in_parallel)(void);
+static void CDECL (*pomp_set_num_threads)(int);
#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
@@ -36,6 +39,9 @@ static BOOL init(void)
return FALSE;
}
+ GETFUNC(omp_get_num_threads);
+ GETFUNC(omp_in_parallel);
+ GETFUNC(omp_set_num_threads);
GETFUNC(_vcomp_fork);
GETFUNC(omp_get_max_threads);
@@ -142,6 +148,49 @@ static void test_vcomp_fork_float(void)
p_vcomp_fork_f5(TRUE, 5, _test_vcomp_fork_float_worker, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f);
}
+#define NLOOPS_SHORT 5
+#define SLEEP_MS_SHORT 50
+
+static void CDECL _test_omp_in_parallel_nested_worker(LONG volatile *psum)
+{
+ if (pomp_in_parallel())
+ InterlockedIncrement(psum);
+}
+
+static void CDECL _test_omp_in_parallel_worker(LONG volatile *psum)
+{
+ int i;
+ InterlockedIncrement(psum);
+ for (i=0; i<NLOOPS_SHORT; i++)
+ {
+ p_vcomp_fork(1, 1, _test_omp_in_parallel_nested_worker, psum);
+ if (pomp_in_parallel())
+ InterlockedIncrement(psum);
+ Sleep(SLEEP_MS_SHORT);
+ }
+}
+
+static void test_omp_in_parallel(void)
+{
+ int par;
+ int old_nt;
+ LONG volatile ncalls;
+
+ old_nt = pomp_get_num_threads();
+ pomp_set_num_threads(1);
+
+ ncalls = 0;
+ p_vcomp_fork(1, 1, _test_omp_in_parallel_worker, &ncalls);
+
+ ok(ncalls == 1 + 2 * NLOOPS_SHORT,
+ "omp_in_parallel false in parallel region?!\n");
+
+ par = pomp_in_parallel();
+ ok(par == 0, "omp_in_parallel true outside parallel region?!\n");
+
+ pomp_set_num_threads(old_nt);
+}
+
START_TEST(fork)
{
if (!init())
@@ -150,4 +199,5 @@ START_TEST(fork)
test_vcomp_fork_ptr();
test_vcomp_fork_uintptr();
test_vcomp_fork_float();
+ test_omp_in_parallel();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 8bc66e8..156233f 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/vcomp/vcomp_private.h b/dlls/vcomp/vcomp_private.h
new file mode 100644
index 0000000..50c4643
--- /dev/null
+++ b/dlls/vcomp/vcomp_private.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2015 Sebastian Lackner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern DWORD vcomp_context_tls DECLSPEC_HIDDEN;
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index f008e2e..dd276d0 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 f008e2e..dd276d0 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.2.1

View File

@ -1,309 +0,0 @@
From 26d179bd36c65f9f416eafa4b9245f51a6ba6ecd Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Mon, 15 Oct 2012 21:01:30 -0700
Subject: vcomp: better stubs for _vcomp_for_dynamic_init,
_vcomp_for_dynamic_next
---
dlls/vcomp/fork.c | 15 -----------
dlls/vcomp/tests/work.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 +--
dlls/vcomp/vcomp_private.h | 37 +++++++++++++++++++++++++
dlls/vcomp/work.c | 47 ++++++++++++++++++++++++++++++++
dlls/vcomp100/vcomp100.spec | 4 +--
dlls/vcomp90/vcomp90.spec | 4 +--
7 files changed, 156 insertions(+), 21 deletions(-)
diff --git a/dlls/vcomp/fork.c b/dlls/vcomp/fork.c
index 49399c6..5af2021 100644
--- a/dlls/vcomp/fork.c
+++ b/dlls/vcomp/fork.c
@@ -27,21 +27,6 @@
#include "wine/debug.h"
#include "vcomp_private.h"
-struct vcomp_team
-{
- struct vcomp_team *parent;
-};
-
-static inline struct vcomp_team *vcomp_get_team(void)
-{
- return (struct vcomp_team *)TlsGetValue(vcomp_context_tls);
-}
-
-static inline void vcomp_set_team(struct vcomp_team *team)
-{
- TlsSetValue(vcomp_context_tls, team);
-}
-
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
diff --git a/dlls/vcomp/tests/work.c b/dlls/vcomp/tests/work.c
index 2a76227..5abe0e1 100644
--- a/dlls/vcomp/tests/work.c
+++ b/dlls/vcomp/tests/work.c
@@ -21,12 +21,18 @@
#include "wine/test.h"
static void WINAPIV (*p_vcomp_fork)(DWORD parallel, int nargs, void *helper, ...);
+static void CDECL (*p_vcomp_for_dynamic_init)(int flags, int first, int last, int mystep, int chunksize);
+static int CDECL (*p_vcomp_for_dynamic_next)(int *pcounter, int *pchunklimit);
static void CDECL (*p_vcomp_for_static_end)(void);
static void CDECL (*p_vcomp_for_static_init)(int first, int last, int mystep, int chunksize, int *pnloops, int *pfirst, int *plast, int *pchunksize, int *pfinalchunkstart);
static void CDECL (*p_vcomp_for_static_simple_init)(int first, int last, int mystep, int step, int *pfirst, int *plast);
#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
+/* Matches definitions in ../vcomp_private.h */
+#define VCOMP_DYNAMIC_FOR_FLAGS_DOWN 0x0
+#define VCOMP_DYNAMIC_FOR_FLAGS_UP 0x40
+
static BOOL init(void)
{
HMODULE vcomp = LoadLibraryA("vcomp.dll");
@@ -37,6 +43,8 @@ static BOOL init(void)
}
GETFUNC(_vcomp_fork);
+ GETFUNC(_vcomp_for_dynamic_init);
+ GETFUNC(_vcomp_for_dynamic_next);
GETFUNC(_vcomp_for_static_end);
GETFUNC(_vcomp_for_static_init);
GETFUNC(_vcomp_for_static_simple_init);
@@ -47,6 +55,63 @@ static BOOL init(void)
static LONG volatile ncalls;
static LONG volatile nsum;
+static void CDECL _test_vcomp_for_dynamic_worker_up(void)
+{
+ int i, limit;
+
+ InterlockedIncrement(&ncalls);
+
+ /* pragma omp schedule(dynamic,16) */
+ /* for (i=0; i<=17; i++) */
+ p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FOR_FLAGS_UP, 0, 17, 1, 16);
+ while (p_vcomp_for_dynamic_next(&i, &limit))
+ {
+ for (; i<=limit; i++)
+ {
+ int j;
+ for (j=0; j<i; j++)
+ InterlockedIncrement(&nsum);
+ }
+ }
+}
+
+static void CDECL _test_vcomp_for_dynamic_worker_down(void)
+{
+ int i, limit;
+
+ InterlockedIncrement(&ncalls);
+
+ /* pragma omp schedule(dynamic,16) */
+ /* for (i=17; i>=0; i--) */
+ p_vcomp_for_dynamic_init(VCOMP_DYNAMIC_FOR_FLAGS_DOWN, 17, 0, 1, 16);
+ while (p_vcomp_for_dynamic_next(&i, &limit))
+ {
+ for (; i>=limit; i--)
+ {
+ int j;
+ for (j=0; j<i; j++)
+ InterlockedIncrement(&nsum);
+ }
+ }
+}
+
+static void test_vcomp_for_dynamic(void)
+{
+ /* for (i=0; i<=17; i++) nsum += i; */
+ ncalls = 0;
+ nsum = 0;
+ p_vcomp_fork(1, 0, _test_vcomp_for_dynamic_worker_up);
+ ok(ncalls >= 1, "expected >= 1 call, got %d\n", ncalls);
+ ok(nsum == 9*17, "expected sum 9*17, got %d\n", nsum);
+
+ /* for (i=17; i>=0; i--) nsum += i; */
+ ncalls = 0;
+ nsum = 0;
+ p_vcomp_fork(1, 0, _test_vcomp_for_dynamic_worker_down);
+ ok(ncalls >= 1, "expected >= 1 call, got %d\n", ncalls);
+ ok(nsum == 9*17, "expected sum 9*17, got %d\n", nsum);
+}
+
static void CDECL _test_vcomp_for_static_init_worker(void)
{
const int my_start = 0;
@@ -123,6 +188,7 @@ START_TEST(work)
if (!init())
return;
+ test_vcomp_for_dynamic();
test_vcomp_for_static_init();
test_vcomp_for_static_simple_init();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 156233f..f603660 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/vcomp/vcomp_private.h b/dlls/vcomp/vcomp_private.h
index 50c4643..d3a7005 100644
--- a/dlls/vcomp/vcomp_private.h
+++ b/dlls/vcomp/vcomp_private.h
@@ -1,4 +1,7 @@
/*
+ * vcmp wine internal private include file
+ *
+ * Copyright 2012 Dan Kegel
* Copyright 2015 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
@@ -16,4 +19,38 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#ifndef __WINE_VCOMP_PRIVATE_H
+#define __WINE_VCOMP_PRIVATE_H
+
+struct vcomp_team
+{
+ struct vcomp_team *parent;
+ union
+ {
+ struct
+ {
+ int counter;
+ int step;
+ int iterations_remaining;
+ int chunksize;
+ int flags;
+ } dyn_for;
+ } work;
+};
+
extern DWORD vcomp_context_tls DECLSPEC_HIDDEN;
+
+static inline struct vcomp_team *vcomp_get_team(void)
+{
+ return (struct vcomp_team *)TlsGetValue(vcomp_context_tls);
+}
+
+static inline void vcomp_set_team(struct vcomp_team *team)
+{
+ TlsSetValue(vcomp_context_tls, team);
+}
+
+#define VCOMP_DYNAMIC_FOR_FLAGS_DOWN 0x0
+#define VCOMP_DYNAMIC_FOR_FLAGS_UP 0x40
+
+#endif
diff --git a/dlls/vcomp/work.c b/dlls/vcomp/work.c
index 82df26e..87bce93 100644
--- a/dlls/vcomp/work.c
+++ b/dlls/vcomp/work.c
@@ -25,9 +25,56 @@
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
+#include "vcomp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vcomp);
+void CDECL _vcomp_for_dynamic_init(int flags, int first, int last, int mystep, int chunksize)
+{
+ struct vcomp_team *pt = vcomp_get_team();
+
+ TRACE("(%d, %d, %d, %d, %d): stub\n", flags, first, last, mystep, chunksize);
+
+ pt->work.dyn_for.counter = first;
+ pt->work.dyn_for.chunksize = chunksize;
+ pt->work.dyn_for.flags = flags;
+ pt->work.dyn_for.step = mystep;
+ if (flags & VCOMP_DYNAMIC_FOR_FLAGS_UP)
+ pt->work.dyn_for.iterations_remaining = 1 + (last - first) / mystep;
+ else
+ pt->work.dyn_for.iterations_remaining = 1 + (first - last) / mystep;
+}
+
+int CDECL _vcomp_for_dynamic_next(int *pcounter, int *pchunklimit)
+{
+ struct vcomp_team *pt = vcomp_get_team();
+ int n;
+
+ TRACE("(%p, %p): stub.\n", pcounter, pchunklimit);
+
+ n = pt->work.dyn_for.chunksize;
+ if (n > pt->work.dyn_for.iterations_remaining)
+ n = pt->work.dyn_for.iterations_remaining;
+
+ *pcounter = pt->work.dyn_for.counter;
+
+ if (pt->work.dyn_for.flags & VCOMP_DYNAMIC_FOR_FLAGS_UP)
+ {
+ pt->work.dyn_for.counter += pt->work.dyn_for.step * n;
+ *pchunklimit = pt->work.dyn_for.counter - 1;
+ }
+ else
+ {
+ pt->work.dyn_for.counter -= pt->work.dyn_for.step * n;
+ *pchunklimit = pt->work.dyn_for.counter + 1;
+ }
+ pt->work.dyn_for.iterations_remaining -= n;
+
+ TRACE("counter %d, iterations_remaining %d, n %d, returning %d\n",
+ pt->work.dyn_for.counter, pt->work.dyn_for.iterations_remaining, n, (n > 0));
+ return (n > 0);
+}
+
void CDECL _vcomp_for_static_init(int first, int last, int mystep, int chunksize, int *pnloops, int *pfirst, int *plast, int *pchunksize, int *pfinalchunkstart)
{
TRACE("(%d, %d, %d, %d, %p, %p, %p, %p, %p): stub\n",
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index dd276d0..48d5e3f 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 dd276d0..48d5e3f 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.2.1

View File

@ -1,180 +0,0 @@
From 8069c24409570d48c59bb103539d1ea1fd835c36 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Mon, 15 Oct 2012 21:09:56 -0700
Subject: vcomp: better stubs for _vcomp_sections_init, _vcomp_sections_next
---
dlls/vcomp/tests/work.c | 34 ++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 4 ++--
dlls/vcomp/vcomp_private.h | 5 +++++
dlls/vcomp/work.c | 18 ++++++++++++++++++
dlls/vcomp100/vcomp100.spec | 4 ++--
dlls/vcomp90/vcomp90.spec | 4 ++--
6 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/tests/work.c b/dlls/vcomp/tests/work.c
index 5abe0e1..981f741 100644
--- a/dlls/vcomp/tests/work.c
+++ b/dlls/vcomp/tests/work.c
@@ -20,12 +20,15 @@
#include "wine/test.h"
+static void WINAPIV (*p_vcomp_barrier)(void);
static void WINAPIV (*p_vcomp_fork)(DWORD parallel, int nargs, void *helper, ...);
static void CDECL (*p_vcomp_for_dynamic_init)(int flags, int first, int last, int mystep, int chunksize);
static int CDECL (*p_vcomp_for_dynamic_next)(int *pcounter, int *pchunklimit);
static void CDECL (*p_vcomp_for_static_end)(void);
static void CDECL (*p_vcomp_for_static_init)(int first, int last, int mystep, int chunksize, int *pnloops, int *pfirst, int *plast, int *pchunksize, int *pfinalchunkstart);
static void CDECL (*p_vcomp_for_static_simple_init)(int first, int last, int mystep, int step, int *pfirst, int *plast);
+static void CDECL (*p_vcomp_sections_init)(int n);
+static int CDECL (*p_vcomp_sections_next)(void);
#define GETFUNC(x) do { p##x = (void*)GetProcAddress(vcomp, #x); ok(p##x != NULL, "Export '%s' not found\n", #x); } while(0)
@@ -42,12 +45,15 @@ static BOOL init(void)
return FALSE;
}
+ GETFUNC(_vcomp_barrier);
GETFUNC(_vcomp_fork);
GETFUNC(_vcomp_for_dynamic_init);
GETFUNC(_vcomp_for_dynamic_next);
GETFUNC(_vcomp_for_static_end);
GETFUNC(_vcomp_for_static_init);
GETFUNC(_vcomp_for_static_simple_init);
+ GETFUNC(_vcomp_sections_init);
+ GETFUNC(_vcomp_sections_next);
return TRUE;
}
@@ -183,6 +189,33 @@ static void test_vcomp_for_static_simple_init(void)
ok(nsum == 6*13, "expected sum 6*13, got %d\n", nsum);
}
+int section_calls[3];
+
+static void CDECL _test_vcomp_sections_worker(void)
+{
+ p_vcomp_sections_init(3);
+
+ for (;;)
+ {
+ int i = p_vcomp_sections_next();
+ if (i < 0 || i >= 3) break;
+ section_calls[i]++;
+ }
+
+ p_vcomp_barrier();
+}
+
+static void test_vcomp_sections(void)
+{
+ section_calls[0] = 0;
+ section_calls[1] = 0;
+ section_calls[2] = 0;
+ p_vcomp_fork(1, 0, _test_vcomp_sections_worker);
+ ok(section_calls[0] == 1, "section 0 not called once\n");
+ ok(section_calls[1] == 1, "section 1 not called once\n");
+ ok(section_calls[2] == 1, "section 2 not called once\n");
+}
+
START_TEST(work)
{
if (!init())
@@ -191,4 +224,5 @@ START_TEST(work)
test_vcomp_for_dynamic();
test_vcomp_for_static_init();
test_vcomp_for_static_simple_init();
+ test_vcomp_sections();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index f603660..1b02a65 100644
--- a/dlls/vcomp/vcomp.spec
+++ b/dlls/vcomp/vcomp.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long)
+@ cdecl _vcomp_sections_next()
@ cdecl _vcomp_set_num_threads(long)
@ cdecl _vcomp_single_begin(long)
@ cdecl _vcomp_single_end()
diff --git a/dlls/vcomp/vcomp_private.h b/dlls/vcomp/vcomp_private.h
index d3a7005..3d6c22b 100644
--- a/dlls/vcomp/vcomp_private.h
+++ b/dlls/vcomp/vcomp_private.h
@@ -35,6 +35,11 @@ struct vcomp_team
int chunksize;
int flags;
} dyn_for;
+ struct
+ {
+ int counter;
+ int nsect;
+ } sections;
} work;
};
diff --git a/dlls/vcomp/work.c b/dlls/vcomp/work.c
index 87bce93..4370ec5 100644
--- a/dlls/vcomp/work.c
+++ b/dlls/vcomp/work.c
@@ -97,3 +97,21 @@ void CDECL _vcomp_for_static_end(void)
{
TRACE("stub\n");
}
+
+void CDECL _vcomp_sections_init(int n)
+{
+ struct vcomp_team *pt = vcomp_get_team();
+ TRACE("(%d): stub\n", n);
+ pt->work.sections.counter = 0;
+ pt->work.sections.nsect = n;
+}
+
+int CDECL _vcomp_sections_next(void)
+{
+ struct vcomp_team *pt = vcomp_get_team();
+ int i = pt->work.sections.counter++;
+ if (i >= pt->work.sections.nsect)
+ i = -1;
+ TRACE("stub; returning %d\n", i);
+ return i;
+}
diff --git a/dlls/vcomp100/vcomp100.spec b/dlls/vcomp100/vcomp100.spec
index 48d5e3f..ab93ec2 100644
--- a/dlls/vcomp100/vcomp100.spec
+++ b/dlls/vcomp100/vcomp100.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long) vcomp._vcomp_sections_init
+@ cdecl _vcomp_sections_next() vcomp._vcomp_sections_next
@ cdecl _vcomp_set_num_threads(long) vcomp._vcomp_set_num_threads
@ cdecl _vcomp_single_begin(long) vcomp._vcomp_single_begin
@ cdecl _vcomp_single_end() vcomp._vcomp_single_end
diff --git a/dlls/vcomp90/vcomp90.spec b/dlls/vcomp90/vcomp90.spec
index 48d5e3f..ab93ec2 100644
--- a/dlls/vcomp90/vcomp90.spec
+++ b/dlls/vcomp90/vcomp90.spec
@@ -83,8 +83,8 @@
@ stub _vcomp_reduction_u2
@ stub _vcomp_reduction_u4
@ stub _vcomp_reduction_u8
-@ stub _vcomp_sections_init
-@ stub _vcomp_sections_next
+@ cdecl _vcomp_sections_init(long) vcomp._vcomp_sections_init
+@ cdecl _vcomp_sections_next() vcomp._vcomp_sections_next
@ cdecl _vcomp_set_num_threads(long) vcomp._vcomp_set_num_threads
@ cdecl _vcomp_single_begin(long) vcomp._vcomp_single_begin
@ cdecl _vcomp_single_end() vcomp._vcomp_single_end
--
2.2.1

View File

@ -1,25 +0,0 @@
From 5748aa15dd5e619714e9a04a033b30bd1fdae7d7 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 29 Jan 2015 00:18:47 +0100
Subject: vcomp: Add a warning that multithreading is not yet supported.
---
dlls/vcomp/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index e37cf16..1dd57dd 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -126,6 +126,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
ERR("Failed to allocate TLS index\n");
return FALSE;
}
+
+ FIXME("Builtin vcomp doesn't support multithreading, use native library for better performance.\n");
break;
case DLL_PROCESS_DETACH:
TlsFree(vcomp_context_tls);
--
2.2.1

View File

@ -1 +0,0 @@
Fixes: [31640] Implement additional stubs for vcomp dlls