Use thread-local storage for ERR.

Change-Id: I012bff37094ecb29621197ea1d52626bb87f2f0f
diff --git a/crypto/err/err.c b/crypto/err/err.c
index a11f891..521faed 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -125,6 +125,8 @@
 #include <openssl/mem.h>
 #include <openssl/thread.h>
 
+#include "../internal.h"
+
 
 extern const uint32_t kOpenSSLFunctionValues[];
 extern const size_t kOpenSSLFunctionValuesLen;
@@ -149,83 +151,40 @@
   memset(error, 0, sizeof(struct err_error_st));
 }
 
-DEFINE_LHASH_OF(ERR_STATE);
-
-/* state_hash is a map from thread ID to ERR_STATE. It works like thread-local
- * storage. */
-static LHASH_OF(ERR_STATE) *state_hash = NULL;
-
 /* global_next_library contains the next custom library value to return. */
 static int global_next_library = ERR_NUM_LIBS;
 
-/* err_state_hash is an lhash hash function for ERR_STATE. */
-static uint32_t err_state_hash(const ERR_STATE *a) {
-  return CRYPTO_THREADID_hash(&a->tid);
-}
+static void err_state_free(void *statep) {
+  ERR_STATE *state = statep;
 
-/* err_state_cmp is an lhash compare function for ERR_STATE. */
-static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) {
-  return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
+  if (state == NULL) {
+    return;
+  }
+
+  unsigned i;
+  for (i = 0; i < ERR_NUM_ERRORS; i++) {
+    err_clear(&state->errors[i]);
+  }
+  if (state->to_free) {
+    OPENSSL_free(state->to_free);
+  }
+  OPENSSL_free(state);
 }
 
 /* err_get_state gets the ERR_STATE object for the current thread. */
 static ERR_STATE *err_get_state(void) {
-  CRYPTO_THREADID tid;
-  ERR_STATE pattern, *state, *race_state;
-  int insert_result;
-  static ERR_STATE fallback;
-
-  CRYPTO_THREADID_current(&tid);
-  memset(&pattern, 0, sizeof(pattern));
-  CRYPTO_THREADID_cpy(&pattern.tid, &tid);
-
-  CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-  if (state_hash == NULL) {
-    CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-    CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-    if (state_hash == NULL) {
-      state_hash = lh_ERR_STATE_new(err_state_hash, err_state_cmp);
-    }
-    CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-    CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-  }
-
-  if (state_hash == NULL) {
-    CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-    return NULL;
-  }
-
-  state = lh_ERR_STATE_retrieve(state_hash, &pattern);
-  CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-  if (state != NULL) {
-    return state;
-  }
-
-  state = OPENSSL_malloc(sizeof(ERR_STATE));
+  ERR_STATE *state = CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_ERR);
   if (state == NULL) {
-    CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-    /* The other error functions don't cope with a failure to get the error
-     * state, so we return a dummy value. */
-    return &fallback;
+    state = OPENSSL_malloc(sizeof(ERR_STATE));
+    if (state == NULL) {
+      return NULL;
+    }
+    memset(state, 0, sizeof(ERR_STATE));
+    if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state, err_state_free)) {
+      return NULL;
+    }
   }
 
-  memset(state, 0, sizeof(ERR_STATE));
-  CRYPTO_THREADID_cpy(&state->tid, &tid);
-
-  CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-  insert_result = lh_ERR_STATE_insert(state_hash, &race_state, state);
-  CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-
-  if (!insert_result) {
-    /* Insertion failed because of malloc failure. */
-    OPENSSL_free(state);
-    return &fallback;
-  }
-
-  /* We cannot have raced with another thread to insert an ERR_STATE because no
-   * other thread should be inserting values for this thread. */
-  assert(race_state == NULL);
-
   return state;
 }
 
@@ -358,43 +317,13 @@
   state->top = state->bottom = 0;
 }
 
