Split unlock functions into read/write variants.

Windows SRWLOCK requires you call different functions here. Split
them up in preparation for switching Windows from CRITICAL_SECTION.

BUG=37

Change-Id: I7b5c6a98eab9ae5bb0734b805cfa1ff334918f35
Reviewed-on: https://boringssl-review.googlesource.com/8080
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/montgomery.c b/crypto/bn/montgomery.c
index f56998e..7c3b420 100644
--- a/crypto/bn/montgomery.c
+++ b/crypto/bn/montgomery.c
@@ -293,7 +293,7 @@
                            const BIGNUM *mod, BN_CTX *bn_ctx) {
   CRYPTO_MUTEX_lock_read(lock);
   BN_MONT_CTX *ctx = *pmont;
-  CRYPTO_MUTEX_unlock(lock);
+  CRYPTO_MUTEX_unlock_read(lock);
 
   if (ctx) {
     return 1;
@@ -317,7 +317,7 @@
   *pmont = ctx;
 
 out:
-  CRYPTO_MUTEX_unlock(lock);
+  CRYPTO_MUTEX_unlock_write(lock);
   return ctx != NULL;
 }
 
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 9221bf1..c4e4b13 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -325,7 +325,7 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex);
   ret = global_next_library++;
-  CRYPTO_STATIC_MUTEX_unlock(&global_next_library_mutex);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex);
 
   return ret;
 }
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 8fa1240..d67abba 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -163,7 +163,7 @@
   ret = 1;
 
 err:
-  CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&ex_data_class->lock);
   return ret;
 }
 
@@ -217,7 +217,7 @@
   if (n > 0) {
     *out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth);
   }
-  CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&ex_data_class->lock);
 
   if (n > 0 && *out == NULL) {
     OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
diff --git a/crypto/internal.h b/crypto/internal.h
index ded43fe..2d130fc 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -393,8 +393,11 @@
  * of lock on it. */
 OPENSSL_EXPORT void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock);
 
-/* CRYPTO_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock);
+/* CRYPTO_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock);
 
 /* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */
 OPENSSL_EXPORT void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock);
@@ -413,8 +416,12 @@
 OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_write(
     struct CRYPTO_STATIC_MUTEX *lock);
 
-/* CRYPTO_STATIC_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock(
+/* CRYPTO_STATIC_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_read(
+    struct CRYPTO_STATIC_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_write(
     struct CRYPTO_STATIC_MUTEX *lock);
 
 
diff --git a/crypto/obj/obj.c b/crypto/obj/obj.c
index 94f739c..16d964c 100644
--- a/crypto/obj/obj.c
+++ b/crypto/obj/obj.c
@@ -87,7 +87,7 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
   ret = global_next_nid++;
-  CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock);
 
   return ret;
 }
@@ -200,11 +200,11 @@
 
     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
   nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
   if (nid_ptr == NULL) {
@@ -243,11 +243,11 @@
     template.sn = short_name;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
   nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
   if (nid_ptr == NULL) {
@@ -277,11 +277,11 @@
     template.ln = long_name;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
   nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
   if (nid_ptr == NULL) {
@@ -330,11 +330,11 @@
     template.nid = nid;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
 err:
   OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
@@ -618,7 +618,7 @@
   if (obj->ln != NULL) {
     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock);
 
   return ok;
 }
diff --git a/crypto/rand/urandom.c b/crypto/rand/urandom.c
index a519983..434fe43 100644
--- a/crypto/rand/urandom.c
+++ b/crypto/rand/urandom.c
@@ -69,7 +69,7 @@
   CRYPTO_STATIC_MUTEX_lock_read(&requested_lock);
   urandom_buffering = urandom_buffering_requested;
   int fd = urandom_fd_requested;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock);
 
   if (fd == -2) {
     do {
@@ -106,7 +106,7 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
   urandom_fd_requested = fd;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
 
   CRYPTO_once(&once, init_once);
   if (urandom_fd != fd) {
@@ -127,7 +127,7 @@
   CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
   urandom_buffering_requested = 1;
   urandom_fd_requested = fd;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
 
   CRYPTO_once(&once, init_once);
   if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) {
diff --git a/crypto/refcount_lock.c b/crypto/refcount_lock.c
index bb8ef86..ea6a06d 100644
--- a/crypto/refcount_lock.c
+++ b/crypto/refcount_lock.c
@@ -31,7 +31,7 @@
   if (*count < CRYPTO_REFCOUNT_MAX) {
     (*count)++;
   }
-  CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
 }
 
 int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) {
@@ -45,7 +45,7 @@
     (*count)--;
   }
   ret = (*count == 0);
-  CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
 
   return ret;
 }
diff --git a/crypto/rsa/rsa_impl.c b/crypto/rsa/rsa_impl.c
index 548c535..af44a3d 100644
--- a/crypto/rsa/rsa_impl.c
+++ b/crypto/rsa/rsa_impl.c
@@ -234,7 +234,7 @@
   }
 
   if (ret != NULL) {
-    CRYPTO_MUTEX_unlock(&rsa->lock);
+    CRYPTO_MUTEX_unlock_write(&rsa->lock);
     return ret;
   }
 
@@ -243,7 +243,7 @@
   /* We didn't find a free BN_BLINDING to use so increase the length of
    * the arrays by one and use the newly created element. */
 
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
   ret = BN_BLINDING_new();
   if (ret == NULL) {
     return NULL;
@@ -281,14 +281,14 @@
   rsa->blindings_inuse = new_blindings_inuse;
   rsa->num_blindings++;
 
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
   return ret;
 
 err2:
   OPENSSL_free(new_blindings);
 
 err1:
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
   BN_BLINDING_free(ret);
   return NULL;
 }
