From: Dan Kegel Subject: [PATCH 1/6] vcomp: better stub for _vcomp_fork Message-Id: <1349240286-15004-1-git-send-email-dank@kegel.com> Date: Tue, 2 Oct 2012 21:58:01 -0700 --- 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 + +#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 + +@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 @@ + + + +Wine vcomp test suite + + + + + + 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