From a41463e31c4e3c231a84c47088e76d39191c4f36 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 12 Jul 2004 14:11:17 +0000
Subject: [PATCH] win32 doesn't support a static initializer for mutexes, thus
 the first user must initialize the lock. The problem are concurrent "first"
 users - the pthread_mutex_t initialization must be synchronized. The current
 implementation is broken, the attached patches fixes that: mutex_initlock is
 a spinlock. If the pthread_mutex_t mutex is not initialized, then the
 spinlock is acquired, if the pthread_mutex_t is initialized if it's not yet
 initialized and then the spinlock is dropped.

Manfred Spraul
---
 src/interfaces/libpq/fe-connect.c | 16 +++++++++++-----
 src/interfaces/libpq/fe-secure.c  | 16 +++++++++++-----
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index c323c45fc6f..9b60efa3e67 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.275 2004/06/19 04:22:17 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.276 2004/07/12 14:11:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3193,10 +3193,16 @@ default_threadlock(int acquire)
 #ifndef WIN32
 	static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
 #else
-	static pthread_mutex_t singlethread_lock;
-        static long mutex_initialized = 0;
-        if (!InterlockedExchange(&mutex_initialized, 1L))
-                pthread_mutex_init(&singlethread_lock, NULL);
+	static pthread_mutex_t singlethread_lock = NULL;
+	static long mutex_initlock = 0;
+
+	if (singlethread_lock == NULL) {
+		while(InterlockedExchange(&mutex_initlock, 1) == 1)
+			/* loop, another thread own the lock */ ;
+		if (singlethread_lock == NULL)
+			pthread_mutex_init(&singlethread_lock, NULL);
+		InterlockedExchange(&mutex_initlock,0);
+	}
 #endif
 	if (acquire)
 		pthread_mutex_lock(&singlethread_lock);
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index c827f940e25..ad7897ff7f4 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.42 2004/06/19 04:22:17 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.43 2004/07/12 14:11:17 momjian Exp $
  *
  * NOTES
  *	  The client *requires* a valid server certificate.  Since
@@ -867,10 +867,16 @@ init_ssl_system(PGconn *conn)
 #ifndef WIN32
         static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
 #else
-        static pthread_mutex_t init_mutex;
-        static long mutex_initialized = 0L;
-        if (!InterlockedExchange(&mutex_initialized, 1L))
-                pthread_mutex_init(&init_mutex, NULL);
+	static pthread_mutex_t init_mutex = NULL;
+	static long mutex_initlock = 0;
+
+	if (init_mutex == NULL) {
+		while(InterlockedExchange(&mutex_initlock, 1) == 1)
+			/* loop, another thread own the lock */ ;
+		if (init_mutex == NULL)
+			pthread_mutex_init(&init_mutex, NULL);
+		InterlockedExchange(&mutex_initlock,0);
+	}
 #endif
 	pthread_mutex_lock(&init_mutex);
 	
-- 
GitLab