Rebase against 22f28d2923811b85024f63ce43e41966a864ecd0.

This commit is contained in:
Sebastian Lackner 2015-07-15 18:48:39 +02:00
parent d26abf2d93
commit d205f22f1e
20 changed files with 1020 additions and 992 deletions

View File

@ -1,4 +1,4 @@
From 16bb8ba07739f3c189920cdbf56f87aa520456c0 Mon Sep 17 00:00:00 2001
From f4024fac3fba56c007fa873a66271eef4f6c31ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Wed, 1 Apr 2015 04:34:20 +0200
Subject: ntdll: Load CLI/.NET images in the same way as Windows XP and above.
@ -9,7 +9,7 @@ Subject: ntdll: Load CLI/.NET images in the same way as Windows XP and above.
2 files changed, 133 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 2c8074b..5810080 100644
index 1cd6e47..4d985d4 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1079,16 +1079,11 @@ static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry )
@ -33,11 +33,11 @@ index 2c8074b..5810080 100644
ERR( "%s doesn't have an entry point, it cannot be executed\n",
debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) );
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 9810f07..18f20fe 100644
index bef0ab1..2dd8ad0 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -97,6 +97,10 @@ static UINT tls_module_count; /* number of modules with TLS directory */
static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */
static IMAGE_TLS_DIRECTORY *tls_dirs; /* array of TLS directories */
LIST_ENTRY tls_links = { &tls_links, &tls_links };
+static HRESULT (WINAPI *p_CorValidateImage)(PVOID* ImageBase, LPCWSTR FileName);
@ -126,7 +126,7 @@ index 9810f07..18f20fe 100644
* get_modref
*
* Looks for the referenced HMODULE in the current process
@@ -863,6 +939,10 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
@@ -868,6 +944,10 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */
wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
@ -137,7 +137,7 @@ index 9810f07..18f20fe 100644
wm->ldr.TlsIndex = alloc_tls_slot( &wm->ldr );
if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
@@ -1058,8 +1138,43 @@ static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved
@@ -1063,8 +1143,43 @@ static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved
BOOL retv = FALSE;
/* Skip calls for modules loaded with special load flags */
@ -182,7 +182,7 @@ index 9810f07..18f20fe 100644
if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return STATUS_SUCCESS;
@@ -2865,7 +2980,20 @@ static void load_global_options(void)
@@ -2870,7 +2985,20 @@ static void load_global_options(void)
*/
static void start_process( void *kernel_start )
{
@ -205,5 +205,5 @@ index 9810f07..18f20fe 100644
/******************************************************************
--
2.3.3
2.4.5

View File

@ -55,7 +55,7 @@ version()
echo "Copyright (C) 2014-2015 the Wine Staging project authors."
echo ""
echo "Patchset to be applied on upstream Wine:"
echo " commit a8f45dff604058d419bd6c2e070f65a13a6ddfdb"
echo " commit 22f28d2923811b85024f63ce43e41966a864ecd0"
echo ""
}
@ -203,7 +203,6 @@ patch_enable_all ()
enable_server_RootDirectory_File="$1"
enable_server_Shared_Memory="$1"
enable_server_Stored_ACLs="$1"
enable_server_Unexpected_Wakeup="$1"
enable_setupapi_SetupDiSelectBestCompatDrv="$1"
enable_setupapi_SetupDiSetDeviceInstallParamsW="$1"
enable_setupapi_SetupPromptForDisk="$1"
@ -678,9 +677,6 @@ patch_enable ()
server-Stored_ACLs)
enable_server_Stored_ACLs="$2"
;;
server-Unexpected_Wakeup)
enable_server_Unexpected_Wakeup="$2"
;;
setupapi-SetupDiSelectBestCompatDrv)
enable_setupapi_SetupDiSelectBestCompatDrv="$2"
;;
@ -1407,9 +1403,6 @@ if test "$enable_category_stable" -eq 1; then
if test "$enable_server_Delete_On_Close" -gt 1; then
abort "Patchset server-Delete_On_Close disabled, but category-stable depends on that."
fi
if test "$enable_server_Unexpected_Wakeup" -gt 1; then
abort "Patchset server-Unexpected_Wakeup disabled, but category-stable depends on that."
fi
if test "$enable_setupapi_SetupDiSetDeviceInstallParamsW" -gt 1; then
abort "Patchset setupapi-SetupDiSetDeviceInstallParamsW disabled, but category-stable depends on that."
fi
@ -1538,7 +1531,6 @@ if test "$enable_category_stable" -eq 1; then
enable_server_ClipCursor=1
enable_server_CreateProcess_ACLs=1
enable_server_Delete_On_Close=1
enable_server_Unexpected_Wakeup=1
enable_setupapi_SetupDiSetDeviceInstallParamsW=1
enable_shell32_RunDLL_CallEntry16=1
enable_shell32_SHFileOperation=1
@ -4115,20 +4107,6 @@ if test "$enable_server_Shared_Memory" -eq 1; then
) >> "$patchlist"
fi
# Patchset server-Unexpected_Wakeup
# |
# | Modified files:
# | * dlls/kernel32/tests/sync.c, server/thread.c
# |
if test "$enable_server_Unexpected_Wakeup" -eq 1; then
patch_apply server-Unexpected_Wakeup/0001-server-Avoid-sending-unexpected-wakeup-with-uninitia.patch
patch_apply server-Unexpected_Wakeup/0002-kernel32-tests-Repeat-test-for-SignalObjectAndWait-m.patch
(
echo '+ { "Sebastian Lackner", "server: Avoid sending unexpected wakeup with uninitialized cookie value.", 1 },';
echo '+ { "Sebastian Lackner", "kernel32/tests: Repeat test for SignalObjectAndWait multiple times to test wineserver wakeup cookie management.", 1 },';
) >> "$patchlist"
fi
# Patchset setupapi-SetupDiSelectBestCompatDrv
# |
# | This patchset fixes the following Wine bugs:
@ -4513,31 +4491,32 @@ fi
# | * [#31640] Implement various vcomp functions
# |
# | Modified files:
# | * 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
# | * configure.ac, dlls/vcomp/main.c, dlls/vcomp/tests/Makefile.in, dlls/vcomp/tests/vcomp.c, dlls/vcomp/vcomp.spec,
# | dlls/vcomp100/vcomp100.spec, dlls/vcomp90/vcomp90.spec
# |
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
patch_apply vcomp-Functions/0002-vcomp-Add-multithreaded-implementation-for-_vcomp_fo.patch
patch_apply vcomp-Functions/0003-vcomp-Implement-_vcomp_barrier.patch
patch_apply vcomp-Functions/0004-vcomp-tests-Add-initial-tests.patch
patch_apply vcomp-Functions/0005-vcomp-tests-Add-additional-tests-for-_vcomp_fork.patch
patch_apply vcomp-Functions/0006-vcomp-Implement-_vcomp_for_static_simple_init-and-_v.patch
patch_apply vcomp-Functions/0007-vcomp-tests-Add-tests-for-_vcomp_for_static_simple_i.patch
patch_apply vcomp-Functions/0008-vcomp-Implement-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0009-vcomp-tests-Add-tests-for-_vcomp_for_static_init.patch
patch_apply vcomp-Functions/0010-vcomp-Implement-omp_in_parallel.patch
patch_apply vcomp-Functions/0011-vcomp-Implement-_vcomp_sections_init-and-_vcomp_sect.patch
patch_apply vcomp-Functions/0012-vcomp-Implement-_vcomp_for_dynamic_init-and-_vcomp_f.patch
(
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: Add multithreaded implementation for _vcomp_fork.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp: Implement _vcomp_barrier.", 1 },';
echo '+ { "Sebastian Lackner", "vcomp/tests: Add initial tests.", 1 },';
echo '+ { "Dan Kegel", "vcomp/tests: Add additional 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 },';

View File

@ -1,67 +0,0 @@
From 9df06c6e4b4cf258b7f321dfd5e20467bef2b36f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 22 Nov 2014 17:42:22 +0100
Subject: server: Avoid sending unexpected wakeup with uninitialized cookie
value.
While executing the kernel32/sync tests I noticed a couple of unexpected wakeup cookies, which looked like uninitialized wineserver memory.
Here an excerpt from the log (added additional debug values):
---
server/thread.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/server/thread.c b/server/thread.c
index ba3f1d5..bdd9ef7 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -601,6 +601,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj
wait->count = count;
wait->flags = flags;
wait->select = select_op->op;
+ wait->cookie = 0;
wait->user = NULL;
wait->timeout = timeout;
wait->abandoned = 0;
@@ -719,7 +720,7 @@ int wake_thread( struct thread *thread )
cookie = thread->wait->cookie;
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
end_wait( thread );
- if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
+ if (cookie && send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
{
if (!count) count = -1;
break;
@@ -749,7 +750,7 @@ int wake_thread_queue_entry( struct wait_queue_entry *entry )
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
end_wait( thread );
- if (send_thread_wakeup( thread, cookie, signaled ) != -1)
+ if (!cookie || send_thread_wakeup( thread, cookie, signaled ) != -1)
wake_thread( thread ); /* check other waits too */
return 1;
@@ -768,6 +769,8 @@ static void thread_timeout( void *ptr )
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id );
end_wait( thread );
+
+ assert( cookie );
if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
/* check if other objects have become signaled in the meantime */
wake_thread( thread );
@@ -1429,6 +1432,12 @@ DECL_HANDLER(select)
set_error( STATUS_INVALID_PARAMETER );
return;
}
+ if (!req->cookie)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
op_size = min( get_req_data_size() - sizeof(*result), sizeof(select_op) );
memset( &select_op, 0, sizeof(select_op) );
memcpy( &select_op, result + 1, op_size );
--
2.1.3

