Blame SOURCES/libgcrypt-1.5.3-ath-reinstall.patch

f9a702
diff -up libgcrypt-1.5.3/src/ath.c.ath-reinstall libgcrypt-1.5.3/src/ath.c
f9a702
--- libgcrypt-1.5.3/src/ath.c.ath-reinstall	2013-07-25 11:10:04.000000000 +0200
f9a702
+++ libgcrypt-1.5.3/src/ath.c	2017-02-28 14:37:15.267668432 +0100
f9a702
@@ -36,7 +36,7 @@
f9a702
 #include <errno.h>
f9a702
 
f9a702
 #include "ath.h"
f9a702
-
f9a702
+#include "g10lib.h"
f9a702
 
f9a702
 
f9a702
 /* The interface table.  */
f9a702
@@ -45,6 +45,13 @@ static struct ath_ops ops;
f9a702
 /* True if we should use the external callbacks.  */
f9a702
 static int ops_set;
f9a702
 
f9a702
+struct lock_list
f9a702
+{
f9a702
+  ath_mutex_t *lock;
f9a702
+  struct lock_list *next;
f9a702
+};
f9a702
+
f9a702
+static struct lock_list *reinstallable_locks;
f9a702
 
f9a702
 /* For the dummy interface.  */
f9a702
 #define MUTEX_UNLOCKED	((ath_mutex_t) 0)
f9a702
@@ -62,6 +69,50 @@ static int ops_set;
f9a702
 /* The lock we take while checking for lazy lock initialization.  */
f9a702
 static ath_mutex_t check_init_lock = ATH_MUTEX_INITIALIZER;
f9a702
 
f9a702
+static void
f9a702
+add_reinstallable_lock(ath_mutex_t *lock)
f9a702
+{
f9a702
+  struct lock_list *ll, *new, **ptr;
f9a702
+
f9a702
+  new = gcry_calloc(1, sizeof(*new));
f9a702
+  if (!new)
f9a702
+    abort();
f9a702
+
f9a702
+  for (ll = reinstallable_locks, ptr = &reinstallable_locks; ll != NULL; ptr = &ll->next, ll = ll->next)
f9a702
+    {
f9a702
+      if (ll->lock == lock)
f9a702
+        {
f9a702
+          gcry_free(new);
f9a702
+          return;
f9a702
+        }
f9a702
+    }
f9a702
+
f9a702
+  new->lock = lock;
f9a702
+  *ptr = new;
f9a702
+}
f9a702
+
f9a702
+static void
f9a702
+remove_reinstallable_lock(ath_mutex_t *lock)
f9a702
+{
f9a702
+  struct lock_list *ll, **ptr;
f9a702
+
f9a702
+  for (ll = reinstallable_locks, ptr = &reinstallable_locks; ll != NULL; ptr = &ll->next, ll = ll->next)
f9a702
+    {
f9a702
+      if (ll->lock == lock)
f9a702
+        {
f9a702
+          *ptr = ll->next;
f9a702
+          gcry_free(ll);
f9a702
+          /* we do not store duplicates */
f9a702
+          return;
f9a702
+        }
f9a702
+    }
f9a702
+
f9a702
+#ifndef NDEBUG
f9a702
+    /* lock not found, should not happen */
f9a702
+    abort();
f9a702
+#endif
f9a702
+}
f9a702
+
f9a702
 int
f9a702
 ath_init (void)
f9a702
 {
f9a702
@@ -85,7 +136,9 @@ ath_init (void)
f9a702
 gpg_err_code_t
f9a702
 ath_install (struct ath_ops *ath_ops, int check_only)
f9a702
 {
f9a702
-  if (check_only)
f9a702
+  gpg_err_code_t err = 0;
f9a702
+
f9a702
+  if (check_only && ops_set)
f9a702
     {
f9a702
       unsigned int option = 0;
f9a702
 
f9a702
@@ -119,7 +172,25 @@ ath_install (struct ath_ops *ath_ops, in
f9a702
   else
f9a702
     ops_set = 0;
f9a702
 
f9a702
-  return 0;
f9a702
+  if (ops_set && reinstallable_locks)
f9a702
+    {
f9a702
+      struct lock_list *ll;
f9a702
+
f9a702
+      ath_init();
f9a702
+      for (ll = reinstallable_locks; ll != NULL;)
f9a702
+        {
f9a702
+          struct lock_list *prev;
f9a702
+
f9a702
+          if (ath_mutex_init(ll->lock))
f9a702
+            err = GPG_ERR_NOT_SUPPORTED;
f9a702
+          prev = ll;
f9a702
+          ll = ll->next;
f9a702
+          gcry_free(prev);
f9a702
+        }
f9a702
+      reinstallable_locks = NULL;
f9a702
+    }
f9a702
+
f9a702
+  return err;
f9a702
 }
f9a702
 
f9a702
 
f9a702
@@ -143,6 +214,8 @@ ath_mutex_init (ath_mutex_t *lock)
f9a702
 {
f9a702
   if (ops_set)
f9a702
     return mutex_init (lock, 0);
f9a702
+  else
f9a702
+    add_reinstallable_lock(lock);
f9a702
 
f9a702
 #ifndef NDEBUG
f9a702
   *lock = MUTEX_UNLOCKED;
f9a702
@@ -168,6 +241,8 @@ ath_mutex_destroy (ath_mutex_t *lock)
f9a702
       (*ops.mutex_unlock) (&check_init_lock);
f9a702
       return (*ops.mutex_destroy) (lock);
f9a702
     }
f9a702
+  else
f9a702
+    remove_reinstallable_lock(lock);
f9a702
 
f9a702
 #ifndef NDEBUG
f9a702
   assert (*lock == MUTEX_UNLOCKED);