@@ -305,7 +305,7 @@
 
   CRYPTO_MUTEX_lock_write(&rsa->lock);
   rsa->blindings_inuse[blinding_index] = 0;
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
 }
 
 /* signing */
diff --git a/crypto/thread_none.c b/crypto/thread_none.c
index cf4e85a..85768b4 100644
--- a/crypto/thread_none.c
+++ b/crypto/thread_none.c
@@ -22,7 +22,9 @@
 
 void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {}
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {}
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {}
 
 void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {}
 
@@ -30,7 +32,9 @@
 
 void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {}
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
 
 void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
   if (*once) {
diff --git a/crypto/thread_pthread.c b/crypto/thread_pthread.c
index 2a1c9f8..2baa2b4 100644
--- a/crypto/thread_pthread.c
+++ b/crypto/thread_pthread.c
@@ -45,7 +45,13 @@
   }
 }
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+  if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
+    abort();
+  }
+}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
   if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
     abort();
   }
@@ -67,7 +73,13 @@
   }
 }
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+  if (pthread_rwlock_unlock(&lock->lock) != 0) {
+    abort();
+  }
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
   if (pthread_rwlock_unlock(&lock->lock) != 0) {
     abort();
   }
diff --git a/crypto/thread_win.c b/crypto/thread_win.c
index 2632565..85e5993 100644
--- a/crypto/thread_win.c
+++ b/crypto/thread_win.c
@@ -57,7 +57,11 @@
   EnterCriticalSection((CRITICAL_SECTION *) lock);
 }
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+  LeaveCriticalSection((CRITICAL_SECTION *) lock);
+}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
   LeaveCriticalSection((CRITICAL_SECTION *) lock);
 }
 
@@ -87,7 +91,11 @@
   CRYPTO_STATIC_MUTEX_lock_read(lock);
 }
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+  LeaveCriticalSection(&lock->lock);
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
   LeaveCriticalSection(&lock->lock);
 }
 
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 4f0a49e..4445b05 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -327,7 +327,7 @@
                     hent = NULL;
                     k = 0;
                 }
-                CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+                CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock);
             } else {
                 k = 0;
                 hent = NULL;
@@ -392,7 +392,7 @@
             if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
                 tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx);
             }
-            CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);
+            CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock);
 
             /*
              * If a CRL, update the last file suffix added for this
@@ -412,14 +412,14 @@
                 if (!hent) {
                     hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
                     if (hent == NULL) {
-                        CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+                        CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
                         ok = 0;
                         goto finish;
                     }
                     hent->hash = h;
                     hent->suffix = k;
                     if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
-                        CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+                        CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
                         OPENSSL_free(hent);
                         ok = 0;
                         goto finish;
@@ -427,7 +427,7 @@
                 } else if (hent->suffix < k)
                     hent->suffix = k;
 
-                CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
+                CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
             }
 
             if (tmp != NULL) {
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index ec3f300..553756d 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -305,7 +305,7 @@
 
     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
     tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
-    CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
     if (tmp == NULL || type == X509_LU_CRL) {
         for (i = vs->current_method;
@@ -364,7 +364,7 @@
     } else
         sk_X509_OBJECT_push(ctx->objs, obj);
 
-    CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
     return ret;
 }
@@ -396,7 +396,7 @@
     } else
         sk_X509_OBJECT_push(ctx->objs, obj);
 
-    CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
     return ret;
 }
@@ -504,7 +504,7 @@
          * cache
          */
         X509_OBJECT xobj;
-        CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+        CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
         if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
             sk_X509_free(sk);
             return NULL;
@@ -513,7 +513,7 @@
         CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
         idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
         if (idx < 0) {
-            CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
             sk_X509_free(sk);
             return NULL;
         }
@@ -522,13 +522,13 @@
         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
         x = obj->data.x509;
         if (!sk_X509_push(sk, X509_up_ref(x))) {
-            CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
             X509_free(x);
             sk_X509_pop_free(sk, X509_free);
             return NULL;
         }
     }
