Piotr Caban : msvcp120: Added _Call_once implementation.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 22 04:48:25 CDT 2015


Module: wine
Branch: master
Commit: a7a3cd84b5581ccb1ac06a7788b4982c0deecde6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a7a3cd84b5581ccb1ac06a7788b4982c0deecde6

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed May 20 22:18:58 2015 +0200

msvcp120: Added _Call_once implementation.

---

 dlls/msvcp110/msvcp110.spec         |  4 +--
 dlls/msvcp120/msvcp120.spec         |  4 +--
 dlls/msvcp120/tests/msvcp120.c      | 55 +++++++++++++++++++++++++++++++++++++
 dlls/msvcp120_app/msvcp120_app.spec |  4 +--
 dlls/msvcp90/misc.c                 | 35 +++++++++++++++++++++++
 5 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/dlls/msvcp110/msvcp110.spec b/dlls/msvcp110/msvcp110.spec
index 3be4944..c87eb66 100644
--- a/dlls/msvcp110/msvcp110.spec
+++ b/dlls/msvcp110/msvcp110.spec
@@ -3727,8 +3727,8 @@
 @ cdecl -ret64 -arch=arm ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAA_JPB_W_J at Z(ptr wstr int64) basic_streambuf_wchar_xsputn
 @ thiscall -ret64 -arch=i386 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAE_JPB_W_J at Z(ptr wstr int64) basic_streambuf_wchar_xsputn
 @ cdecl -arch=win64 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MEAA_JPEB_W_J at Z(ptr ptr long) basic_streambuf_wchar_xsputn
-@ stub _Call_once
-@ stub _Call_onceEx
+@ cdecl _Call_once(ptr ptr)
+@ cdecl _Call_onceEx(ptr ptr ptr)
 @ stub _Cnd_broadcast
 @ stub _Cnd_destroy
 @ stub _Cnd_do_broadcast_at_thread_exit
diff --git a/dlls/msvcp120/msvcp120.spec b/dlls/msvcp120/msvcp120.spec
index d8187d5..b84a380 100644
--- a/dlls/msvcp120/msvcp120.spec
+++ b/dlls/msvcp120/msvcp120.spec
@@ -3668,8 +3668,8 @@
 @ cdecl -ret64 -arch=arm ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAA_JPB_W_J at Z(ptr wstr int64) basic_streambuf_wchar_xsputn
 @ thiscall -ret64 -arch=i386 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAE_JPB_W_J at Z(ptr wstr int64) basic_streambuf_wchar_xsputn
 @ cdecl -arch=win64 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MEAA_JPEB_W_J at Z(ptr ptr long) basic_streambuf_wchar_xsputn
-@ stub _Call_once
-@ stub _Call_onceEx
+@ cdecl _Call_once(ptr ptr)
+@ cdecl _Call_onceEx(ptr ptr ptr)
 @ stub _Cnd_broadcast
 @ stub _Cnd_destroy
 @ stub _Cnd_do_broadcast_at_thread_exit
diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
index 32ca437..f89543f 100644
--- a/dlls/msvcp120/tests/msvcp120.c
+++ b/dlls/msvcp120/tests/msvcp120.c
@@ -43,6 +43,8 @@ static int (__cdecl *p_isleadbyte)(int);
 static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
 static int (__cdecl *p_xtime_get)(xtime*, int);
 static _Cvtvec* (__cdecl *p__Getcvt)(_Cvtvec*);
+static void (CDECL *p__Call_once)(int *once, void (CDECL *func)(void));
+static void (CDECL *p__Call_onceEx)(int *once, void (CDECL *func)(void*), void *argv);
 
 static HMODULE msvcp;
 
@@ -60,6 +62,8 @@ static BOOL init(void)
     p__Xtime_diff_to_millis2 = (void*)GetProcAddress(msvcp, "_Xtime_diff_to_millis2");
     p_xtime_get = (void*)GetProcAddress(msvcp, "xtime_get");
     p__Getcvt = (void*)GetProcAddress(msvcp, "_Getcvt");
+    p__Call_once = (void*)GetProcAddress(msvcp, "_Call_once");
+    p__Call_onceEx = (void*)GetProcAddress(msvcp, "_Call_onceEx");
 
     msvcr = GetModuleHandleA("msvcr120.dll");
     p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
@@ -190,12 +194,63 @@ static void test__Getcvt(void)
     }
 }
 