View File

@ -1,42 +0,0 @@
From e8a0619c85e774abd866e3882038dee563007c77 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 16 Dec 2014 06:23:15 +0100
Subject: kernel32/tests: Repeat test for SignalObjectAndWait multiple times to
test wineserver wakeup cookie management.
---
dlls/kernel32/tests/sync.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index cbe0acb..668b92d 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -64,6 +64,7 @@ static void test_signalandwait(void)
HMODULE kernel32;
DWORD r;
HANDLE event[2], semaphore[2], file;
+ int i;
kernel32 = GetModuleHandleA("kernel32.dll");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
@@ -96,9 +97,13 @@ static void test_signalandwait(void)
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
- /* event[0] is now signalled */
- r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
- ok( r == WAIT_OBJECT_0, "should succeed\n");
+ /* event[0] is now signalled - we repeat this test multiple times
+ * to ensure that the wineserver handles this situation properly. */
+ for (i = 0; i < 10000; i++)
+ {
+ r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
+ ok( r == WAIT_OBJECT_0, "should succeed\n");
+ }
/* event[0] is not signalled */
r = WaitForSingleObject(event[0], 0);
--
2.1.3

View File

@ -1 +0,0 @@
Category: stable

View File

@ -1,17 +1,20 @@
From 6404654fd885acbf0e563d9b5070d321986b5b8d Mon Sep 17 00:00:00 2001
From d0d4b3991b691ee74e999f82dbf57a5a400fe7db Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Sat, 11 Jul 2015 06:50:26 +0200
Date: Tue, 14 Jul 2015 21:40:36 +0200
Subject: vcomp: Implement stub for _vcomp_fork.
Changes:
* The original patch added a new file, I moved the implementation to main.c.
* A huge comment block was removed, tests are more reliable than comments anyway. ;)
---
dlls/vcomp/main.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/main.c | 95 +++++++++++++++++++++++++++++++++++++++++++++
dlls/vcomp/vcomp.spec | 2 +-
dlls/vcomp100/vcomp100.spec | 2 +-
dlls/vcomp90/vcomp90.spec | 2 +-
4 files changed, 96 insertions(+), 3 deletions(-)
4 files changed, 98 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index ab2a372..26f6c67 100644
index 8ec3616..03c085b 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -3,6 +3,7 @@
@ -22,24 +25,14 @@ index ab2a372..26f6c67 100644
*
* 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");
}
@@ -40,6 +41,89 @@ struct vcomp_thread_data
int fork_threads;
};
+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")
@ -109,6 +102,7 @@ index ab2a372..26f6c67 100644
+ __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)
@ -118,9 +112,27 @@ index ab2a372..26f6c67 100644
+
+#endif
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
static inline struct vcomp_thread_data *vcomp_get_thread_data(void)
{
TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
return (struct vcomp_thread_data *)TlsGetValue(vcomp_context_tls);
@@ -160,6 +244,17 @@ void CDECL _vcomp_single_end(void)
TRACE("stub\n");
}
+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);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
TRACE("(%p, %d, %p)\n", instance, reason, reserved);
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 306dd15..d446574 100644
--- a/dlls/vcomp/vcomp.spec

View File

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

View File

