]> git.draconx.ca Git - cdecl99.git/blobdiff - t/errthread.c
libcdecl: Use a different pthread_once workalike for Windows.
[cdecl99.git] / t / errthread.c
index 445fc83e27eec1f0bfd5143c23b486fe9d3301ad..0f1fdf1de0bee3abc6db8d0a7c9cb962815eddce 100644 (file)
@@ -101,6 +101,11 @@ static void run_thread2(void)
        tap_bail_out("run_thread2 failed: %s", strerror(err));
 }
 
+static void check_init_once(void)
+{
+       tap_result(1, "init_once # SKIP test not implemented");
+}
+
 #elif USE_ISOC_THREADS
 #define THREAD_API "isoc"
 #include <threads.h>
@@ -121,6 +126,11 @@ static void run_thread2(void)
        tap_bail_out("run_thread2 failed");
 }
 
+static void check_init_once(void)
+{
+       tap_result(1, "init_once # SKIP test not implemented");
+}
+
 #elif USE_WINDOWS_THREADS
 #define THREAD_API "windows"
 #define WIN32_LEAN_AND_MEAN
@@ -148,6 +158,61 @@ static void run_thread2(void)
 
        tap_bail_out("run_thread2 failed (%lu)", GetLastError());
 }
+
+/* Also include init_once sanity test on Windows */
+#include "thread-w32.h"
+
+HANDLE init_semaphore;
+
+static void init_once_cb(void)
+{
+       tap_result(1, "init_once_cb start");
+
+       ReleaseSemaphore(init_semaphore, 2, NULL);
+       Sleep(1000);
+
+       tap_diag("init_once_cb exit");
+}
+
+static DWORD WINAPI init_thread(LPVOID p)
+{
+       WaitForSingleObject(init_semaphore, INFINITE);
+
+       tap_diag("init_thread start");
+       init_once();
+       tap_diag("init_thread exit");
+
+       return 0;
+}
+
+static void check_init_once(void)
+{
+       HANDLE threads[3];
+       DWORD rc;
+       int i;
+
+       if (!(init_semaphore = CreateSemaphore(NULL, 0, 10, NULL)))
+               tap_bail_out("check_init_once failed (%lu)", GetLastError());
+
+       if (!(threads[0] = CreateThread(NULL, 0, init_thread, NULL, 0, &rc)))
+               tap_bail_out("check_init_once failed (%lu)", GetLastError());
+       if (!(threads[1] = CreateThread(NULL, 0, init_thread, NULL, 0, &rc)))
+               tap_bail_out("check_init_once failed (%lu)", GetLastError());
+       if (!(threads[2] = CreateThread(NULL, 0, init_thread, NULL, 0, &rc)))
+               tap_bail_out("check_init_once failed (%lu)", GetLastError());
+
+       ReleaseSemaphore(init_semaphore, 1, NULL);
+       WaitForMultipleObjects(3, threads, TRUE, INFINITE);
+
+       for (i = 0; i < 3; i++)
+               CloseHandle(threads[i]);
+       CloseHandle(init_semaphore);
+
+       for (i = 0; i < 10000000; i++)
+               init_once();
+}
+
+
 #else
 #undef THREAD_API
 int main(void)
@@ -163,7 +228,7 @@ int main(void)
        const struct cdecl_error *err;
 
        tap_diag("using thread API: " THREAD_API);
-       tap_plan(9);
+       tap_plan(10);
 
        /* Simulate an error in the main thread. */
        cdecl__errmsg(CDECL__ENOMEM);
@@ -195,6 +260,12 @@ int main(void)
         * Main thread allocation should be the only one left.
         */
        tap_result(test_live_allocations() == 1, "thread cleanup");
+
+       /*
+        * Basic init_once sanity check for Windows.
+        */
+       check_init_once();
+
        tap_done();
 }
 #endif