Nikolay Sivov : kernel32: Some tests for blocking initialization with InitOnceBeginInitialize().

Alexandre Julliard julliard at winehq.org
Tue Jul 24 14:39:28 CDT 2012


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Jul 24 13:39:12 2012 +0400

kernel32: Some tests for blocking initialization with InitOnceBeginInitialize().

---

 dlls/kernel32/tests/sync.c |   64 ++++++++++++++++++++++++++++++++++---------
 include/winbase.h          |    6 +++-
 include/winnt.h            |    9 +++++-
 3 files changed, 63 insertions(+), 16 deletions(-)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index 97139a9..6e55381 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -39,6 +39,8 @@ static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFI
 static BOOL   (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
 static VOID   (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
 static BOOL   (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
+static BOOL   (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
+static BOOL   (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
 
 static void test_signalandwait(void)
 {
@@ -1138,11 +1140,13 @@ static void test_WaitForMultipleObjects(void)
 }
 
 static BOOL g_initcallback_ret, g_initcallback_called;
+static void *g_initctxt;
 
 BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
 {
     g_initcallback_called = TRUE;
     /* zero bit set means here that initialization is taking place - initialization locked */
+    ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
     ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
     ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
     return g_initcallback_ret;
@@ -1151,8 +1155,7 @@ BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctx
 static void test_initonce(void)
 {
     INIT_ONCE initonce;
-    void *ctxt;
-    BOOL ret;
+    BOOL ret, pending;
 
     if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
     {
@@ -1160,48 +1163,79 @@ static void test_initonce(void)
         return;
     }
 
+    /* blocking initialization with callback */
     initonce.Ptr = (void*)0xdeadbeef;
     pInitOnceInitialize(&initonce);
     ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
 
     /* initialisation completed successfully */
     g_initcallback_ret = TRUE;
-    ctxt = NULL;
-    ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
+    g_initctxt = NULL;
+    ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
     ok(ret, "got wrong ret value %d\n", ret);
     ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
-    ok(ctxt == (void*)0x0, "got %p\n", ctxt);
+    ok(g_initctxt == (void*)0x0, "got %p\n", g_initctxt);
     ok(g_initcallback_called, "got %d\n", g_initcallback_called);
 
     /* so it's been called already so won't be called again */
-    ctxt = NULL;
+    g_initctxt = NULL;
     g_initcallback_called = FALSE;
-    ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
+    ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
     ok(ret, "got wrong ret value %d\n", ret);
     ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
-    ok(ctxt == (void*)0, "got %p\n", ctxt);
+    ok(g_initctxt == (void*)0, "got %p\n", g_initctxt);
     ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
 
     pInitOnceInitialize(&initonce);
     g_initcallback_called = FALSE;
     /* 2 lower order bits should never be used, you'll get a crash in result */
-    ctxt = (void*)0xFFFFFFF0;
-    ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
+    g_initctxt = (void*)0xFFFFFFF0;
+    ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
     ok(ret, "got wrong ret value %d\n", ret);
     ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
-    ok(ctxt == (void*)0xFFFFFFF0, "got %p\n", ctxt);
+    ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
     ok(g_initcallback_called, "got %d\n", g_initcallback_called);
 
     /* callback failed */
     g_initcallback_ret = FALSE;
     g_initcallback_called = FALSE;
-    ctxt = NULL;
+    g_initctxt = NULL;
     pInitOnceInitialize(&initonce);
-    ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
+    ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
     ok(!ret, "got wrong ret value %d\n", ret);
     ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
-    ok(ctxt == NULL, "got %p\n", ctxt);
+    ok(g_initctxt == NULL, "got %p\n", g_initctxt);
     ok(g_initcallback_called, "got %d\n", g_initcallback_called);
+
+    /* blocking initialzation without a callback */
+    pInitOnceInitialize(&initonce);
+    g_initctxt = NULL;
+    pending = FALSE;
+    ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
+    ok(ret, "got wrong ret value %d\n", ret);
+    ok(pending, "got %d\n", pending);
+    ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
+    ok(g_initctxt == NULL, "got %p\n", g_initctxt);
+    /* another attempt to begin initialization with block a single thread */
+
+    g_initctxt = NULL;
+    pending = 0xf;
+    ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
+    ok(!ret, "got wrong ret value %d\n", ret);
+    ok(pending == 0xf, "got %d\n", pending);
+    ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
+    ok(g_initctxt == NULL, "got %p\n", g_initctxt);
+
+    g_initctxt = (void*)0xdeadbee0;
+    ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
+    ok(!ret, "got wrong ret value %d\n", ret);
+    ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
+
+    /* once failed already */
+    g_initctxt = (void*)0xdeadbee0;
+    ret = pInitOnceComplete(&initonce, 0, g_initctxt);
+    ok(ret, "got wrong ret value %d\n", ret);
+    ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
 }
 
 START_TEST(sync)
@@ -1218,6 +1252,8 @@ START_TEST(sync)
     pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
     pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
     pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
+    pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
+    pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
 
     test_signalandwait();
     test_mutex();
diff --git a/include/winbase.h b/include/winbase.h
index 0bc5755..bc765f1 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1320,7 +1320,10 @@ typedef struct _WIN32_STREAM_ID {
 typedef RTL_RUN_ONCE  INIT_ONCE;
 typedef PRTL_RUN_ONCE PINIT_ONCE;
 typedef PRTL_RUN_ONCE LPINIT_ONCE;
-#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
+#define INIT_ONCE_STATIC_INIT       RTL_RUN_ONCE_INIT
+#define INIT_ONCE_CHECK_ONLY        RTL_RUN_ONCE_CHECK_ONLY
+#define INIT_ONCE_ASYNC             RTL_RUN_ONCE_ASYNC
+#define INIT_ONCE_INIT_FAILED       RTL_RUN_ONCE_INIT_FAILED
 /* initialization callback prototype */
 typedef BOOL (WINAPI *PINIT_ONCE_FN)(PINIT_ONCE,PVOID,PVOID*);
 
@@ -1884,6 +1887,7 @@ WINADVAPI  BOOL        WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR,
 WINADVAPI  BOOL        WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE);
 WINBASEAPI VOID        WINAPI InitializeSListHead(PSLIST_HEADER);
 WINBASEAPI VOID        WINAPI InitializeSRWLock(PSRWLOCK);
+WINBASEAPI BOOL        WINAPI InitOnceExecuteOnce(PINIT_ONCE,PINIT_ONCE_FN,PVOID,PVOID*);
 WINBASEAPI VOID        WINAPI InitOnceInitialize(PINIT_ONCE);
 WINBASEAPI PSLIST_ENTRY WINAPI InterlockedFlushSList(PSLIST_HEADER);
 WINBASEAPI PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER);
diff --git a/include/winnt.h b/include/winnt.h
index d65e2f6..b679017 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5092,7 +5092,14 @@ typedef union _RTL_RUN_ONCE {
     PVOID Ptr;
 } RTL_RUN_ONCE, *PRTL_RUN_ONCE;
 
-NTSYSAPI VOID NTAPI RtlRunOnceInitialize(PRTL_RUN_ONCE);
+#define RTL_RUN_ONCE_CHECK_ONLY     0x00000001
+#define RTL_RUN_ONCE_ASYNC          0x00000002
+#define RTL_RUN_ONCE_INIT_FAILED    0x00000004
+
+typedef DWORD WINAPI RTL_RUN_ONCE_INIT_FN(PRTL_RUN_ONCE, PVOID, PVOID*);
+typedef RTL_RUN_ONCE_INIT_FN *PRTL_RUN_ONCE_INIT_FN;
+NTSYSAPI VOID WINAPI RtlRunOnceInitialize(PRTL_RUN_ONCE);
+NTSYSAPI DWORD WINAPI RtlRunOnceExecuteOnce(PRTL_RUN_ONCE,PRTL_RUN_ONCE_INIT_FN,PVOID,PVOID*);
 
 #include <pshpack8.h>
 typedef struct _IO_COUNTERS {




More information about the wine-cvs mailing list