@ -0,0 +1,259 @@
From 6f76d9a3a8a11bc4f6d3e6ddba1fcb9a856d0b2f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 14 Jul 2015 21:41:10 +0200
Subject: vcomp: Add multithreaded implementation for _vcomp_fork.
---
dlls/vcomp/main.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 172 insertions(+), 8 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 03c085b..20aeb4f 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,22 +24,52 @@
#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 struct list vcomp_idle_threads = LIST_INIT(vcomp_idle_threads);
static DWORD vcomp_context_tls = TLS_OUT_OF_INDEXES;
+static HMODULE vcomp_module;
static int vcomp_max_threads;
static int vcomp_num_threads;
static BOOL vcomp_nested_fork = FALSE;
+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_data
{
+ struct vcomp_team_data *team;
int thread_num;
int fork_threads;
+
+ /* only used for concurrent tasks */
+ struct list entry;
+ CONDITION_VARIABLE cond;
+};
+
+struct vcomp_team_data
+{
+ CONDITION_VARIABLE cond;
+ int num_threads;
+ int finished_threads;
+
+ /* callback arguments */
+ int nargs;
+ void *wrapper;
+ __ms_va_list valist;
};
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
@@ -145,8 +176,9 @@ static struct vcomp_thread_data *vcomp_init_thread_data(void)
ExitProcess(1);
}
- thread_data->thread_num = 0;
- thread_data->fork_threads = 0;
+ thread_data->team = NULL;
+ thread_data->thread_num = 0;
+ thread_data->fork_threads = 0;
vcomp_set_thread_data(thread_data);
return thread_data;
@@ -187,8 +219,9 @@ int CDECL omp_get_num_procs(void)
int CDECL omp_get_num_threads(void)
{
- TRACE("stub\n");
- return 1;
+ struct vcomp_team_data *team_data = vcomp_init_thread_data()->team;
+ TRACE("()\n");
+ return team_data ? team_data->num_threads : 1;
}
int CDECL omp_get_thread_num(void)
@@ -244,15 +277,145 @@ void CDECL _vcomp_single_end(void)
TRACE("stub\n");
}
+static DWORD WINAPI _vcomp_fork_worker(void *param)
+{
+ struct vcomp_thread_data *thread_data = param;
+ vcomp_set_thread_data(thread_data);
+
+ TRACE("starting worker thread for %p\n", thread_data);
+
+ EnterCriticalSection(&vcomp_section);
+ for (;;)
+ {
+ struct vcomp_team_data *team = thread_data->team;
+ if (team != NULL)
+ {
+ LeaveCriticalSection(&vcomp_section);
+ _vcomp_fork_call_wrapper(team->wrapper, team->nargs, team->valist);
+ EnterCriticalSection(&vcomp_section);
+
+ thread_data->team = NULL;
+ list_remove(&thread_data->entry);
+ list_add_tail(&vcomp_idle_threads, &thread_data->entry);
+ if (++team->finished_threads >= team->num_threads)
+ WakeAllConditionVariable(&team->cond);
+ }
+
+ if (!SleepConditionVariableCS(&thread_data->cond, &vcomp_section, 5000) &&
+ GetLastError() == ERROR_TIMEOUT && !thread_data->team)
+ {
+ break;
+ }
+ }
+ list_remove(&thread_data->entry);
+ LeaveCriticalSection(&vcomp_section);
+
+ TRACE("terminating worker thread for %p\n", thread_data);
+
+ HeapFree(GetProcessHeap(), 0, thread_data);
+ vcomp_set_thread_data(NULL);
+ FreeLibraryAndExitThread(vcomp_module, 0);
+ return 0;
+}
+
void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
{
- __ms_va_list valist;
+ struct vcomp_thread_data *prev_thread_data = vcomp_init_thread_data();
+ struct vcomp_thread_data thread_data;
+ struct vcomp_team_data team_data;
+ int num_threads;
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 (!ifval)
+ num_threads = 1;
+ else if (prev_thread_data->team && !vcomp_nested_fork)
+ num_threads = 1;
+ else if (prev_thread_data->fork_threads)
+ num_threads = prev_thread_data->fork_threads;
+ else
+ num_threads = vcomp_num_threads;
+
+ InitializeConditionVariable(&team_data.cond);
+ team_data.num_threads = 1;
+ team_data.finished_threads = 0;
+ team_data.nargs = nargs;
+ team_data.wrapper = wrapper;
+ __ms_va_start(team_data.valist, wrapper);
+
+ thread_data.team = &team_data;
+ thread_data.thread_num = 0;
+ thread_data.fork_threads = 0;
+ list_init(&thread_data.entry);
+ InitializeConditionVariable(&thread_data.cond);
+
+ if (num_threads > 1)
+ {
+ struct list *ptr;
+ EnterCriticalSection(&vcomp_section);
+
+ /* reuse existing threads (if any) */
+ while (team_data.num_threads < num_threads && (ptr = list_head(&vcomp_idle_threads)))
+ {
+ struct vcomp_thread_data *data = LIST_ENTRY(ptr, struct vcomp_thread_data, entry);
+ data->team = &team_data;
+ data->thread_num = team_data.num_threads++;
+ data->fork_threads = 0;
+ list_remove(&data->entry);
+ list_add_tail(&thread_data.entry, &data->entry);
+ WakeAllConditionVariable(&data->cond);
+ }
+
+ /* spawn additional threads */
+ while (team_data.num_threads < num_threads)
+ {
+ struct vcomp_thread_data *data;
+ HMODULE module;
+ HANDLE thread;
+
+ data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
+ if (!data) break;
+
+ data->team = &team_data;
+ data->thread_num = team_data.num_threads;
+ data->fork_threads = 0;
+ InitializeConditionVariable(&data->cond);
+
+ thread = CreateThread(NULL, 0, _vcomp_fork_worker, data, 0, NULL);
+ if (!thread)
+ {
+ HeapFree(GetProcessHeap(), 0, data);
+ break;
+ }
+
+ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (const WCHAR *)vcomp_module, &module);
+ team_data.num_threads++;
+ list_add_tail(&thread_data.entry, &data->entry);
+ CloseHandle(thread);
+ }
+
+ LeaveCriticalSection(&vcomp_section);
+ }
+
+ vcomp_set_thread_data(&thread_data);
+ _vcomp_fork_call_wrapper(team_data.wrapper, team_data.nargs, team_data.valist);
+ vcomp_set_thread_data(prev_thread_data);
+ prev_thread_data->fork_threads = 0;
+
+ if (team_data.num_threads > 1)
+ {
+ EnterCriticalSection(&vcomp_section);
+
+ team_data.finished_threads++;
+ while (team_data.finished_threads < team_data.num_threads)
+ SleepConditionVariableCS(&team_data.cond, &vcomp_section, INFINITE);
+
+ LeaveCriticalSection(&vcomp_section);
+ assert(list_empty(&thread_data.entry));
+ }
+
+ __ms_va_end(team_data.valist);
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
@@ -275,6 +438,7 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
}
GetSystemInfo(&sysinfo);
+ vcomp_module = instance;
vcomp_max_threads = sysinfo.dwNumberOfProcessors;
vcomp_num_threads = sysinfo.dwNumberOfProcessors;
break;
--
2.4.5

