[PATCH 1/6] vcomp: better stub for _vcomp_fork
Dan Kegel
dank at kegel.com
Tue Oct 2 23:58:01 CDT 2012
---
configure.ac | 3 +-
dlls/vcomp/Makefile.in | 1 +
dlls/vcomp/fork.c | 157 +++++++++++++++++++++++++++++++++++++++
dlls/vcomp/tests/Makefile.in | 10 +++
dlls/vcomp/tests/fork.c | 81 ++++++++++++++++++++
dlls/vcomp/tests/vcomp.manifest | 21 ++++++
dlls/vcomp/tests/vcomp.rc | 22 ++++++
dlls/vcomp/vcomp.spec | 2 +-
8 files changed, 295 insertions(+), 2 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 5c7e9a2..63c38ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3003,7 +3003,8 @@ WINE_CONFIG_DLL(uxtheme,,[implib])
WINE_CONFIG_TEST(dlls/uxtheme/tests)
WINE_CONFIG_DLL(vbscript)
WINE_CONFIG_TEST(dlls/vbscript/tests)
-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 d256526..971cf0f 100644
--- a/dlls/vcomp/Makefile.in
+++ b/dlls/vcomp/Makefile.in
@@ -1,6 +1,7 @@
MODULE = vcomp.dll
C_SRCS = \
+ fork.c \
main.c
@MAKE_DLL_RULES@
diff --git a/dlls/vcomp/fork.c b/dlls/vcomp/fork.c
new file mode 100644
index 0000000..47a3f7f
--- /dev/null
+++ b/dlls/vcomp/fork.c
@@ -0,0 +1,157 @@
+/*
+ * 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 WINAPIV _vcomp_fork(DWORD parallel, int nargs, void *helper, ...);
+void CDECL _vcomp_fork_body(DWORD parallel, int nargs, void *helper, DWORD *args);
+void CDECL _vcomp_fork_call_helper(void *helper, int nargs, DWORD *args);
+
+
+/* Marshal helper's arguments into array, then call _vcomp_fork_body.
+ * The helper's arguments are always pointers, never floating point numbers.
+ */
+
+#ifdef __i386__
+/* Happily, on x86, we can write the first part in C, too. */
+void WINAPIV _vcomp_fork(DWORD parallel, int nargs, void *helper, ...)
+{
+ va_list valist;
+ va_start(valist, helper);
+ _vcomp_fork_body(parallel, nargs, helper, (DWORD *)valist);
+ va_end(valist);
+}
+#endif
+
+#ifdef __x86_64__
+/* on entry: rcx = parallel, rdx = nargs, r8 = helper, r9 = 1st vararg
+ * The varargs are always pointers.
+ */
+__ASM_GLOBAL_FUNC(_vcomp_fork,
+ "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")
+ "movq %r9,40(%rbp)\n\t" /* 1st vararg to shadow area */
+ "leaq 40(%rbp),%r9\n\t" /* addr of 1st vararg */
+ "callq _vcomp_fork_body\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\n")
+#endif
+
+
+/* Do the actual forking and joining */
+
+void CDECL _vcomp_fork_body(DWORD parallel, int nargs, void *helper, DWORD *args)
+{
+ TRACE("(%d, %d, %p, %p): stub\n", parallel, nargs, helper, args);
+ _vcomp_fork_call_helper(helper, nargs, args);
+}
+
+
+/* Push the arguments back onto the stack, and call the helper
+ * function (usually generated by the visual c compiler)
+ * for this parallel section.
+ */
+
+#ifdef __i386__
+__ASM_GLOBAL_FUNC(_vcomp_fork_call_helper,
+ "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" /* edx = nargs */
+ "movl %esp,%edi\n\t"
+ "shll $2,%edx\n\t"
+ "jz 1f\n\t" /* if (((edx *= sizeof(int))) != 0) */
+ "subl %edx,%edi\n\t" /* reserve space for copy of varargs */
+ "andl $~15,%edi\n\t" /* pad if needed for 16 byte alignmnt */
+ "movl %edi,%esp\n\t" /* esp as if we had pushed varargs */
+ "movl 12(%ebp),%ecx\n\t" /* ecx = nargs */
+ "movl 16(%ebp),%esi\n\t" /* si -> first vararg to copy */
+ "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\n")
+#endif
+
+#ifdef __x86_64__
+/* on entry: rcx = helper, rdx = nargs, r8 = adr of args */
+__ASM_GLOBAL_FUNC(_vcomp_fork_call_helper,
+ "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\n")
+#endif
diff --git a/dlls/vcomp/tests/Makefile.in b/dlls/vcomp/tests/Makefile.in
new file mode 100644
index 0000000..7a2e103
--- /dev/null
+++ b/dlls/vcomp/tests/Makefile.in
@@ -0,0 +1,10 @@
+TESTDLL = vcomp.dll
+IMPORTS = vcomp
+
+C_SRCS = \
+ fork.c
+
+RC_SRCS = \
+ vcomp.rc
+
+ at MAKE_TEST_RULES@
diff --git a/dlls/vcomp/tests/fork.c b/dlls/vcomp/tests/fork.c
new file mode 100644
index 0000000..a82a77b
--- /dev/null
+++ b/dlls/vcomp/tests/fork.c
@@ -0,0 +1,81 @@
+/*
+ * 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 void WINAPIV (*p_vcomp_fork)(DWORD parallel, int nargs, void *helper, ...);
+
+#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);
+
+ return TRUE;
+}
+
+static LONG volatile ncalls;
+
+static void CDECL _test_vcomp_fork_worker1(LONG volatile *p)
+{
+ if (p == 0) {
+ ok(p != 0, "oops, p is NULL\n");
+ }
+ InterlockedIncrement(p);
+}
+
+static void CDECL _test_vcomp_fork_worker5(int a, int b, int c, int d, int 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", d);
+ InterlockedIncrement(&ncalls);
+}
+
+static void test_vcomp_fork(void)
+{
+ ncalls = 0;
+ p_vcomp_fork(0, 1, _test_vcomp_fork_worker1, &ncalls);
+ ok(ncalls == 1, "expected 1 call, got %d\n", ncalls);
+
+ ncalls = 0;
+ p_vcomp_fork(0, 5, _test_vcomp_fork_worker5, 1, 2, 3, 4, 5);
+ ok(ncalls == 1, "expected 1 call, got %d\n", ncalls);
+
+ ncalls = 0;
+ p_vcomp_fork(1, 5, _test_vcomp_fork_worker5, 1, 2, 3, 4, 5);
+ ok(ncalls >= 1, "expected >= 1 call, got %d\n", ncalls);
+}
+
+START_TEST(fork)
+{
+ if (!init())
+ return;
+
+ test_vcomp_fork();
+}
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 41b57fb..1378c8d 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
--
1.7.9.5
More information about the wine-patches
mailing list