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>
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
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)
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);
* 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