View File

@ -0,0 +1,65 @@
From 5990968a0ae43fd6f4a4001107ef5d4fcc273458 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 14 Jul 2015 21:41:27 +0200
Subject: vcomp: Implement _vcomp_barrier.
---
dlls/vcomp/main.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 20aeb4f..bcaa4ea 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -70,6 +70,10 @@ struct vcomp_team_data
int nargs;
void *wrapper;
__ms_va_list valist;
+
+ /* barrier */
+ unsigned int barrier;
+ int barrier_count;
};
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
@@ -256,7 +260,27 @@ void CDECL omp_set_num_threads(int num_threads)
void CDECL _vcomp_barrier(void)
{
- TRACE("stub\n");
+ struct vcomp_team_data *team_data = vcomp_init_thread_data()->team;
+
+ TRACE("()\n");
+
+ if (!team_data)
+ return;
+
+ EnterCriticalSection(&vcomp_section);
+ if (++team_data->barrier_count >= team_data->num_threads)
+ {
+ team_data->barrier++;
+ team_data->barrier_count = 0;
+ WakeAllConditionVariable(&team_data->cond);
+ }
+ else
+ {
+ unsigned int barrier = team_data->barrier;
+ while (team_data->barrier == barrier)
+ SleepConditionVariableCS(&team_data->cond, &vcomp_section, INFINITE);
+ }
+ LeaveCriticalSection(&vcomp_section);
}
void CDECL _vcomp_set_num_threads(int num_threads)
@@ -342,6 +366,8 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_data.nargs = nargs;
team_data.wrapper = wrapper;
__ms_va_start(team_data.valist, wrapper);
+ team_data.barrier = 0;
+ team_data.barrier_count = 0;
thread_data.team = &team_data;
thread_data.thread_num = 0;
--
2.4.5

View File

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

View File

