mirror of
https://github.com/openssl/openssl.git
synced 2024-12-09 05:51:54 +08:00
Implement new multi-threading API
Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org>
This commit is contained in:
parent
bdcd83e127
commit
71a04cfca0
@ -34,9 +34,11 @@ LIB= $(TOP)/libcrypto.a
|
||||
SHARED_LIB= libcrypto$(SHLIB_EXT)
|
||||
LIBSRC= cryptlib.c mem.c mem_clr.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
|
||||
ebcdic.c uid.c o_time.c o_str.c o_dir.c thr_id.c lock.c \
|
||||
threads_pthread.c threads_win.c threads_none.c \
|
||||
o_init.c o_fips.c mem_sec.c init.c
|
||||
LIBOBJ= cryptlib.o mem.o mem_dbg.o cversion.o ex_data.o cpt_err.o \
|
||||
ebcdic.o uid.o o_time.o o_str.o o_dir.o thr_id.o lock.o \
|
||||
threads_pthread.o threads_win.o threads_none.o \
|
||||
o_init.o o_fips.o mem_sec.o init.o $(CPUID_OBJ)
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
@ -3,6 +3,7 @@ LIBS=../libcrypto
|
||||
SOURCE[../libcrypto]=\
|
||||
cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
|
||||
ebcdic.c uid.c o_time.c o_str.c o_dir.c thr_id.c lock.c \
|
||||
threads_pthread.c threads_win.c threads_none.c \
|
||||
o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -}
|
||||
EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
|
||||
x86cpuid.pl x86_64cpuid.pl ia64cpuid.S \
|
||||
|
165
crypto/threads_none.c
Normal file
165
crypto/threads_none.c
Normal file
@ -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
|
167
crypto/threads_pthread.c
Normal file
167
crypto/threads_pthread.c
Normal file
@ -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
|
190
crypto/threads_win.c
Normal file
190
crypto/threads_win.c
Normal file
@ -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
|
@ -2,176 +2,66 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
CRYPTO_THREADID_set_callback, CRYPTO_THREADID_get_callback,
|
||||
CRYPTO_THREADID_current, CRYPTO_THREADID_cmp, CRYPTO_THREADID_cpy,
|
||||
CRYPTO_THREADID_hash, CRYPTO_set_locking_callback, CRYPTO_num_locks,
|
||||
CRYPTO_set_dynlock_create_callback, CRYPTO_set_dynlock_lock_callback,
|
||||
CRYPTO_set_dynlock_destroy_callback, CRYPTO_get_new_dynlockid,
|
||||
CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
|
||||
CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock,
|
||||
CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free, CRYPTO_atomic_add - OpenSSL thread support
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
/* Don't use this structure directly. */
|
||||
typedef struct crypto_threadid_st
|
||||
{
|
||||
void *ptr;
|
||||
unsigned long val;
|
||||
} CRYPTO_THREADID;
|
||||
/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
|
||||
void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val);
|
||||
void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
|
||||
int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID *));
|
||||
void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *);
|
||||
void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
|
||||
int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a,
|
||||
const CRYPTO_THREADID *b);
|
||||
void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest,
|
||||
const CRYPTO_THREADID *src);
|
||||
unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
|
||||
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
|
||||
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
|
||||
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
|
||||
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
|
||||
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
|
||||
|
||||
int CRYPTO_num_locks(void);
|
||||
|
||||
/* struct CRYPTO_dynlock_value needs to be defined by the user */
|
||||
struct CRYPTO_dynlock_value;
|
||||
|
||||
void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *
|
||||
(*dyn_create_function)(const char *file, int line));
|
||||
void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)
|
||||
(int mode, struct CRYPTO_dynlock_value *l,
|
||||
const char *file, int line));
|
||||
void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)
|
||||
(struct CRYPTO_dynlock_value *l, const char *file, int line));
|
||||
|
||||
int CRYPTO_get_new_dynlockid(void);
|
||||
|
||||
void CRYPTO_destroy_dynlockid(int i);
|
||||
|
||||
void CRYPTO_lock(int mode, int n, const char *file, int line);
|
||||
|
||||
#define CRYPTO_w_lock(type) \
|
||||
CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
|
||||
#define CRYPTO_w_unlock(type) \
|
||||
CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,OPENSSL_FILE,OPENSSL_LINE)
|
||||
#define CRYPTO_r_lock(type) \
|
||||
CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
|
||||
#define CRYPTO_r_unlock(type) \
|
||||
CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,OPENSSL_FILE,OPENSSL_LINE)
|
||||
#define CRYPTO_add(addr,amount,type) \
|
||||
CRYPTO_add_lock(addr,amount,type,OPENSSL_FILE,OPENSSL_LINE)
|
||||
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
OpenSSL can safely be used in multi-threaded applications provided
|
||||
that at least two callback functions are set, locking_function and
|
||||
threadid_func.
|
||||
OpenSSL can be safely used in multi-threaded applications provided that
|
||||
support for the underlying OS threading API is built-in. Currently, OpenSSL
|
||||
supports the pthread and Windows APIs. OpenSSL can also be built without
|
||||
any multi-threading support, for example on platforms that don't provide
|
||||
any threading support or that provide a threading API that is not yet
|
||||
supported by OpenSSL.
|
||||
|
||||
locking_function(int mode, int n, const char *file, int line) is
|
||||
needed to perform locking on shared data structures.
|
||||
(Note that OpenSSL uses a number of global data structures that
|
||||
will be implicitly shared whenever multiple threads use OpenSSL.)
|
||||
Multi-threaded applications will crash at random if it is not set.
|
||||
|
||||
locking_function() must be able to handle up to CRYPTO_num_locks()
|
||||
different mutex locks. It sets the B<n>-th lock if B<mode> &
|
||||
B<CRYPTO_LOCK>, and releases it otherwise.
|
||||
|
||||
B<file> and B<line> are the file number of the function setting the
|
||||
lock. They can be useful for debugging.
|
||||
|
||||
threadid_func(CRYPTO_THREADID *id) is needed to record the currently-executing
|
||||
thread's identifier into B<id>. The implementation of this callback should not
|
||||
fill in B<id> directly, but should use CRYPTO_THREADID_set_numeric() if thread
|
||||
IDs are numeric, or CRYPTO_THREADID_set_pointer() if they are pointer-based.
|
||||
The B<id> must be unique for the duration of the execution of the program.
|
||||
If the application does not register such a callback using
|
||||
CRYPTO_THREADID_set_callback(), then a default implementation is used - on
|
||||
Windows this uses the system's default thread identifying APIs, and on
|
||||
all other platforms it uses the address of B<errno>. The latter is satisfactory
|
||||
for thread-safety if and only if the platform has a thread-local error number
|
||||
facility.
|
||||
|
||||
Once threadid_func() is registered, or if the built-in default implementation is
|
||||
to be used;
|
||||
The following multi-threading function are provided:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
CRYPTO_THREADID_current() records the currently-executing thread ID into the
|
||||
given B<id> object.
|
||||
CRYPTO_THREAD_lock_new() allocates, initializes and returns a new read/write
|
||||
lock.
|
||||
|
||||
=item *
|
||||
CRYPTO_THREADID_cmp() compares two thread IDs (returning zero for equality, ie.
|
||||
the same semantics as memcmp()).
|
||||
CRYPTO_THREAD_read_lock() locks the provided B<lock> for reading.
|
||||
|
||||
=item *
|
||||
CRYPTO_THREADID_cpy() duplicates a thread ID value,
|
||||
CRYPTO_THREAD_write_lock() locks the provided B<lock> for writing.
|
||||
|
||||
=item *
|
||||
CRYPTO_THREADID_hash() returns a numeric value usable as a hash-table key. This
|
||||
is usually the exact numeric or pointer-based thread ID used internally, however
|
||||
this also handles the unusual case where pointers are larger than 'long'
|
||||
variables and the platform's thread IDs are pointer-based - in this case, mixing
|
||||
is done to attempt to produce a unique numeric value even though it is not as
|
||||
wide as the platform's true thread IDs.
|
||||
CRYPTO_THREAD_unlock() unlocks the previously locked B<lock>.
|
||||
|
||||
=item *
|
||||
CRYPTO_THREAD_lock_frees() frees the provided B<lock>.
|
||||
|
||||
=item *
|
||||
CRYPTO_atomic_add() atomically adds B<amount> to B<val> and returns the
|
||||
result of the operation in B<ret>. B<lock> will be locked, unless atomic
|
||||
operations are supported on the specific platform. Because of this, if a
|
||||
variable is modified by CRYPTO_atomic_add() then CRYPTO_atomic_add() must
|
||||
be the only way that the variable is modified.
|
||||
|
||||
=back
|
||||
|
||||
Additionally, OpenSSL supports dynamic locks, and sometimes, some parts
|
||||
of OpenSSL need it for better performance. To enable this, the following
|
||||
is required:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
Three additional callback function, dyn_create_function, dyn_lock_function
|
||||
and dyn_destroy_function.
|
||||
|
||||
=item *
|
||||
A structure defined with the data that each lock needs to handle.
|
||||
|
||||
=back
|
||||
|
||||
struct CRYPTO_dynlock_value has to be defined to contain whatever structure
|
||||
is needed to handle locks.
|
||||
|
||||
dyn_create_function(const char *file, int line) is needed to create a
|
||||
lock. Multi-threaded applications might crash at random if it is not set.
|
||||
|
||||
dyn_lock_function(int mode, CRYPTO_dynlock *l, const char *file, int line)
|
||||
is needed to perform locking off dynamic lock numbered n. Multi-threaded
|
||||
applications might crash at random if it is not set.
|
||||
|
||||
dyn_destroy_function(CRYPTO_dynlock *l, const char *file, int line) is
|
||||
needed to destroy the lock l. Multi-threaded applications might crash at
|
||||
random if it is not set.
|
||||
|
||||
CRYPTO_get_new_dynlockid() is used to create locks. It will call
|
||||
dyn_create_function for the actual creation.
|
||||
|
||||
CRYPTO_destroy_dynlockid() is used to destroy locks. It will call
|
||||
dyn_destroy_function for the actual destruction.
|
||||
|
||||
CRYPTO_lock() is used to lock and unlock the locks. mode is a bitfield
|
||||
describing what should be done with the lock. n is the number of the
|
||||
lock as returned from CRYPTO_get_new_dynlockid(). mode can be combined
|
||||
from the following values. These values are pairwise exclusive, with
|
||||
undefined behaviour if misused (for example, CRYPTO_READ and CRYPTO_WRITE
|
||||
should not be used together):
|
||||
|
||||
CRYPTO_LOCK 0x01
|
||||
CRYPTO_UNLOCK 0x02
|
||||
CRYPTO_READ 0x04
|
||||
CRYPTO_WRITE 0x08
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
CRYPTO_num_locks() returns the required number of locks.
|
||||
CRYPTO_THREAD_lock_new() returns the allocated lock, or NULL on error.
|
||||
|
||||
CRYPTO_get_new_dynlockid() returns the index to the newly created lock.
|
||||
CRYPTO_THREAD_lock_frees() returns no value.
|
||||
|
||||
The other functions return no values.
|
||||
The other functions return 1 on success or 0 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
@ -185,21 +75,6 @@ You can find out if OpenSSL was configured with thread support:
|
||||
// no thread support
|
||||
#endif
|
||||
|
||||
Also, dynamic locks are currently not used internally by OpenSSL, but
|
||||
may do so in the future.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
B<crypto/threads/mttest.c> shows examples of the callback functions on
|
||||
Solaris, Irix and Win32.
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
B<CRYPTO_THREADID> and associated functions were introduced in OpenSSL 1.0.0
|
||||
to replace (actually, deprecate) the previous CRYPTO_set_id_callback(),
|
||||
CRYPTO_get_id_callback(), and CRYPTO_thread_id() functions which assumed
|
||||
thread IDs to always be represented by 'unsigned long'.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<crypto(3)>
|
||||
|
92
include/internal/threads.h
Normal file
92
include/internal/threads.h
Normal file
@ -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
|
@ -245,6 +245,16 @@ typedef struct {
|
||||
struct CRYPTO_dynlock_value *data;
|
||||
} CRYPTO_dynlock;
|
||||
|
||||
typedef void CRYPTO_RWLOCK;
|
||||
|
||||
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void);
|
||||
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock);
|
||||
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock);
|
||||
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock);
|
||||
void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock);
|
||||
|
||||
int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock);
|
||||
|
||||
/*
|
||||
* The following can be used to detect memory leaks in the library. If
|
||||
* used, it turns on malloc checking
|
||||
|
@ -82,6 +82,7 @@ SSLSKEWITH0PTEST= sslskewith0ptest
|
||||
ASYNCTEST= asynctest
|
||||
DTLSV1LISTENTEST = dtlsv1listentest
|
||||
CTTEST= ct_test
|
||||
THREADSTEST= threadstest
|
||||
|
||||
TESTS= alltests
|
||||
|
||||
@ -103,7 +104,7 @@ EXE= $(NPTEST)$(EXE_EXT) $(MEMLEAKTEST)$(EXE_EXT) \
|
||||
$(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \
|
||||
$(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \
|
||||
$(CLIENTHELLOTEST)$(EXE_EXT) $(PACKETTEST)$(EXE_EXT) $(ASYNCTEST)$(EXE_EXT) \
|
||||
$(DTLSV1LISTENTEST)$(EXE_EXT) $(CTTEST)$(EXE_EXT)
|
||||
$(DTLSV1LISTENTEST)$(EXE_EXT) $(CTTEST)$(EXE_EXT) $(THREADSTEST)$(EXE_EXT)
|
||||
|
||||
# $(METHTEST)$(EXE_EXT)
|
||||
|
||||
@ -120,7 +121,8 @@ OBJ= $(NPTEST).o $(MEMLEAKTEST).o \
|
||||
$(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(V3NAMETEST).o \
|
||||
$(HEARTBEATTEST).o $(P5_CRPT2_TEST).o \
|
||||
$(CONSTTIMETEST).o $(VERIFYEXTRATEST).o $(CLIENTHELLOTEST).o \
|
||||
$(PACKETTEST).o $(ASYNCTEST).o $(DTLSV1LISTENTEST).o $(CTTEST).o testutil.o
|
||||
$(PACKETTEST).o $(ASYNCTEST).o $(DTLSV1LISTENTEST).o $(CTTEST).o \
|
||||
$(THREADSTEST).o testutil.o
|
||||
|
||||
SRC= $(NPTEST).c $(MEMLEAKTEST).c \
|
||||
$(BNTEST).c $(ECTEST).c \
|
||||
@ -134,7 +136,8 @@ SRC= $(NPTEST).c $(MEMLEAKTEST).c \
|
||||
$(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(V3NAMETEST).c \
|
||||
$(HEARTBEATTEST).c $(P5_CRPT2_TEST).c \
|
||||
$(CONSTTIMETEST).c $(VERIFYEXTRATEST).c $(CLIENTHELLOTEST).c \
|
||||
$(PACKETTEST).c $(ASYNCTEST).c $(DTLSV1LISTENTEST).c $(CTTEST).c testutil.c
|
||||
$(PACKETTEST).c $(ASYNCTEST).c $(DTLSV1LISTENTEST).c $(CTTEST).c \
|
||||
$(THREADSTEST).c testutil.c
|
||||
|
||||
HEADER= testutil.h
|
||||
|
||||
@ -373,6 +376,9 @@ $(DTLSV1LISTENTEST)$(EXE_EXT): $(DTLSV1LISTENTEST).o
|
||||
$(CTTEST)$(EXE_EXT): $(CTTEST).o testutil.o
|
||||
@target=$(CTTEST) testutil=testutil.o; $(BUILD_CMD)
|
||||
|
||||
$(THREADSTEST)$(EXE_EXT): $(THREADSTEST).o $(DLIBCRYPTO)
|
||||
@target=$(THREADSTEST) $(BUILD_CMD)
|
||||
|
||||
dummytest$(EXE_EXT): dummytest.o $(DLIBCRYPTO)
|
||||
@target=dummytest; $(BUILD_CMD)
|
||||
|
||||
|
@ -13,7 +13,7 @@ PROGRAMS=\
|
||||
danetest heartbeat_test p5_crpt2_test \
|
||||
constant_time_test verify_extra_test clienthellotest \
|
||||
packettest asynctest secmemtest srptest memleaktest \
|
||||
dtlsv1listentest ct_test
|
||||
dtlsv1listentest ct_test threadstest
|
||||
|
||||
SOURCE[nptest]=nptest.c
|
||||
INCLUDE[nptest]={- rel2abs(catdir($builddir,"../include")) -} ../include
|
||||
@ -206,3 +206,7 @@ DEPEND[dtlsv1listentest]=../libssl
|
||||
SOURCE[ct_test]=ct_test.c
|
||||
INCLUDE[ct_test]={- rel2abs(catdir($builddir,"../include")) -} ../include
|
||||
DEPEND[ct_test]=../libcrypto
|
||||
|
||||
SOURCE[threadstest]=threadstest.c
|
||||
INCLUDE[threadstest]={- rel2abs(catdir($builddir,"../include")) -} .. ../include
|
||||
DEPEND[threadstest]=../libcrypto
|
||||
|
5
test/recipes/90-test_threads.t
Executable file
5
test/recipes/90-test_threads.t
Executable file
@ -0,0 +1,5 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
use OpenSSL::Test::Simple;
|
||||
|
||||
simple_test("test_threads", "threadstest");
|
283
test/threadstest.c
Normal file
283
test/threadstest.c
Normal file
@ -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;
|
||||
}
|
@ -4713,3 +4713,16 @@ OPENSSL_INIT_free 5216 1_1_0 EXIST::FUNCTION:
|
||||
OPENSSL_INIT_set_config_filename 5217 1_1_0 EXIST::FUNCTION:
|
||||
SRP_user_pwd_free 5218 1_1_0 EXIST::FUNCTION:SRP
|
||||
SRP_VBASE_get1_by_user 5219 1_1_0 EXIST::FUNCTION:SRP
|
||||
CRYPTO_THREAD_lock_new 5220 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_lock_free 5221 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_read_lock 5222 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_write_lock 5223 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_unlock 5224 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_atomic_add 5225 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_init_local 5226 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_cleanup_local 5227 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_set_local 5228 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_get_local 5229 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_get_current_id 5230 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_compare_id 5231 1_1_0 EXIST::FUNCTION:
|
||||
CRYPTO_THREAD_run_once 5232 1_1_0 EXIST::FUNCTION:
|
||||
|
@ -236,6 +236,7 @@ $ssl.=" include/openssl/srtp.h";
|
||||
my $crypto ="include/openssl/crypto.h";
|
||||
$crypto.=" include/internal/o_dir.h";
|
||||
$crypto.=" include/internal/o_str.h";
|
||||
$crypto.=" include/internal/threads.h";
|
||||
$crypto.=" include/openssl/des.h" ; # unless $no_des;
|
||||
$crypto.=" include/openssl/idea.h" ; # unless $no_idea;
|
||||
$crypto.=" include/openssl/rc4.h" ; # unless $no_rc4;
|
||||
|
Loading…
Reference in New Issue
Block a user