Thread: [PATCH] fix libpq mutex initialization for multithreaded win32 libs

[PATCH] fix libpq mutex initialization for multithreaded win32 libs

From
Manfred Spraul
Date:
Hi,

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.

Again untested due to lack of Visual C++.

--
    Manfre
? GNUmakefile
? config.log
? config.status
? src/Makefile.global
? src/include/pg_config.h
? src/include/stamp-h
? src/port/pg_config_paths.h
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.275
diff -c -r1.275 fe-connect.c
*** src/interfaces/libpq/fe-connect.c    19 Jun 2004 04:22:17 -0000    1.275
--- src/interfaces/libpq/fe-connect.c    20 Jun 2004 16:38:38 -0000
***************
*** 3193,3202 ****
  #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);
  #endif
      if (acquire)
          pthread_mutex_lock(&singlethread_lock);
--- 3193,3208 ----
  #ifndef WIN32
      static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
  #else
!     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);
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.42
diff -c -r1.42 fe-secure.c
*** src/interfaces/libpq/fe-secure.c    19 Jun 2004 04:22:17 -0000    1.42
--- src/interfaces/libpq/fe-secure.c    20 Jun 2004 16:38:39 -0000
***************
*** 867,876 ****
  #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);
  #endif
      pthread_mutex_lock(&init_mutex);

--- 867,882 ----
  #ifndef WIN32
          static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
  #else
!     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);


Re: [PATCH] fix libpq mutex initialization for multithreaded

From
Bruce Momjian
Date:
Patch applied.  Thanks.

---------------------------------------------------------------------------


Manfred Spraul wrote:
> Hi,
>
> 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.
>
> Again untested due to lack of Visual C++.
>
> --
>     Manfre

> ? GNUmakefile
> ? config.log
> ? config.status
> ? src/Makefile.global
> ? src/include/pg_config.h
> ? src/include/stamp-h
> ? src/port/pg_config_paths.h
> Index: src/interfaces/libpq/fe-connect.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
> retrieving revision 1.275
> diff -c -r1.275 fe-connect.c
> *** src/interfaces/libpq/fe-connect.c    19 Jun 2004 04:22:17 -0000    1.275
> --- src/interfaces/libpq/fe-connect.c    20 Jun 2004 16:38:38 -0000
> ***************
> *** 3193,3202 ****
>   #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);
>   #endif
>       if (acquire)
>           pthread_mutex_lock(&singlethread_lock);
> --- 3193,3208 ----
>   #ifndef WIN32
>       static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
>   #else
> !     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);
> Index: src/interfaces/libpq/fe-secure.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
> retrieving revision 1.42
> diff -c -r1.42 fe-secure.c
> *** src/interfaces/libpq/fe-secure.c    19 Jun 2004 04:22:17 -0000    1.42
> --- src/interfaces/libpq/fe-secure.c    20 Jun 2004 16:38:39 -0000
> ***************
> *** 867,876 ****
>   #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);
>   #endif
>       pthread_mutex_lock(&init_mutex);
>
> --- 867,882 ----
>   #ifndef WIN32
>           static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
>   #else
> !     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);
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 8: explain analyze is your friend

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073