@ -0,0 +1,338 @@
From 01b14a9059e5a0ade1818046b03546adc0002bde Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 14 Jul 2015 21:42:11 +0200
Subject: vcomp/tests: Add initial tests.
The only way to get the tests pass on all testbot machines was to dynamically
create a manifest file. Without manifest file, the vcomp library cannot be found
on all machines > Win2000, with manifest file as resource the Windows loader is
not able to load the executable for testbots without vcrun2005.
---
configure.ac | 1 +
dlls/vcomp/tests/Makefile.in | 4 +
dlls/vcomp/tests/vcomp.c | 290 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 295 insertions(+)
create mode 100644 dlls/vcomp/tests/Makefile.in
create mode 100644 dlls/vcomp/tests/vcomp.c
diff --git a/configure.ac b/configure.ac
index 3eaec29..f15a17a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3322,6 +3322,7 @@ WINE_CONFIG_TEST(dlls/uxtheme/tests)
WINE_CONFIG_DLL(vbscript,,[clean])
WINE_CONFIG_TEST(dlls/vbscript/tests,[clean])
WINE_CONFIG_DLL(vcomp)
+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..d1b7b12
--- /dev/null
+++ b/dlls/vcomp/tests/Makefile.in
@@ -0,0 +1,4 @@
+TESTDLL = vcomp.dll
+
+C_SRCS = \
+ vcomp.c
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
new file mode 100644
index 0000000..b084791
--- /dev/null
+++ b/dlls/vcomp/tests/vcomp.c
@@ -0,0 +1,290 @@
+/*
+ * Unit test suite for vcomp
+ *
+ * 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
+ */
+
+#include "wine/test.h"
+
+static char vcomp_manifest_file[MAX_PATH];
+static HANDLE vcomp_actctx_hctx;
+static ULONG_PTR vcomp_actctx_cookie;
+static HMODULE vcomp_handle;
+
+static HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*);
+static BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*);
+static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
+static VOID (WINAPI *pReleaseActCtx)(HANDLE);
+
+static void (CDECL *p_vcomp_barrier)(void);
+static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
+static void (CDECL *p_vcomp_set_num_threads)(int num_threads);
+static int (CDECL *pomp_get_max_threads)(void);
+static int (CDECL *pomp_get_nested)(void);
+static int (CDECL *pomp_get_num_threads)(void);
+static int (CDECL *pomp_get_thread_num)(void);
+static void (CDECL *pomp_set_nested)(int nested);
+static void (CDECL *pomp_set_num_threads)(int num_threads);
+
+#ifdef __i386__
+#define ARCH "x86"
+#elif defined(__x86_64__)
+#define ARCH "amd64"
+#else
+#define ARCH "none"
+#endif
+
+static const char vcomp_manifest[] =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
+ " <assemblyIdentity\n"
+ " type=\"win32\"\n"
+ " name=\"Wine.vcomp.Test\"\n"
+ " version=\"1.0.0.0\"\n"
+ " processorArchitecture=\"" ARCH "\"\n"
+ " />\n"
+ "<description>Wine vcomp test suite</description>\n"
+ "<dependency>\n"
+ " <dependentAssembly>\n"
+ " <assemblyIdentity\n"
+ " type=\"win32\"\n"
+ " name=\"Microsoft.VC80.OpenMP\"\n"
+ " version=\"8.0.50608.0\"\n"
+ " processorArchitecture=\"" ARCH "\"\n"
+ " publicKeyToken=\"1fc8b3b9a1e18e3b\"\n"
+ " />\n"
+ " </dependentAssembly>\n"
+ "</dependency>\n"
+ "</assembly>\n";
+
+#undef ARCH
+
+static void create_vcomp_manifest(void)
+{
+ char temp_path[MAX_PATH];
+ HMODULE kernel32;
+ DWORD written;
+ ACTCTXA ctx;
+ HANDLE file;
+
+ kernel32 = GetModuleHandleA("kernel32.dll");
+ pCreateActCtxA = (void *)GetProcAddress(kernel32, "CreateActCtxA");
+ pActivateActCtx = (void *)GetProcAddress(kernel32, "ActivateActCtx");
+ pDeactivateActCtx = (void *)GetProcAddress(kernel32, "DeactivateActCtx");
+ pReleaseActCtx = (void *)GetProcAddress(kernel32, "ReleaseActCtx");
+ if (!pCreateActCtxA) return;
+
+ if (!GetTempPathA(sizeof(temp_path), temp_path) ||
+ !GetTempFileNameA(temp_path, "vcomp", 0, vcomp_manifest_file))
+ {
+ ok(0, "failed to create manifest file\n");
+ return;
+ }
+
+ file = CreateFileA(vcomp_manifest_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ ok(0, "failed to open manifest file\n");
+ return;
+ }
+
+ if (!WriteFile(file, vcomp_manifest, sizeof(vcomp_manifest) - 1, &written, NULL))
+ written = 0;
+ CloseHandle(file);
+
+ if (written != sizeof(vcomp_manifest) - 1)
+ {
+ ok(0, "failed to write manifest file\n");
+ DeleteFileA(vcomp_manifest_file);
+ return;
+ }
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.cbSize = sizeof(ctx);
+ ctx.lpSource = vcomp_manifest_file;
+ vcomp_actctx_hctx = pCreateActCtxA(&ctx);
+ if (!vcomp_actctx_hctx)
+ {
+ ok(0, "failed to create activation context\n");
+ DeleteFileA(vcomp_manifest_file);
+ return;
+ }
+
+ if (!pActivateActCtx(vcomp_actctx_hctx, &vcomp_actctx_cookie))
+ {
+ win_skip("failed to activate context\n");
+ pReleaseActCtx(vcomp_actctx_hctx);
+ DeleteFileA(vcomp_manifest_file);
+ vcomp_actctx_hctx = NULL;
+ }
+}
+
+static void release_vcomp(void)
+{
+ if (vcomp_handle)
+ FreeLibrary(vcomp_handle);
+
+ if (vcomp_actctx_hctx)
+ {
+ pDeactivateActCtx(0, vcomp_actctx_cookie);
+ pReleaseActCtx(vcomp_actctx_hctx);
+ DeleteFileA(vcomp_manifest_file);
+ }
+}
+
+#define VCOMP_GET_PROC(func) \
+ do \
+ { \
+ p ## func = (void *)GetProcAddress(vcomp_handle, #func); \
+ if (!p ## func) trace("Failed to get address for %s\n", #func); \
+ } \
+ while (0)
+
+static BOOL init_vcomp(void)
+{
+ create_vcomp_manifest();
+
+ vcomp_handle = LoadLibraryA("vcomp.dll");
+ if (!vcomp_handle)
+ {
+ win_skip("vcomp.dll not installed\n");
+ release_vcomp();
+ return FALSE;
+ }
+
+ VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_fork);
+ VCOMP_GET_PROC(_vcomp_set_num_threads);
+ VCOMP_GET_PROC(omp_get_max_threads);
+ VCOMP_GET_PROC(omp_get_nested);
+ VCOMP_GET_PROC(omp_get_num_threads);
+ VCOMP_GET_PROC(omp_get_thread_num);
+ VCOMP_GET_PROC(omp_set_nested);
+ VCOMP_GET_PROC(omp_set_num_threads);
+
+ return TRUE;
+}
+
+#undef VCOMP_GET_PROC
+
+static void CDECL num_threads_cb2(LONG *count)
+{
+ InterlockedIncrement(count);
+}
+
+static void CDECL num_threads_cb(BOOL nested, int nested_threads, LONG *count)
+{
+ int num_threads, thread_num;
+ LONG thread_count;
+
+ InterlockedIncrement(count);
+ p_vcomp_barrier();
+
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == *count, "expected num_threads == %d, got %d\n", *count, num_threads);
+ thread_num = pomp_get_thread_num();
+ ok(thread_num >= 0 && thread_num < num_threads,
+ "expected thread_num in range [0, %d], got %d\n", num_threads - 1, thread_num);
+
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
+ if (nested)
+ ok(thread_count == nested_threads, "expected %d thread, got %d\n", nested_threads, thread_count);
+ else
+ ok(thread_count == 1, "expected 1 thread, got %d\n", thread_count);
+
+ p_vcomp_set_num_threads(4);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 1, num_threads_cb2, &thread_count);
+ if (nested)
+ ok(thread_count == 4 , "expected 4 thread, got %d\n", thread_count);
+ else
+ ok(thread_count == 1 , "expected 1 thread, got %d\n", thread_count);
+}
+
+static void test_omp_get_num_threads(BOOL nested)
+{
+ int is_nested, max_threads, num_threads, thread_num;
+ LONG thread_count;
+
+ pomp_set_nested(nested);
+ is_nested = pomp_get_nested();
+ ok(is_nested == nested, "expected %d, got %d\n", nested, is_nested);
+
+ max_threads = pomp_get_max_threads();
+ ok(max_threads >= 1, "expected max_threads >= 1, got %d\n", max_threads);
+ thread_num = pomp_get_thread_num();
+ ok(thread_num == 0, "expected thread_num == 0, got %d\n", thread_num);
+
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, max_threads, &thread_count);
+ ok(thread_count == max_threads, "expected %d threads, got %d\n", max_threads, thread_count);
+
+ pomp_set_num_threads(2);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 2, &thread_count);
+ ok(thread_count == 2, "expected 2 threads, got %d\n", thread_count);
+
+ pomp_set_num_threads(4);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
+
+ p_vcomp_set_num_threads(8);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ ok(thread_count == 8, "expected 8 threads, got %d\n", thread_count);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
+
+ p_vcomp_set_num_threads(0);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
+
+ pomp_set_num_threads(0);
+ num_threads = pomp_get_num_threads();
+ ok(num_threads == 1, "expected num_threads == 1, got %d\n", num_threads);
+ thread_count = 0;
+ p_vcomp_fork(TRUE, 3, num_threads_cb, nested, 4, &thread_count);
+ ok(thread_count == 4, "expected 4 threads, got %d\n", thread_count);
+
+ pomp_set_num_threads(max_threads);
+ pomp_set_nested(FALSE);
+}
+
+START_TEST(vcomp)
+{
+ if (!init_vcomp())
+ return;
+
+ test_omp_get_num_threads(FALSE);
+ test_omp_get_num_threads(TRUE);
+
+ release_vcomp();
+}
--
2.4.5

View File

