Convert CRYPTO_LOCK_BIO to new multi-threading API
authorAlessandro Ghedini <alessandro@ghedini.me>
Fri, 26 Feb 2016 11:51:31 +0000 (11:51 +0000)
committerRich Salz <rsalz@openssl.org>
Tue, 8 Mar 2016 16:10:34 +0000 (11:10 -0500)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
crypto/bio/bio_lib.c
doc/crypto/BIO_new.pod
include/openssl/bio.h
include/openssl/crypto.h
ssl/bio_ssl.c

index ee8d622b2071a639e89ee4a97041f9c8f911d603..522525b1296b243749c2343a63c3028fd39f58b1 100644 (file)
@@ -94,12 +94,22 @@ int BIO_set(BIO *bio, BIO_METHOD *method)
     bio->num_read = 0L;
     bio->num_write = 0L;
     CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
-    if (method->create != NULL)
+
+    bio->lock = CRYPTO_THREAD_lock_new();
+    if (bio->lock == NULL) {
+        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
+        return 0;
+    }
+
+    if (method->create != NULL) {
         if (!method->create(bio)) {
             CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
-            return (0);
+            CRYPTO_THREAD_lock_free(bio->lock);
+            return 0;
         }
-    return (1);
+    }
+
+    return 1;
 }
 
 int BIO_free(BIO *a)
@@ -107,23 +117,29 @@ int BIO_free(BIO *a)
     int i;
 
     if (a == NULL)
-        return (0);
+        return 0;
+
+    if (CRYPTO_atomic_add(&a->references, -1, &i, a->lock) <= 0)
+        return 0;
 
-    i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
     REF_PRINT_COUNT("BIO", a);
     if (i > 0)
-        return (1);
+        return 1;
     REF_ASSERT_ISNT(i < 0);
     if ((a->callback != NULL) &&
         ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
-        return (i);
+        return i;
 
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
 
+    CRYPTO_THREAD_lock_free(a->lock);
+
     if ((a->method != NULL) && (a->method->destroy != NULL))
         a->method->destroy(a);
+
     OPENSSL_free(a);
-    return (1);
+
+    return 1;
 }
 
 void BIO_vfree(BIO *a)
@@ -131,6 +147,18 @@ void BIO_vfree(BIO *a)
     BIO_free(a);
 }
 
+int BIO_up_ref(BIO *a)
+{
+    int i;
+
+    if (CRYPTO_atomic_add(&a->references, 1, &i, a->lock) <= 0)
+        return 0;
+
+    REF_PRINT_COUNT("BIO", a);
+    REF_ASSERT_ISNT(i < 2);
+    return ((i > 1) ? 1 : 0);
+}
+
 void BIO_clear_flags(BIO *b, int flags)
 {
     b->flags &= ~flags;
index 76679f3da4fd30d6c37adfd8ea45f859e0883ed5..d6d87c3901ff8d59f13ef6465dcc32d4f8d19176 100644 (file)
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-BIO_new, BIO_set, BIO_free, BIO_vfree, BIO_free_all - BIO allocation and freeing functions
+BIO_new, BIO_set, BIO_up_ref, BIO_free, BIO_vfree, BIO_free_all - BIO allocation and freeing functions
 
 =head1 SYNOPSIS
 
@@ -10,6 +10,7 @@ BIO_new, BIO_set, BIO_free, BIO_vfree, BIO_free_all - BIO allocation and freeing
 
  BIO * BIO_new(BIO_METHOD *type);
  int   BIO_set(BIO *a,BIO_METHOD *type);
+ int   BIO_up_ref(BIO *a);
  int   BIO_free(BIO *a);
  void  BIO_vfree(BIO *a);
  void  BIO_free_all(BIO *a);
@@ -20,6 +21,8 @@ The BIO_new() function returns a new BIO using method B<type>.
 
 BIO_set() sets the method of an already existing BIO.
 
+BIO_up_ref() increments the reference count associated with the BIO object.
+
 BIO_free() frees up a single BIO, BIO_vfree() also frees up a single BIO
 but it does not return a value.
 If B<a> is NULL nothing is done.
@@ -36,7 +39,7 @@ If B<a> is NULL nothing is done.
 
 BIO_new() returns a newly created BIO or NULL if the call fails.
 
-BIO_set(), BIO_free() return 1 for success and 0 for failure.
+BIO_set(), BIO_up_ref() and BIO_free() return 1 for success and 0 for failure.
 
 BIO_free_all() and BIO_vfree() do not return values.
 
index a1b4ced571c7de47cbee8646d84d56a0a3285795..ae59948389365b2447e2f5cc9901ad9ba1802989 100644 (file)
@@ -326,6 +326,7 @@ struct bio_st {
     uint64_t num_read;
     uint64_t num_write;
     CRYPTO_EX_DATA ex_data;
+    CRYPTO_RWLOCK *lock;
 };
 
 DEFINE_STACK_OF(BIO)
@@ -635,6 +636,7 @@ BIO *BIO_new(BIO_METHOD *type);
 int BIO_set(BIO *a, BIO_METHOD *type);
 int BIO_free(BIO *a);
 void BIO_vfree(BIO *a);
+int BIO_up_ref(BIO *a);
 int BIO_read(BIO *b, void *data, int len);
 int BIO_gets(BIO *bp, char *buf, int size);
 int BIO_write(BIO *b, const void *data, int len);
index 53c26b9a7ff8c2bfb9429da23898309eb386d4bf..a36d7175e163a0088f6571ba9a6d066cdc9f2c8e 100644 (file)
@@ -181,7 +181,6 @@ extern "C" {
 # define CRYPTO_LOCK_RAND                18
 # define CRYPTO_LOCK_RAND2               19
 # define CRYPTO_LOCK_MALLOC              20
-# define CRYPTO_LOCK_BIO                 21
 # define CRYPTO_LOCK_READDIR             24
 # define CRYPTO_LOCK_RSA_BLINDING        25
 # define CRYPTO_LOCK_MALLOC2             27
index 9eec0226af6b8d63154e0d5cdf5589da0e7fe1dd..c433cf507369a5b053c274f315e46fd05bf456d8 100644 (file)
@@ -338,7 +338,7 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
             if (b->next_bio != NULL)
                 BIO_push(bio, b->next_bio);
             b->next_bio = bio;
-            CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
+            BIO_up_ref(bio);
         }
         b->init = 1;
         break;
@@ -371,7 +371,7 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
     case BIO_CTRL_PUSH:
         if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) {
             SSL_set_bio(ssl, b->next_bio, b->next_bio);
-            CRYPTO_add(&b->next_bio->references, 1, CRYPTO_LOCK_BIO);
+            BIO_up_ref(b);
         }
         break;
     case BIO_CTRL_POP:
@@ -384,7 +384,7 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr)
             if (ssl->rbio != ssl->wbio)
                 BIO_free_all(ssl->wbio);
             if (b->next_bio != NULL)
-                CRYPTO_add(&b->next_bio->references, -1, CRYPTO_LOCK_BIO);
+                BIO_free(b->next_bio);
             ssl->wbio = NULL;
             ssl->rbio = NULL;
         }