mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added initial set of patches for multithreaded vcomp implementation.
This commit is contained in:
parent
d709879134
commit
65c559753a
@ -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
1
debian/changelog
vendored
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
patches/vcomp-Functions/definition
Normal file
1
patches/vcomp-Functions/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [31640] Implement various vcomp functions
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
Fixes: [31640] Implement additional stubs for vcomp dlls
|
Loading…
x
Reference in New Issue
Block a user