@ -0,0 +1,107 @@
From e9d9801b549a73db5666c51c14200aeca63725b4 Mon Sep 17 00:00:00 2001
From: Dan Kegel <dank@kegel.com>
Date: Tue, 14 Jul 2015 21:42:31 +0200
Subject: vcomp/tests: Add additional tests for _vcomp_fork.
Changes:
* The number of threads is now set to 4 before running the tests.
* Some functions were renamed.
* All fork tests are now in a single test_*() function.
* Various ok(...) messages were improved.
---
dlls/vcomp/tests/vcomp.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index b084791..a9b975d 100644
--- a/dlls/vcomp/tests/vcomp.c
+++ b/dlls/vcomp/tests/vcomp.c
@@ -1,6 +1,7 @@
/*
* Unit test suite for vcomp
*
+ * Copyright 2012 Dan Kegel
* Copyright 2015 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
@@ -278,6 +279,69 @@ static void test_omp_get_num_threads(BOOL nested)
pomp_set_nested(FALSE);
}
+static void CDECL fork_ptr_cb(LONG *a, LONG *b, LONG *c, LONG *d, LONG *e)
+{
+ InterlockedIncrement(a);
+ InterlockedIncrement(b);
+ InterlockedIncrement(c);
+ InterlockedIncrement(d);
+ InterlockedIncrement(e);
+}
+
+static void CDECL fork_uintptr_cb(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 fork_float_cb(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 max_threads = pomp_get_max_threads();
+ pomp_set_num_threads(4);
+
+ a = 0; b = 1; c = 2; d = 3; e = 4;
+ p_vcomp_fork(FALSE, 5, fork_ptr_cb, &a, &b, &c, &d, &e);
+ ok(a == 1, "expected a == 1, got %d\n", a);
+ ok(b == 2, "expected b == 2, got %d\n", b);
+ ok(c == 3, "expected c == 3, got %d\n", c);
+ ok(d == 4, "expected d == 4, got %d\n", d);
+ ok(e == 5, "expected e == 5, got %d\n", e);
+
+ a = 0; b = 1; c = 2; d = 3; e = 4;
+ p_vcomp_fork(TRUE, 5, fork_ptr_cb, &a, &b, &c, &d, &e);
+ ok(a == 4, "expected a == 4, got %d\n", a);
+ ok(b == 5, "expected b == 5, got %d\n", b);
+ ok(c == 6, "expected c == 6, got %d\n", c);
+ ok(d == 7, "expected d == 7, got %d\n", d);
+ ok(e == 8, "expected e == 8, got %d\n", e);
+
+ p_vcomp_fork(TRUE, 5, fork_uintptr_cb, (UINT_PTR)1, (UINT_PTR)(MAXUINT_PTR - 2),
+ (UINT_PTR)3, (UINT_PTR)(MAXUINT_PTR - 4), (UINT_PTR)5);
+
+ if (sizeof(int) < sizeof(void *))
+ 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, fork_float_cb, 1.5f, 2.5f, 3.5f, 4.5f, 5.5f);
+ }
+
+ pomp_set_num_threads(max_threads);
+}
+
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -285,6 +349,7 @@ START_TEST(vcomp)
test_omp_get_num_threads(FALSE);
test_omp_get_num_threads(TRUE);
+ test_vcomp_fork();
release_vcomp();
}
--
2.4.5

View File

@ -1,4 +1,4 @@
From f455eb53b0d527874fb95bdc652d1a31cd8fa93a Mon Sep 17 00:00:00 2001
From 7b64b41a512320a89e7758db43343ebe99c0f563 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
@ -12,25 +12,25 @@ Subject: vcomp: Implement _vcomp_for_static_simple_init and
4 files changed, 96 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 9de9721..400f93a 100644
index bcaa4ea..fcbd747 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -174,6 +174,96 @@ void CDECL _vcomp_single_end(void)
@@ -301,6 +301,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;
+ struct vcomp_thread_data *thread_data = vcomp_init_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations, per_thread, remaining;
+ DWORD num_threads, thread_num;
+
+ 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;
+ num_threads = team_data->num_threads;
+ thread_num = thread_data->thread_num;
+
+ if (num_threads == 1)
+ {
@ -109,9 +109,9 @@ index 9de9721..400f93a 100644
+ TRACE("()\n");
+}
+
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_data *thread_data = param;
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index d446574..b14edca 100644
--- a/dlls/vcomp/vcomp.spec

View File

@ -1,49 +1,37 @@
From af8411c2c51708c2edbc620b3d775bf5a08144f9 Mon Sep 17 00:00:00 2001
From 656f0051550426759e8f6ab287391bbe6a168418 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(+)
dlls/vcomp/tests/vcomp.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 220 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 5c6a861..1971b6d 100644
index a9b975d..34c1ebc 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));
@@ -32,6 +32,9 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static HMODULE hvcomp = 0;
+static void (CDECL *p_vcomp_barrier)(void);
static void (CDECL *p_vcomp_barrier)(void);
+static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_simple_init)(unsigned int first, unsigned int last, int step,
+ BOOL forward, unsigned int *begin, unsigned int *end);
static void (WINAPIV *p_vcomp_fork)(BOOL ifval, int nargs, void *wrapper, ...);
static void (CDECL *p_vcomp_set_num_threads)(int num_threads);
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;
@@ -168,6 +171,8 @@ static BOOL init_vcomp(void)
}
+ VCOMP_GET_PROC(_vcomp_barrier);
VCOMP_GET_PROC(_vcomp_barrier);
+ VCOMP_GET_PROC(_vcomp_for_static_end);
+ VCOMP_GET_PROC(_vcomp_for_static_simple_init);
VCOMP_GET_PROC(_vcomp_fork);
VCOMP_GET_PROC(_vcomp_set_num_threads);
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)
}
@@ -342,6 +347,220 @@ static void test_vcomp_fork(void)
pomp_set_num_threads(max_threads);
}
+static void CDECL _test_vcomp_for_static_simple_init(void)
@ -263,12 +251,13 @@ index 5c6a861..1971b6d 100644
START_TEST(vcomp)
{
if (!init_vcomp())
return;
@@ -350,6 +569,7 @@ START_TEST(vcomp)
test_omp_get_num_threads(FALSE);
test_omp_get_num_threads(TRUE);
test_vcomp_fork();
+ test_vcomp_for_static_simple_init();
FreeLibrary(hvcomp);
release_vcomp();
}
--
2.4.5

View File

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

View File

@ -1,4 +1,4 @@
From 721c89ed7aec4a9ae8f0a5f7b0efeee838c08985 Mon Sep 17 00:00:00 2001
From ed0734ad10de657efb30ec7c851d20d20ba79a0a 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.
@ -11,26 +11,26 @@ Subject: vcomp: Implement _vcomp_for_static_init.
4 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 400f93a..2eeea3b 100644
index fcbd747..b22dd37 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,
@@ -386,6 +386,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;
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations, num_chunks, per_thread, remaining;
+ DWORD num_threads, thread_num;
+
+ 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;
+ num_threads = team_data->num_threads;
+ thread_num = thread_data->thread_num;
+
+ if (chunksize < 1)
+ chunksize = 1;

View File

@ -1,4 +1,4 @@
From 9cea1ba140eb5d8ecd70eab4a68e309cd80fd454 Mon Sep 17 00:00:00 2001
From 39cd9028667159d38193fca46691b7cdbc0fe82b 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.
@ -8,11 +8,11 @@ Subject: vcomp/tests: Add tests for _vcomp_for_static_init.
1 file changed, 199 insertions(+)
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 1971b6d..96806fd 100644
index 34c1ebc..0103af1 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;
@@ -33,6 +33,8 @@ static VOID (WINAPI *pReleaseActCtx)(HANDLE);
static void (CDECL *p_vcomp_barrier)(void);
static void (CDECL *p_vcomp_for_static_end)(void);
+static void (CDECL *p_vcomp_for_static_init)(int first, int last, int step, int chunksize, unsigned int *loops,
@ -20,15 +20,15 @@ index 1971b6d..96806fd 100644
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)
@@ -172,6 +174,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)
VCOMP_GET_PROC(_vcomp_set_num_threads);
@@ -561,6 +564,201 @@ static void test_vcomp_for_static_simple_init(void)
}
}
@ -230,13 +230,13 @@ index 1971b6d..96806fd 100644
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -345,6 +543,7 @@ START_TEST(vcomp)
@@ -570,6 +768,7 @@ START_TEST(vcomp)
test_omp_get_num_threads(TRUE);
test_vcomp_fork();
test_vcomp_for_static_simple_init();
+ test_vcomp_for_static_init();
FreeLibrary(hvcomp);
release_vcomp();
}
--
2.4.5

View File

@ -1,4 +1,4 @@
From aad24232add010020898eaa1a0934cb353c123f2 Mon Sep 17 00:00:00 2001
From d9ec7f94c0ecefeccf49f1d09bf458eb90472faf 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.
@ -11,22 +11,22 @@ Subject: vcomp: Implement omp_in_parallel.
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index 4f3471a..fccad93 100644
index b22dd37..a9a49ce 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -351,6 +351,12 @@ void CDECL _vcomp_for_static_end(void)
@@ -453,6 +453,12 @@ void CDECL _vcomp_for_static_end(void)
TRACE("()\n");
}
+int CDECL omp_in_parallel(void)
+{
+ TRACE("()\n");
+ return vcomp_get_team_info() != NULL;
+ return vcomp_init_thread_data()->team != NULL;
+}
+
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_data *thread_data = param;
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 8bc66e8..156233f 100644
--- a/dlls/vcomp/vcomp.spec

View File

@ -1,4 +1,4 @@
From 77d6daebca21cfb4209a8281abac2b9db0d7a1b4 Mon Sep 17 00:00:00 2001
From 92b615e0038571e52fb6cc22164ba80c07dcf2f5 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
@ -13,129 +13,127 @@ Subject: vcomp: Implement _vcomp_sections_init and _vcomp_sections_next and
5 files changed, 104 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index fccad93..db47ff6 100644
index a9a49ce..31814d6 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;
@@ -58,6 +58,9 @@ struct vcomp_thread_data
/* only used for concurrent tasks */
struct list entry;
CONDITION_VARIABLE cond;
+
+ /* section */
+ DWORD section;
+ unsigned int section;
};
struct vcomp_team_info
@@ -72,6 +75,11 @@ struct vcomp_team_info
struct vcomp_team_data
@@ -74,6 +77,11 @@ struct vcomp_team_data
/* barrier */
DWORD barrier;
DWORD barrier_count;
unsigned int barrier;
int barrier_count;
+
+ /* section */
+ DWORD section;
+ DWORD num_sections;
+ DWORD section_index;
+ unsigned int section;
+ unsigned int num_sections;
+ unsigned int 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_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
@@ -453,6 +461,43 @@ void CDECL _vcomp_for_static_end(void)
TRACE("()\n");
}
+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;
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+
+ TRACE("(%d)\n", n);
+
+ EnterCriticalSection(&vcomp_section);
+ thread_info->section++;
+ if ((int)(thread_info->section - team_info->section) > 0)
+ thread_data->section++;
+ if ((int)(thread_data->section - team_data->section) > 0)
+ {
+ /* first thread in a new section */
+ team_info->section = thread_info->section;
+ team_info->num_sections = n;
+ team_info->section_index = 0;
+ team_data->section = thread_data->section;
+ team_data->num_sections = n;
+ team_data->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;
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ int i = -1;
+
+ TRACE("()\n");
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_info->section == team_info->section &&
+ team_info->section_index < team_info->num_sections)
+ if (thread_data->section == team_data->section &&
+ team_data->section_index < team_data->num_sections)
+ {
+ i = team_info->section_index++;
+ i = team_data->section_index++;
+ }
+ LeaveCriticalSection(&vcomp_section);
+ return i;
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
int CDECL omp_in_parallel(void)
{
TRACE("()\n");
@@ -526,10 +571,12 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
__ms_va_start(team_data.valist, wrapper);
team_data.barrier = 0;
team_data.barrier_count = 0;
+ team_data.section = 0;
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;
thread_data.team = &team_data;
thread_data.thread_num = 0;
thread_data.fork_threads = 0;
+ thread_data.section = 1;
list_init(&thread_data.entry);
InitializeConditionVariable(&thread_data.cond);
/* 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;
@@ -545,6 +592,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->team = &team_data;
data->thread_num = team_data.num_threads++;
data->fork_threads = 0;
+ data->section = 1;
list_remove(&data->entry);
list_add_tail(&thread_data.entry, &data->entry);
WakeAllConditionVariable(&data->cond);
@@ -563,6 +611,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->team = &team_data;
data->thread_num = team_data.num_threads;
data->fork_threads = 0;
+ data->section = 1;
InitializeConditionVariable(&data->cond);
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)
thread = CreateThread(NULL, 0, _vcomp_fork_worker, data, 0, NULL);
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 96806fd..902a836 100644
index 0103af1..c962fe8 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
@@ -38,6 +38,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 void (CDECL *p_vcomp_set_num_threads)(int num_threads);
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)
static int (CDECL *pomp_get_nested)(void);
@@ -177,6 +179,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(_vcomp_set_num_threads);
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)
VCOMP_GET_PROC(omp_get_nested);
@@ -759,6 +763,50 @@ static void test_vcomp_for_static_init(void)
}
}
@ -186,13 +184,13 @@ index 96806fd..902a836 100644
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -544,6 +592,7 @@ START_TEST(vcomp)
@@ -769,6 +817,7 @@ START_TEST(vcomp)
test_vcomp_fork();
test_vcomp_for_static_simple_init();
test_vcomp_for_static_init();
+ test_vcomp_sections_init();
FreeLibrary(hvcomp);
release_vcomp();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 156233f..7083ce4 100644

View File

@ -1,4 +1,4 @@
From f29610acbf9ce393b772520f6041acce9d1aefd8 Mon Sep 17 00:00:00 2001
From 145ddf41060e93e9f320d5d2e4347dd2c7b8a83f 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
@ -13,23 +13,23 @@ Subject: vcomp: Implement _vcomp_for_dynamic_init and _vcomp_for_dynamic_next
5 files changed, 152 insertions(+), 6 deletions(-)
diff --git a/dlls/vcomp/main.c b/dlls/vcomp/main.c
index db47ff6..3a1e9ee 100644
index 31814d6..174ce06 100644
--- a/dlls/vcomp/main.c
+++ b/dlls/vcomp/main.c
@@ -59,6 +59,9 @@ struct vcomp_thread_info
@@ -61,6 +61,9 @@ struct vcomp_thread_data
/* section */
DWORD section;
unsigned int section;
+
+ /* dynamic */
+ DWORD dynamic;
+ unsigned int dynamic;
};
struct vcomp_team_info
@@ -80,6 +83,15 @@ struct vcomp_team_info
DWORD section;
DWORD num_sections;
DWORD section_index;
struct vcomp_team_data
@@ -82,6 +85,15 @@ struct vcomp_team_data
unsigned int section;
unsigned int num_sections;
unsigned int section_index;
+
+ /* dynamic */
+ DWORD dynamic;
@ -41,23 +41,23 @@ index db47ff6..3a1e9ee 100644
+ 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)
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
@@ -498,6 +510,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;
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations;
+ BOOL forward = (flags & 0x40) != 0;
+
+ TRACE("(%d, %d, %d, %d, %d)\n", flags, first, last, step, chunksize);
+
+ EnterCriticalSection(&vcomp_section);
+ thread_info->dynamic++;
+ if ((int)(thread_info->dynamic - team_info->dynamic) > 0)
+ thread_data->dynamic++;
+ if ((int)(thread_data->dynamic - team_data->dynamic) > 0)
+ {
+ /* first thread in a new for_dynamic */
+
@ -76,102 +76,100 @@ index db47ff6..3a1e9ee 100644
+ 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);
+ team_data->dynamic = thread_data->dynamic;
+ team_data->dynamic_forward = forward;
+ team_data->dynamic_first = first;
+ team_data->dynamic_iterations = iterations;
+ team_data->dynamic_step = step;
+ team_data->dynamic_chunksize = max(1, iterations / team_data->num_threads);
+ team_data->dynamic_min_chunksize = max(1, chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+}
+
+int CDECL _vcomp_for_dynamic_next(int *begin, int *end)
+{
+ struct vcomp_thread_info *thread_info = vcomp_get_thread_info();
+ struct vcomp_team_info *team_info = thread_info->team;
+ struct vcomp_thread_data *thread_data = vcomp_get_thread_data();
+ struct vcomp_team_data *team_data = thread_data->team;
+ unsigned int iterations = 0;
+
+ TRACE("(%p, %p)\n", begin, end);
+
+ EnterCriticalSection(&vcomp_section);
+ if (thread_info->dynamic == team_info->dynamic &&
+ team_info->dynamic_iterations != 0)
+ if (thread_data->dynamic == team_data->dynamic &&
+ team_data->dynamic_iterations != 0)
+ {
+ iterations = min(team_info->dynamic_iterations, team_info->dynamic_chunksize);
+ team_info->dynamic_iterations -= iterations;
+ iterations = min(team_data->dynamic_iterations, team_data->dynamic_chunksize);
+ team_data->dynamic_iterations -= iterations;
+
+ if (team_info->dynamic_forward)
+ if (team_data->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;
+ *begin = team_data->dynamic_first;
+ *end = team_data->dynamic_first + (iterations - 1) * team_data->dynamic_step;
+ team_data->dynamic_first += iterations * team_data->dynamic_step;
+ }
+ else
+ {
+ *begin = team_info->dynamic_first;
+ *end = team_info->dynamic_first - (iterations - 1) * team_info->dynamic_step;
+ team_info->dynamic_first -= iterations * team_info->dynamic_step;
+ *begin = team_data->dynamic_first;
+ *end = team_data->dynamic_first - (iterations - 1) * team_data->dynamic_step;
+ team_data->dynamic_first -= iterations * team_data->dynamic_step;
+ }
+
+ team_info->dynamic_chunksize =
+ max((team_info->dynamic_chunksize * 3 + 2)/4, team_info->dynamic_min_chunksize);
+ team_data->dynamic_chunksize =
+ max((team_data->dynamic_chunksize * 3 + 2)/4, team_data->dynamic_min_chunksize);
+ }
+ LeaveCriticalSection(&vcomp_section);
+
+ return (iterations != 0);
+}
+
void CDECL _vcomp_fork_call_wrapper(void *wrapper, int nargs, __ms_va_list args);
int CDECL omp_in_parallel(void)
{
TRACE("()\n");
@@ -572,11 +661,13 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
team_data.barrier = 0;
team_data.barrier_count = 0;
team_data.section = 0;
+ team_data.dynamic = 0;
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;
thread_data.team = &team_data;
thread_data.thread_num = 0;
thread_data.fork_threads = 0;
thread_data.section = 1;
+ thread_data.dynamic = 1;
list_init(&thread_data.entry);
InitializeConditionVariable(&thread_data.cond);
/* 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;
@@ -593,6 +684,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->thread_num = team_data.num_threads++;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
list_remove(&data->entry);
list_add_tail(&thread_data.entry, &data->entry);
WakeAllConditionVariable(&data->cond);
@@ -612,6 +704,7 @@ void WINAPIV _vcomp_fork(BOOL ifval, int nargs, void *wrapper, ...)
data->thread_num = team_data.num_threads;
data->fork_threads = 0;
data->section = 1;
+ data->dynamic = 1;
InitializeConditionVariable(&data->cond);
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)
thread = CreateThread(NULL, 0, _vcomp_fork_worker, data, 0, NULL);
diff --git a/dlls/vcomp/tests/vcomp.c b/dlls/vcomp/tests/vcomp.c
index 902a836..4273680 100644
index c962fe8..af04cc9 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));
@@ -32,6 +32,8 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
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)
@@ -175,6 +177,8 @@ static BOOL init_vcomp(void)
}
VCOMP_GET_PROC(_vcomp_barrier);
@ -180,7 +178,7 @@ index 902a836..4273680 100644
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)
@@ -807,6 +811,54 @@ static void test_vcomp_sections_init(void)
}
}
@ -235,13 +233,13 @@ index 902a836..4273680 100644
START_TEST(vcomp)
{
if (!init_vcomp())
@@ -593,6 +645,7 @@ START_TEST(vcomp)
@@ -818,6 +870,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);
release_vcomp();
}
diff --git a/dlls/vcomp/vcomp.spec b/dlls/vcomp/vcomp.spec
index 7083ce4..1b02a65 100644