diff options
author | Alessandro Ghedini <alessandro@ghedini.me> | 2016-03-02 17:36:17 +0000 |
---|---|---|
committer | Alessandro Ghedini <alessandro@cloudflare.com> | 2016-03-08 14:11:09 +0000 |
commit | 8509dcc9f319190c565ab6baad7c88d37a951d1c (patch) | |
tree | d4b44b7ed13c84a55d73ff0254e370d753587c53 /crypto/err | |
parent | f75200115d1a778c39c8a8850823928d8be1f8ac (diff) |
Convert ERR_STATE to new multi-threading API
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'crypto/err')
-rw-r--r-- | crypto/err/err.c | 198 | ||||
-rw-r--r-- | crypto/err/err_lcl.h | 2 |
2 files changed, 32 insertions, 168 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c index 181882d04e..36ba9c74ef 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -112,13 +112,13 @@ #include <stdarg.h> #include <string.h> #include <internal/cryptlib_int.h> +#include <internal/threads.h> #include <openssl/lhash.h> #include <openssl/crypto.h> #include <openssl/buffer.h> #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/opensslconf.h> -#include "err_lcl.h" static void err_load_strings(int lib, ERR_STRING_DATA *str); @@ -231,25 +231,18 @@ static ERR_STRING_DATA ERR_str_reasons[] = { }; #endif +static CRYPTO_ONCE err_init = CRYPTO_ONCE_STATIC_INIT; +static CRYPTO_THREAD_LOCAL err_thread_local; + /* Predeclarations of the "err_defaults" functions */ static LHASH_OF(ERR_STRING_DATA) *get_hash(int create, int lockit); static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); -static LHASH_OF(ERR_STATE) *int_thread_get(int create, int lockit); -static void int_thread_release(LHASH_OF(ERR_STATE) **hash); -static ERR_STATE *int_thread_get_item(const ERR_STATE *); -static ERR_STATE *int_thread_set_item(ERR_STATE *); -static void int_thread_del_item(const ERR_STATE *); /* * The internal state */ -/* This is a struct so that REF_PRINT_COUNT works. */ -static struct refcount { - int references; -} refcount = { 0 }; static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; -static LHASH_OF(ERR_STATE) *int_thread_hash = NULL; static int int_err_library_number = ERR_LIB_USER; static unsigned long get_error_values(int inc, int top, const char **file, @@ -303,106 +296,6 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) return p; } -static unsigned long err_state_hash(const ERR_STATE *a) -{ - return CRYPTO_THREADID_hash(&a->tid) * 13; -} - -static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) -{ - return CRYPTO_THREADID_cmp(&a->tid, &b->tid); -} - -static LHASH_OF(ERR_STATE) *int_thread_get(int create, int lockit) -{ - LHASH_OF(ERR_STATE) *ret = NULL; - - if (lockit) - CRYPTO_w_lock(CRYPTO_LOCK_ERR); - if (!int_thread_hash && create) { - int_thread_hash = lh_ERR_STATE_new(err_state_hash, err_state_cmp); - } - if (int_thread_hash != NULL) { - refcount.references++; - ret = int_thread_hash; - } - if (lockit) - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - return ret; -} - -static void int_thread_release(LHASH_OF(ERR_STATE) **hash) -{ - int i; - - if (hash == NULL || *hash == NULL) - return; - - i = CRYPTO_add(&refcount.references, -1, CRYPTO_LOCK_ERR); - - REF_PRINT_COUNT(&refcount, "ERR"); - if (i > 0) - return; - REF_ASSERT_ISNT(i < 0); - *hash = NULL; -} - -static ERR_STATE *int_thread_get_item(const ERR_STATE *d) -{ - ERR_STATE *p = NULL; - LHASH_OF(ERR_STATE) *hash; - - CRYPTO_r_lock(CRYPTO_LOCK_ERR); - hash = int_thread_get(0, 0); - if (hash) - p = lh_ERR_STATE_retrieve(hash, d); - CRYPTO_r_unlock(CRYPTO_LOCK_ERR); - - int_thread_release(&hash); - return p; -} - -static ERR_STATE *int_thread_set_item(ERR_STATE *d) -{ - ERR_STATE *p = NULL; - LHASH_OF(ERR_STATE) *hash; - - CRYPTO_w_lock(CRYPTO_LOCK_ERR); - hash = int_thread_get(1, 0); - if (hash) - p = lh_ERR_STATE_insert(hash, d); - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - - int_thread_release(&hash); - return p; -} - -static void int_thread_del_item(const ERR_STATE *d) -{ - ERR_STATE *p = NULL; - LHASH_OF(ERR_STATE) *hash; - - CRYPTO_w_lock(CRYPTO_LOCK_ERR); - hash = int_thread_get(0, 0); - if (hash) { - p = lh_ERR_STATE_delete(hash, d); - /* If there are no other references, and we just removed the - * last item, delete the int_thread_hash */ - if (refcount.references == 1 - && int_thread_hash - && lh_ERR_STATE_num_items(int_thread_hash) == 0) { - refcount.references = 0; - lh_ERR_STATE_free(int_thread_hash); - int_thread_hash = NULL; - hash = NULL; - } - } - CRYPTO_w_unlock(CRYPTO_LOCK_ERR); - - int_thread_release(&hash); - ERR_STATE_free(p); -} - #ifndef OPENSSL_NO_ERR # define NUM_SYS_STR_REASONS 127 # define LEN_SYS_STR_REASON 32 @@ -768,7 +661,6 @@ void ERR_error_string_n(unsigned long e, char *buf, size_t len) } } -/* BAD for multi-threading: uses a local buffer if ret == NULL */ /* * ERR_error_string_n should be used instead for ret != NULL as * ERR_error_string cannot know how large the buffer is @@ -789,16 +681,6 @@ LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void) return get_hash(0, 1); } -LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void) -{ - return int_thread_get(0, 1); -} - -void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash) -{ - int_thread_release(hash); -} - const char *ERR_lib_error_string(unsigned long e) { ERR_STRING_DATA d, *p; @@ -838,68 +720,52 @@ const char *ERR_reason_error_string(unsigned long e) return ((p == NULL) ? NULL : p->string); } -void ERR_remove_thread_state(const CRYPTO_THREADID *id) +void ERR_remove_thread_state(void) { - ERR_STATE tmp; + ERR_STATE *state = ERR_get_state(); + if (state == NULL) + return; - if (id) - CRYPTO_THREADID_cpy(&tmp.tid, id); - else - CRYPTO_THREADID_current(&tmp.tid); - /* - * thread_del_item automatically destroys the LHASH if the number of - * items reaches zero. - */ - int_thread_del_item(&tmp); + CRYPTO_THREAD_set_local(&err_thread_local, NULL); + ERR_STATE_free(state); } #if OPENSSL_API_COMPAT < 0x10000000L void ERR_remove_state(unsigned long pid) { - ERR_remove_thread_state(NULL); + ERR_remove_thread_state(); } #endif +static void err_do_init(void) +{ + CRYPTO_THREAD_init_local(&err_thread_local, NULL); +} + ERR_STATE *ERR_get_state(void) { - static ERR_STATE fallback; - ERR_STATE *ret, tmp, *tmpp = NULL; - int i; - CRYPTO_THREADID tid; - - CRYPTO_THREADID_current(&tid); - CRYPTO_THREADID_cpy(&tmp.tid, &tid); - ret = int_thread_get_item(&tmp); - - /* ret == the error state, if NULL, make a new one */ - if (ret == NULL) { - ret = OPENSSL_malloc(sizeof(*ret)); - if (ret == NULL) - return (&fallback); - CRYPTO_THREADID_cpy(&ret->tid, &tid); - ret->top = 0; - ret->bottom = 0; - for (i = 0; i < ERR_NUM_ERRORS; i++) { - ret->err_data[i] = NULL; - ret->err_data_flags[i] = 0; - } - tmpp = int_thread_set_item(ret); - /* To check if insertion failed, do a get. */ - if (int_thread_get_item(ret) != ret) { - ERR_STATE_free(ret); /* could not insert it */ - return (&fallback); + ERR_STATE *state = NULL; + + CRYPTO_THREAD_run_once(&err_init, err_do_init); + + state = CRYPTO_THREAD_get_local(&err_thread_local); + + if (state == NULL) { + state = OPENSSL_zalloc(sizeof(*state)); + if (state == NULL) + return NULL; + + if (!CRYPTO_THREAD_set_local(&err_thread_local, state)) { + ERR_STATE_free(state); + return NULL; } - /* - * If a race occurred in this function and we came second, tmpp is - * the first one that we just replaced. - */ - ERR_STATE_free(tmpp); /* Ignore failures from these */ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE); } - return ret; + + return state; } int ERR_get_next_error_library(void) diff --git a/crypto/err/err_lcl.h b/crypto/err/err_lcl.h deleted file mode 100644 index c9d24f111e..0000000000 --- a/crypto/err/err_lcl.h +++ /dev/null @@ -1,2 +0,0 @@ - -DEFINE_LHASH_OF(ERR_STATE); |