aboutsummaryrefslogtreecommitdiff
path: root/openssl-1.1.0h/test/threadstest.c
diff options
context:
space:
mode:
Diffstat (limited to 'openssl-1.1.0h/test/threadstest.c')
-rw-r--r--openssl-1.1.0h/test/threadstest.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/openssl-1.1.0h/test/threadstest.c b/openssl-1.1.0h/test/threadstest.c
new file mode 100644
index 0000000..b2e96fa
--- /dev/null
+++ b/openssl-1.1.0h/test/threadstest.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+#include <stdio.h>
+
+#include <openssl/crypto.h>
+
+#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
+
+typedef unsigned int thread_t;
+
+static int run_thread(thread_t *t, void (*f)(void))
+{
+ f();
+ return 1;
+}
+
+static int wait_for_thread(thread_t thread)
+{
+ return 1;
+}
+
+#elif defined(OPENSSL_SYS_WINDOWS)
+
+typedef HANDLE thread_t;
+
+static DWORD WINAPI thread_run(LPVOID arg)
+{
+ void (*f)(void);
+
+ *(void **) (&f) = arg;
+
+ f();
+ return 0;
+}
+
+static int run_thread(thread_t *t, void (*f)(void))
+{
+ *t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL);
+ return *t != NULL;
+}
+
+static int wait_for_thread(thread_t thread)
+{
+ return WaitForSingleObject(thread, INFINITE) == 0;
+}
+
+#else
+
+typedef pthread_t thread_t;
+
+static void *thread_run(void *arg)
+{
+ void (*f)(void);
+
+ *(void **) (&f) = arg;
+
+ f();
+ return NULL;
+}
+
+static int run_thread(thread_t *t, void (*f)(void))
+{
+ return pthread_create(t, NULL, thread_run, *(void **) &f) == 0;
+}
+
+static int wait_for_thread(thread_t thread)
+{
+ return pthread_join(thread, NULL) == 0;
+}
+
+#endif
+
+static int test_lock(void)
+{
+ CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
+
+ if (!CRYPTO_THREAD_read_lock(lock)) {
+ fprintf(stderr, "CRYPTO_THREAD_read_lock() failed\n");
+ return 0;
+ }
+
+ if (!CRYPTO_THREAD_unlock(lock)) {
+ fprintf(stderr, "CRYPTO_THREAD_unlock() failed\n");
+ return 0;
+ }
+
+ CRYPTO_THREAD_lock_free(lock);
+
+ return 1;
+}
+
+static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
+static unsigned once_run_count = 0;
+
+static void once_do_run(void)
+{
+ once_run_count++;
+}
+
+static void once_run_thread_cb(void)
+{
+ CRYPTO_THREAD_run_once(&once_run, once_do_run);
+}
+
+static int test_once(void)
+{
+ thread_t thread;
+ if (!run_thread(&thread, once_run_thread_cb) ||
+ !wait_for_thread(thread))
+ {
+ fprintf(stderr, "run_thread() failed\n");
+ return 0;
+ }
+
+ if (!CRYPTO_THREAD_run_once(&once_run, once_do_run)) {
+ fprintf(stderr, "CRYPTO_THREAD_run_once() failed\n");
+ return 0;
+ }
+
+ if (once_run_count != 1) {
+ fprintf(stderr, "once run %u times\n", once_run_count);
+ return 0;
+ }
+
+ return 1;
+}
+
+static CRYPTO_THREAD_LOCAL thread_local_key;
+static unsigned destructor_run_count = 0;
+static int thread_local_thread_cb_ok = 0;
+
+static void thread_local_destructor(void *arg)
+{
+ unsigned *count;
+
+ if (arg == NULL)
+ return;
+
+ count = arg;
+
+ (*count)++;
+}
+
+static void thread_local_thread_cb(void)
+{
+ void *ptr;
+
+ ptr = CRYPTO_THREAD_get_local(&thread_local_key);
+ if (ptr != NULL) {
+ fprintf(stderr, "ptr not NULL\n");
+ return;
+ }
+
+ if (!CRYPTO_THREAD_set_local(&thread_local_key, &destructor_run_count)) {
+ fprintf(stderr, "CRYPTO_THREAD_set_local() failed\n");
+ return;
+ }
+
+ ptr = CRYPTO_THREAD_get_local(&thread_local_key);
+ if (ptr != &destructor_run_count) {
+ fprintf(stderr, "invalid ptr\n");
+ return;
+ }
+
+ thread_local_thread_cb_ok = 1;
+}
+
+static int test_thread_local(void)
+{
+ thread_t thread;
+ void *ptr = NULL;
+
+ if (!CRYPTO_THREAD_init_local(&thread_local_key, thread_local_destructor)) {
+ fprintf(stderr, "CRYPTO_THREAD_init_local() failed\n");
+ return 0;
+ }
+
+ ptr = CRYPTO_THREAD_get_local(&thread_local_key);
+ if (ptr != NULL) {
+ fprintf(stderr, "ptr not NULL\n");
+ return 0;
+ }
+
+ if (!run_thread(&thread, thread_local_thread_cb) ||
+ !wait_for_thread(thread))
+ {
+ fprintf(stderr, "run_thread() failed\n");
+ return 0;
+ }
+
+ if (thread_local_thread_cb_ok != 1) {
+ fprintf(stderr, "thread-local thread callback failed\n");
+ return 0;
+ }
+
+#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
+
+ ptr = CRYPTO_THREAD_get_local(&thread_local_key);
+ if (ptr != NULL) {
+ fprintf(stderr, "ptr not NULL\n");
+ return 0;
+ }
+
+# if !defined(OPENSSL_SYS_WINDOWS)
+ if (destructor_run_count != 1) {
+ fprintf(stderr, "thread-local destructor run %u times\n",
+ destructor_run_count);
+ return 0;
+ }
+# endif
+
+#endif
+
+ if (!CRYPTO_THREAD_cleanup_local(&thread_local_key)) {
+ fprintf(stderr, "CRYPTO_THREAD_cleanup_local() failed\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ if (!test_lock())
+ return 1;
+
+ if (!test_once())
+ return 1;
+
+ if (!test_thread_local())
+ return 1;
+
+ printf("PASS\n");
+ return 0;
+}