diff options
Diffstat (limited to 'openssl-1.1.0h/test/threadstest.c')
-rw-r--r-- | openssl-1.1.0h/test/threadstest.c | 246 |
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; +} |