-    CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
     return sk;
 
 }
@@ -552,7 +552,7 @@
     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
     if (idx < 0) {
-        CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+        CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
         sk_X509_CRL_free(sk);
         return NULL;
     }
@@ -562,13 +562,13 @@
         x = obj->data.crl;
         X509_CRL_up_ref(x);
         if (!sk_X509_CRL_push(sk, x)) {
-            CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
             X509_CRL_free(x);
             sk_X509_CRL_pop_free(sk, X509_CRL_free);
             return NULL;
         }
     }
-    CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
     return sk;
 }
 
@@ -656,7 +656,7 @@
             }
         }
     }
-    CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
     return ret;
 }
 
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index cd64890..934571d 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -460,14 +460,14 @@
 
     CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
     const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
-    CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock);
 
     if (!is_sorted) {
         CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
         if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
             sk_X509_REVOKED_sort(crl->crl->revoked);
         }
-        CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock);
     }
 
     if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index 1549195..23534b2 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -140,10 +140,10 @@
 
     CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
     if (key->pkey != NULL) {
-        CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+        CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
         return EVP_PKEY_up_ref(key->pkey);
     }
-    CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
 
     /* Re-encode the |X509_PUBKEY| to DER and parse it. */
     int spki_len = i2d_X509_PUBKEY(key, &spki);
@@ -161,12 +161,12 @@
     /* Check to see if another thread set key->pkey first */
     CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
     if (key->pkey) {
-        CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
         EVP_PKEY_free(ret);
         ret = key->pkey;
     } else {
         key->pkey = ret;
-        CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
     }
 
     OPENSSL_free(spki);
diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c
index f1e512e..b8a4be2 100644
--- a/crypto/x509v3/pcy_cache.c
+++ b/crypto/x509v3/pcy_cache.c
@@ -241,7 +241,7 @@
 
     CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
     cache = x->policy_cache;
-    CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock);
 
     if (cache != NULL)
         return cache;
@@ -250,7 +250,7 @@
     if (x->policy_cache == NULL)
         policy_cache_new(x);
     cache = x->policy_cache;
-    CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+    CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock);
 
     return cache;
 }
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 85bc15b..f9324d4 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -431,7 +431,7 @@
     CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
 
     if (x->ex_flags & EXFLAG_SET) {
-        CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
         return;
     }
 
@@ -564,7 +564,7 @@
     }
     x->ex_flags |= EXFLAG_SET;
 
-    CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+    CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
 }
 
 /*
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 3b8cff7..8e9b196 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1774,7 +1774,7 @@
       flush_cache = 1;
       ctx->handshakes_since_cache_flush = 0;
     }
-    CRYPTO_MUTEX_unlock(&ctx->lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->lock);
 
     if (flush_cache) {
       SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL));
diff --git a/ssl/ssl_session.c b/ssl/ssl_session.c
index 009693b..8e51a6a 100644
--- a/ssl/ssl_session.c
+++ b/ssl/ssl_session.c
@@ -396,7 +396,7 @@
       SSL_SESSION_up_ref(session);
     }
     /* TODO(davidben): This should probably move it to the front of the list. */
-    CRYPTO_MUTEX_unlock(&ssl->initial_ctx->lock);
+    CRYPTO_MUTEX_unlock_read(&ssl->initial_ctx->lock);
 
     if (session != NULL) {
       *out_session = session;
@@ -517,7 +517,7 @@
   SSL_SESSION *old_session;
   CRYPTO_MUTEX_lock_write(&ctx->lock);
   if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
-    CRYPTO_MUTEX_unlock(&ctx->lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->lock);
     SSL_SESSION_free(session);
     return 0;
   }
@@ -525,7 +525,7 @@
   if (old_session != NULL) {
     if (old_session == session) {
       /* |session| was already in the cache. */
-      CRYPTO_MUTEX_unlock(&ctx->lock);
+      CRYPTO_MUTEX_unlock_write(&ctx->lock);
       SSL_SESSION_free(old_session);
       return 0;
     }
@@ -547,7 +547,7 @@
     }
   }
 
-  CRYPTO_MUTEX_unlock(&ctx->lock);
+  CRYPTO_MUTEX_unlock_write(&ctx->lock);
   return 1;
 }
 
@@ -571,7 +571,7 @@
     }
 
     if (lock) {
-      CRYPTO_MUTEX_unlock(&ctx->lock);
+      CRYPTO_MUTEX_unlock_write(&ctx->lock);
     }
 
     if (ret) {
@@ -654,7 +654,7 @@
   tp.time = time;
   CRYPTO_MUTEX_lock_write(&ctx->lock);
   lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
-  CRYPTO_MUTEX_unlock(&ctx->lock);
+  CRYPTO_MUTEX_unlock_write(&ctx->lock);
 }
 
 int ssl_clear_bad_session(SSL *ssl) {