+static int cnt;
+static int once;
+
+static void __cdecl call_once_func(void)
+{
+    ok(!once, "once != 0\n");
+    cnt += 0x10000;
+}
+
+static void __cdecl call_once_ex_func(void *arg)
+{
+    int *i = arg;
+
+    ok(!once, "once != 0\n");
+    (*i)++;
+}
+
+DWORD WINAPI call_once_thread(void *arg)
+{
+    p__Call_once(&once, call_once_func);
+    return 0;
+}
+
+DWORD WINAPI call_once_ex_thread(void *arg)
+{
+    p__Call_onceEx(&once, call_once_ex_func, &cnt);
+    return 0;
+}
+
+static void test__Call_once(void)
+{
+    HANDLE h[4];
+    int i;
+
+    for(i=0; i<4; i++)
+        h[i] = CreateThread(NULL, 0, call_once_thread, &once, 0, NULL);
+    ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
+            "error waiting for all threads to finish\n");
+    ok(cnt == 0x10000, "cnt = %x\n", cnt);
+    ok(once == 1, "once = %x\n", once);
+
+    once = cnt = 0;
+    for(i=0; i<4; i++)
+        h[i] = CreateThread(NULL, 0, call_once_ex_thread, &once, 0, NULL);
+    ok(WaitForMultipleObjects(4, h, TRUE, INFINITE) == WAIT_OBJECT_0,
+            "error waiting for all threads to finish\n");
+    ok(cnt == 1, "cnt = %x\n", cnt);
+    ok(once == 1, "once = %x\n", once);
+}
+
 START_TEST(msvcp120)
 {
     if(!init()) return;
     test__Xtime_diff_to_millis2();
     test_xtime_get();
     test__Getcvt();
+    test__Call_once();
 
     FreeLibrary(msvcp);
 }
diff --git a/dlls/msvcp120_app/msvcp120_app.spec b/dlls/msvcp120_app/msvcp120_app.spec
index bd949be..bdfea8b 100644
--- a/dlls/msvcp120_app/msvcp120_app.spec
+++ b/dlls/msvcp120_app/msvcp120_app.spec
@@ -3668,8 +3668,8 @@
 @ cdecl -ret64 -arch=arm ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAA_JPB_W_J at Z(ptr wstr int64) msvcp120.?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAA_JPB_W_J at Z
 @ thiscall -ret64 -arch=i386 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAE_JPB_W_J at Z(ptr wstr int64) msvcp120.?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MAE_JPB_W_J at Z
 @ cdecl -arch=win64 ?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MEAA_JPEB_W_J at Z(ptr ptr long) msvcp120.?xsputn@?$basic_streambuf at _WU?$char_traits at _W@std@@@std@@MEAA_JPEB_W_J at Z
-@ stub _Call_once
-@ stub _Call_onceEx
+@ cdecl _Call_once(ptr ptr) msvcp120._Call_once
+@ cdecl _Call_onceEx(ptr ptr ptr) msvcp120._Call_onceEx
 @ stub _Cnd_broadcast
 @ stub _Cnd_destroy
 @ stub _Cnd_do_broadcast_at_thread_exit
diff --git a/dlls/msvcp90/misc.c b/dlls/msvcp90/misc.c
index 51b2a67..22f90c8 100644
--- a/dlls/msvcp90/misc.c
+++ b/dlls/msvcp90/misc.c
@@ -630,6 +630,41 @@ void __asm_dummy_vtables(void) {
 #endif
 #endif
 
+#if _MSVCP_VER >= 110
+static CRITICAL_SECTION call_once_cs;
+static CRITICAL_SECTION_DEBUG call_once_cs_debug =
+{
+    0, 0, &call_once_cs,
+    { &call_once_cs_debug.ProcessLocksList, &call_once_cs_debug.ProcessLocksList },
+    0, 0, { (DWORD_PTR)(__FILE__ ": call_once_cs") }
+};
+static CRITICAL_SECTION call_once_cs = { &call_once_cs_debug, -1, 0, 0, 0, 0 };
+
+void __cdecl _Call_onceEx(int *once, void (__cdecl *func)(void*), void *argv)
+{
+    TRACE("%p %p %p\n", once, func, argv);
+
+    EnterCriticalSection(&call_once_cs);
+    if(!*once) {
+        /* FIXME: handle exceptions */
+        func(argv);
+        *once = 1;
+    }
+    LeaveCriticalSection(&call_once_cs);
+}
+
+void __cdecl call_once_func_wrapper(void *func)
+{
+    ((void (__cdecl*)(void))func)();
+}
+
+void __cdecl _Call_once(int *once, void (__cdecl *func)(void))
+{
+    TRACE("%p %p\n", once, func);
+    _Call_onceEx(once, call_once_func_wrapper, func);
+}
+#endif
+
 void init_misc(void *base)
 {
 #ifdef __x86_64__




More information about the wine-cvs mailing list