-static void err_state_free(ERR_STATE *state) {
-  unsigned i;
-
-  for (i = 0; i < ERR_NUM_ERRORS; i++) {
-    err_clear(&state->errors[i]);
-  }
-  if (state->to_free) {
-    OPENSSL_free(state->to_free);
-  }
-  OPENSSL_free(state);
-}
-
 void ERR_remove_thread_state(const CRYPTO_THREADID *tid) {
-  CRYPTO_THREADID current;
-
-  if (tid == NULL) {
-    CRYPTO_THREADID_current(&current);
-    tid = &current;
-  }
-
-  ERR_STATE pattern;
-  CRYPTO_THREADID_cpy(&pattern.tid, tid);
-
-  CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-  if (state_hash == NULL) {
-    CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+  if (tid != NULL) {
+    assert(0);
     return;
   }
 
-  ERR_STATE *state = lh_ERR_STATE_delete(state_hash, &pattern);
-  CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
-
-  if (state == NULL) {
-    return;
-  }
-
-  err_state_free(state);
+  ERR_clear_error();
 }
 
 int ERR_get_next_error_library(void) {
@@ -848,14 +777,6 @@
 
 void ERR_load_crypto_strings(void) {}
 
-void ERR_free_strings(void) {
-  CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-  if (state_hash) {
-    lh_ERR_STATE_doall(state_hash, err_state_free);
-    lh_ERR_STATE_free(state_hash);
-    state_hash = NULL;
-  }
-  CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
-}
+void ERR_free_strings(void) {}
 
 void ERR_load_BIO_strings(void) {}
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 20165cd..340cf9b 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -145,10 +145,7 @@
 /* ERR_load_crypto_strings does nothing. */
 OPENSSL_EXPORT void ERR_load_crypto_strings(void);
 
-/* ERR_free_strings frees any memory retained by the error system, expect for
- * per-thread structures which are assumed to have already been freed with
- * |ERR_remove_thread_state|. This should only be called at process
- * shutdown. */
+/* ERR_free_strings does nothing. */
 OPENSSL_EXPORT void ERR_free_strings(void);
 
 
@@ -259,8 +256,12 @@
 /* ERR_clear_error clears the error queue for the current thread. */
 OPENSSL_EXPORT void ERR_clear_error(void);
 
-/* ERR_remove_thread_state deletes the error queue for the given thread. If
- * |tid| is NULL then the error queue for the current thread is deleted. */
+/* ERR_remove_thread_state clears the error queue for the current thread if
+ * |tid| is NULL. Otherwise it does nothing because it's no longer possible to
+ * delete the error queue for other threads.
+ *
+ * Error queues are thread-local data and are deleted automatically. You do not
+ * need to call this function. See |ERR_clear_error|. */
 OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
 
 
@@ -354,9 +355,6 @@
 
 /* ERR_STATE contains the per-thread, error queue. */
 typedef struct err_state_st {
-  /* tid is the identifier of the thread that owns this queue. */
-  CRYPTO_THREADID tid;
-
   /* errors contains the ERR_NUM_ERRORS most recent errors, organised as a ring
    * buffer. */
   struct err_error_st errors[ERR_NUM_ERRORS];
diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h
index 96c4966..02e51ca 100644
--- a/include/openssl/lhash.h
+++ b/include/openssl/lhash.h
@@ -96,7 +96,6 @@
  *
  * LHASH_OF:ASN1_OBJECT
  * LHASH_OF:CONF_VALUE
- * LHASH_OF:ERR_STATE
  * LHASH_OF:EX_CLASS_ITEM
  * LHASH_OF:SSL_SESSION */
 
diff --git a/include/openssl/lhash_macros.h b/include/openssl/lhash_macros.h
index 9f20e4b..018856a 100644
--- a/include/openssl/lhash_macros.h
+++ b/include/openssl/lhash_macros.h
@@ -92,42 +92,6 @@
                             void (*)(CONF_VALUE *, void *), func), \
                arg);
 
-/* ERR_STATE */
-#define lh_ERR_STATE_new(hash, comp)                                        \
-  ((LHASH_OF(ERR_STATE) *)lh_new(                                           \
-      CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ERR_STATE *), hash), \
-      CHECKED_CAST(lhash_cmp_func,                                          \
-                   int (*)(const ERR_STATE *a, const ERR_STATE *b), comp)))
-
-#define lh_ERR_STATE_free(lh) \
-  lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh));
-
-#define lh_ERR_STATE_num_items(lh) \
-  lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh))
-
-#define lh_ERR_STATE_retrieve(lh, data)                                        \
-  ((ERR_STATE *)lh_retrieve(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
-                            CHECKED_CAST(void *, ERR_STATE *, data)))
-
-#define lh_ERR_STATE_insert(lh, old_data, data)                \
-  lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
-            CHECKED_CAST(void **, ERR_STATE **, old_data),     \
-            CHECKED_CAST(void *, ERR_STATE *, data))
-
-#define lh_ERR_STATE_delete(lh, data)                                        \
-  ((ERR_STATE *)lh_delete(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
-                          CHECKED_CAST(void *, ERR_STATE *, data)))
-
-#define lh_ERR_STATE_doall(lh, func)                          \
-  lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
-           CHECKED_CAST(void (*)(void *), void (*)(ERR_STATE *), func));
-
-#define lh_ERR_STATE_doall_arg(lh, func, arg)                     \
-  lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(ERR_STATE) *, lh), \
-               CHECKED_CAST(void (*)(void *, void *),             \
-                            void (*)(ERR_STATE *, void *), func), \
-               arg);
-
 /* EX_CLASS_ITEM */
 #define lh_EX_CLASS_ITEM_new(hash, comp)                                    \
   ((LHASH_OF(EX_CLASS_ITEM) *)lh_new(                                       \