Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org>master
@ -0,0 +1,165 @@ | |||
/* ==================================================================== | |||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* openssl-core@openssl.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* ==================================================================== | |||
*/ | |||
#include <openssl/crypto.h> | |||
#include "internal/threads.h" | |||
#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) | |||
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) | |||
{ | |||
CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(unsigned int)); | |||
if (lock == NULL) | |||
return NULL; | |||
*(unsigned int *)lock = 1; | |||
return lock; | |||
} | |||
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
OPENSSL_assert(*(unsigned int *)lock == 1); | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
OPENSSL_assert(*(unsigned int *)lock == 1); | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) | |||
{ | |||
OPENSSL_assert(*(unsigned int *)lock == 1); | |||
return 1; | |||
} | |||
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) { | |||
if (lock == NULL) | |||
return; | |||
*(unsigned int *)lock = 0; | |||
OPENSSL_free(lock); | |||
return; | |||
} | |||
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) | |||
{ | |||
if (*once != 0) | |||
return 1; | |||
init(); | |||
*once = 1; | |||
return 1; | |||
} | |||
#define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256 | |||
static void *thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX]; | |||
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) | |||
{ | |||
static unsigned int thread_local_key = 0; | |||
if (thread_local_key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) | |||
return 0; | |||
*key = thread_local_key++; | |||
thread_local_storage[*key] = NULL; | |||
return 1; | |||
} | |||
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) | |||
return NULL; | |||
return thread_local_storage[*key]; | |||
} | |||
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) | |||
{ | |||
if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) | |||
return 0; | |||
thread_local_storage[*key] = val; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
*key = OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX + 1; | |||
return 1; | |||
} | |||
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) | |||
{ | |||
return 0; | |||
} | |||
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) | |||
{ | |||
return (a == b); | |||
} | |||
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) | |||
{ | |||
*val += amount; | |||
*ret = *val; | |||
return 1; | |||
} | |||
#endif |
@ -0,0 +1,167 @@ | |||
/* ==================================================================== | |||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* openssl-core@openssl.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* ==================================================================== | |||
*/ | |||
#include <openssl/crypto.h> | |||
#include "internal/threads.h" | |||
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS) | |||
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) | |||
{ | |||
CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t)); | |||
if (lock == NULL) | |||
return NULL; | |||
if (pthread_rwlock_init(lock, NULL) != 0) | |||
return NULL; | |||
return lock; | |||
} | |||
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
if (pthread_rwlock_rdlock(lock) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
if (pthread_rwlock_wrlock(lock) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) | |||
{ | |||
if (pthread_rwlock_unlock(lock) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) | |||
{ | |||
if (lock == NULL) | |||
return; | |||
pthread_rwlock_destroy(lock); | |||
OPENSSL_free(lock); | |||
return; | |||
} | |||
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) | |||
{ | |||
if (pthread_once(once, init) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) | |||
{ | |||
if (pthread_key_create(key, cleanup) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
return pthread_getspecific(*key); | |||
} | |||
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) | |||
{ | |||
if (pthread_setspecific(*key, val) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
if (pthread_key_delete(*key) != 0) | |||
return 0; | |||
return 1; | |||
} | |||
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) | |||
{ | |||
return pthread_self(); | |||
} | |||
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) | |||
{ | |||
return pthread_equal(a, b); | |||
} | |||
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) | |||
{ | |||
#ifdef __ATOMIC_RELAXED | |||
*ret = __atomic_add_fetch(val, amount, __ATOMIC_RELAXED); | |||
#else | |||
if (!CRYPTO_THREAD_write_lock(lock)) | |||
return 0; | |||
*val += amount; | |||
*ret = *val; | |||
if (!CRYPTO_THREAD_unlock(lock)) | |||
return 0; | |||
#endif | |||
return 1; | |||
} | |||
#endif |
@ -0,0 +1,190 @@ | |||
/* ==================================================================== | |||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* openssl-core@openssl.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* ==================================================================== | |||
*/ | |||
#include <openssl/crypto.h> | |||
#include "internal/threads.h" | |||
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS) | |||
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) | |||
{ | |||
CRYPTO_RWLOCK *lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION)); | |||
if (lock == NULL) | |||
return NULL; | |||
/* 0x400 is the spin count value suggested in the documentation */ | |||
if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) | |||
return NULL; | |||
return lock; | |||
} | |||
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
EnterCriticalSection(lock); | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock) | |||
{ | |||
EnterCriticalSection(lock); | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock) | |||
{ | |||
LeaveCriticalSection(lock); | |||
return 1; | |||
} | |||
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock) | |||
{ | |||
if (lock == NULL) | |||
return; | |||
DeleteCriticalSection(lock); | |||
OPENSSL_free(lock); | |||
return; | |||
} | |||
# if _WIN32_WINNT < 0x0600 | |||
# define ONCE_UNINITED 0 | |||
# define ONCE_ININIT 1 | |||
# define ONCE_DONE 2 | |||
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) | |||
{ | |||
LONG volatile *lock = (LONG *)once; | |||
LONG result; | |||
if (*lock == ONCE_DONE) | |||
return 1; | |||
do { | |||
result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); | |||
if (result == ONCE_UNINITED) { | |||
init(); | |||
*lock = ONCE_DONE; | |||
return 1; | |||
} | |||
} while (result == ONCE_ININIT); | |||
return (*lock == ONCE_DONE); | |||
} | |||
# else | |||
BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID p, PVOID *pp) | |||
{ | |||
void (*init)(void) = p; | |||
init(); | |||
return TRUE; | |||
} | |||
void CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) | |||
{ | |||
if (InitOnceExecuteOnce(once, once_cb, init, NULL)) | |||
return 0; | |||
return 1; | |||
} | |||
# endif | |||
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) | |||
{ | |||
*key = TlsAlloc(); | |||
if (*key == TLS_OUT_OF_INDEXES) | |||
return 0; | |||
return 1; | |||
} | |||
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
return TlsGetValue(*key); | |||
} | |||
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) | |||
{ | |||
if (TlsSetValue(*key, val) == 0) | |||
return 0; | |||
return 1; | |||
} | |||
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) | |||
{ | |||
if (TlsFree(*key) == 0) | |||
return 0; | |||
return 1; | |||
} | |||
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void) | |||
{ | |||
return GetCurrentThreadId(); | |||
} | |||
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) | |||
{ | |||
return (a == b); | |||
} | |||
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) | |||
{ | |||
*ret = InterlockedExchangeAdd(val, amount) + amount; | |||
return 1; | |||
} | |||
#endif |
@ -0,0 +1,92 @@ | |||
/* ==================================================================== | |||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* licensing@OpenSSL.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#ifndef HEADER_INTERNAL_THREADS_H | |||
# define HEADER_INTERNAL_THREADS_H | |||
#include "e_os.h" | |||
# if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) | |||
typedef unsigned int CRYPTO_ONCE; | |||
typedef unsigned int CRYPTO_THREAD_LOCAL; | |||
typedef unsigned int CRYPTO_THREAD_ID; | |||
# define CRYPTO_ONCE_STATIC_INIT 0 | |||
# elif defined(OPENSSL_SYS_WINDOWS) | |||
# include <windows.h> | |||
typedef DWORD CRYPTO_THREAD_LOCAL; | |||
typedef DWORD CRYPTO_THREAD_ID; | |||
# if _WIN32_WINNT < 0x0600 | |||
typedef LONG CRYPTO_ONCE; | |||
# define CRYPTO_ONCE_STATIC_INIT 0 | |||
# else | |||
typedef INIT_ONCE CRYPTO_ONCE; | |||
# define CRYPTO_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT | |||
# endif | |||
# else | |||
# include <pthread.h> | |||
typedef pthread_once_t CRYPTO_ONCE; | |||
typedef pthread_key_t CRYPTO_THREAD_LOCAL; | |||
typedef pthread_t CRYPTO_THREAD_ID; | |||
# define CRYPTO_ONCE_STATIC_INIT PTHREAD_ONCE_INIT | |||
# endif | |||
int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)); | |||
int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)); | |||
void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key); | |||
int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val); | |||
int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key); | |||
CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void); | |||
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b); | |||
#endif |
@ -0,0 +1,5 @@ | |||
#! /usr/bin/perl | |||
use OpenSSL::Test::Simple; | |||
simple_test("test_threads", "threadstest"); |
@ -0,0 +1,283 @@ | |||
/* ==================================================================== | |||
* Copyright (c) 2016 The OpenSSL Project. All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. All advertising materials mentioning features or use of this | |||
* software must display the following acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |||
* | |||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |||
* endorse or promote products derived from this software without | |||
* prior written permission. For written permission, please contact | |||
* openssl-core@openssl.org. | |||
* | |||
* 5. Products derived from this software may not be called "OpenSSL" | |||
* nor may "OpenSSL" appear in their names without prior written | |||
* permission of the OpenSSL Project. | |||
* | |||
* 6. Redistributions of any form whatsoever must retain the following | |||
* acknowledgment: | |||
* "This product includes software developed by the OpenSSL Project | |||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |||
* OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* ==================================================================== | |||
*/ | |||
#include <stdio.h> | |||
#include <openssl/crypto.h> | |||
#include "internal/threads.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; | |||
} |