diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 96028e23ca..106529a29f 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -2252,5 +2252,9 @@ Tue, 02 Oct 2007 11:32:25 +0200 - ITAGAKI Takahiro added thread-safe descriptor handling + +Wed, 03 Oct 2007 10:48:39 +0200 + + - Hopefully fixed some stuff that causes Windows builds to fail. - Set ecpg library version to 6.0. - Set ecpg version to 4.4. diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index f7ebbc8c0c..235aa936c6 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.45 2007/10/02 09:49:59 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.46 2007/10/03 08:55:22 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -11,17 +11,15 @@ #include "sqlca.h" #ifdef ENABLE_THREAD_SAFETY -NON_EXEC_STATIC pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t actual_connection_key; -#ifndef WIN32 static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT; #endif -#endif static struct connection *actual_connection = NULL; static struct connection *all_connections = NULL; #ifdef ENABLE_THREAD_SAFETY -NON_EXEC_STATIC void +static void ecpg_actual_connection_init(void) { pthread_key_create(&actual_connection_key, NULL); @@ -447,7 +445,6 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p this->cache_head = NULL; this->prep_stmts = NULL; - this->descriptors = NULL; if (all_connections == NULL) this->next = NULL; diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c index d278a74434..ce02ad3e87 100644 --- a/src/interfaces/ecpg/ecpglib/descriptor.c +++ b/src/interfaces/ecpg/ecpglib/descriptor.c @@ -1,6 +1,6 @@ /* dynamic SQL support routines * - * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.24 2007/10/02 09:49:59 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.25 2007/10/03 08:55:22 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL @@ -21,9 +21,7 @@ static void descriptor_deallocate_all(struct descriptor *list); /* We manage descriptors separately for each thread. */ #ifdef ENABLE_THREAD_SAFETY static pthread_key_t descriptor_key; -#ifndef WIN32 static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT; -#endif static void descriptor_destructor(void *arg) @@ -31,7 +29,7 @@ descriptor_destructor(void *arg) descriptor_deallocate_all(arg); } -NON_EXEC_STATIC void +static void descriptor_key_init(void) { pthread_key_create(&descriptor_key, descriptor_destructor); diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h index 0df6506b0b..f88782c131 100644 --- a/src/interfaces/ecpg/ecpglib/extern.h +++ b/src/interfaces/ecpg/ecpglib/extern.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.29 2007/10/02 09:49:59 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.30 2007/10/03 08:55:22 meskes Exp $ */ #ifndef _ECPG_LIB_EXTERN_H #define _ECPG_LIB_EXTERN_H @@ -36,8 +36,6 @@ bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type, #ifdef ENABLE_THREAD_SAFETY void ecpg_pthreads_init(void); -#else -#define ecpg_pthreads_init() ((void)0) #endif struct connection *ECPGget_connection(const char *); char *ECPGalloc(long, int); @@ -94,7 +92,6 @@ struct connection int autocommit; struct ECPGtype_information_cache *cache_head; struct prepared_statement *prep_stmts; - struct descriptor *descriptors; struct connection *next; }; diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c index 0b3eb47d4e..ed1dfece37 100644 --- a/src/interfaces/ecpg/ecpglib/memory.c +++ b/src/interfaces/ecpg/ecpglib/memory.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.9 2007/09/30 11:38:48 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.10 2007/10/03 08:55:22 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -70,9 +70,7 @@ struct auto_mem #ifdef ENABLE_THREAD_SAFETY static pthread_key_t auto_mem_key; -#ifndef WIN32 static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT; -#endif static void auto_mem_destructor(void *arg) @@ -80,7 +78,7 @@ auto_mem_destructor(void *arg) ECPGfree_auto_mem(); } -NON_EXEC_STATIC void +static void auto_mem_key_init(void) { pthread_key_create(&auto_mem_key, auto_mem_destructor); diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index 51bda5a7de..136290625d 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.38 2007/10/02 09:49:59 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.39 2007/10/03 08:55:22 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -57,9 +57,7 @@ static struct sqlca_t sqlca_init = #ifdef ENABLE_THREAD_SAFETY static pthread_key_t sqlca_key; -#ifndef WIN32 static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT; -#endif #else static struct sqlca_t sqlca = { @@ -90,8 +88,8 @@ static struct sqlca_t sqlca = #endif #ifdef ENABLE_THREAD_SAFETY -NON_EXEC_STATIC pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; -NON_EXEC_STATIC pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER; #endif static int simple_debug = 0; static FILE *debugstream = NULL; @@ -125,7 +123,7 @@ ecpg_sqlca_key_destructor(void *arg) free(arg); /* sqlca structure allocated in ECPGget_sqlca */ } -NON_EXEC_STATIC void +static void ecpg_sqlca_key_init(void) { pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor); @@ -415,24 +413,37 @@ ECPGis_noind_null(enum ECPGttype type, void *ptr) } #ifdef WIN32 +#ifdef ENABLE_THREAD_SAFETY -/* - * Initialize mutexes and call init-once functions on loading. - */ - -BOOL WINAPI -DllMain(HANDLE module, DWORD reason, LPVOID reserved) +void +win32_pthread_mutex(volatile pthread_mutex_t *mutex) { - if (reason == DLL_PROCESS_ATTACH) + if (mutex->handle == NULL) { - connections_mutex = CreateMutex(NULL, FALSE, NULL); - debug_mutex = CreateMutex(NULL, FALSE, NULL); - debug_init_mutex = CreateMutex(NULL, FALSE, NULL); - auto_mem_key_init(); - ecpg_actual_connection_init(); - ecpg_sqlca_key_init(); - descriptor_key_init(); + while (InterlockedExchange((LONG *)&mutex->initlock, 1) == 1) + Sleep(0); + if (mutex->handle == NULL) + mutex->handle = CreateMutex(NULL, FALSE, NULL); + InterlockedExchange((LONG *)&mutex->initlock, 0); } - return TRUE; } -#endif + +static pthread_mutex_t win32_pthread_once_lock = PTHREAD_MUTEX_INITIALIZER; + +void +win32_pthread_once(volatile pthread_once_t *once, void (*fn)(void)) +{ + if (!*once) + { + pthread_mutex_lock(&win32_pthread_once_lock); + if (!*once) + { + *once = true; + fn(); + } + pthread_mutex_unlock(&win32_pthread_once_lock); + } +} + +#endif /* ENABLE_THREAD_SAFETY */ +#endif /* WIN32 */ diff --git a/src/interfaces/ecpg/include/ecpg-pthread-win32.h b/src/interfaces/ecpg/include/ecpg-pthread-win32.h index 369cefb754..991a33dcf1 100644 --- a/src/interfaces/ecpg/include/ecpg-pthread-win32.h +++ b/src/interfaces/ecpg/include/ecpg-pthread-win32.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.3 2007/10/02 09:49:59 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.4 2007/10/03 08:55:23 meskes Exp $ */ /* * pthread mapping macros for win32 native thread implementation */ @@ -10,22 +10,33 @@ #ifndef WIN32 #include -#define NON_EXEC_STATIC static #else -#define NON_EXEC_STATIC +typedef struct pthread_mutex_t +{ + HANDLE handle; + LONG initlock; +} pthread_mutex_t; -typedef HANDLE pthread_mutex_t; typedef DWORD pthread_key_t; +typedef bool pthread_once_t; -#define PTHREAD_MUTEX_INITIALIZER INVALID_HANDLE_VALUE +#define PTHREAD_MUTEX_INITIALIZER { NULL, 0 } +#define PTHREAD_ONCE_INIT false + +void win32_pthread_mutex(volatile pthread_mutex_t *mutex); +void win32_pthread_once(volatile pthread_once_t *once, void (*fn)(void)); #define pthread_mutex_lock(mutex) \ - WaitForSingleObject(*(mutex), INFINITE); + do { \ + if ((mutex)->handle == NULL) \ + win32_pthread_mutex((mutex)); \ + WaitForSingleObject((mutex)->handle, INFINITE); \ + } while(0) #define pthread_mutex_unlock(mutex) \ - ReleaseMutex(*(mutex)) + ReleaseMutex((mutex)->handle) #define pthread_getspecific(key) \ TlsGetValue((key)) @@ -37,18 +48,11 @@ typedef DWORD pthread_key_t; #define pthread_key_create(key, destructor) \ do { *(key) = TlsAlloc(); ((void)(destructor)); } while(0) -/* init-once functions are always called when libecpg is loaded */ -#define pthread_once(key, fn) \ - ((void)0) - -extern pthread_mutex_t connections_mutex; -extern pthread_mutex_t debug_mutex; -extern pthread_mutex_t debug_init_mutex; -extern void auto_mem_key_init(void); -extern void ecpg_actual_connection_init(void); -extern void ecpg_sqlca_key_init(void); -extern void descriptor_key_init(void); -extern BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved); +#define pthread_once(once, fn) \ + do { \ + if (!*(once)) \ + win32_pthread_once((once), (fn)); \ + } while(0) #endif /* WIN32 */ diff --git a/src/interfaces/ecpg/test/expected/thread-descriptor.c b/src/interfaces/ecpg/test/expected/thread-descriptor.c index e1e1341cbb..4bbed8c256 100644 --- a/src/interfaces/ecpg/test/expected/thread-descriptor.c +++ b/src/interfaces/ecpg/test/expected/thread-descriptor.c @@ -100,7 +100,7 @@ struct sqlca_t *ECPGget_sqlca(void); #line 17 "descriptor.pgc" -#ifdef WIN32 +#if defined(ENABLE_THREAD_SAFETY) && defined(WIN32) static unsigned STDCALL fn(void* arg) #else static void* fn(void* arg) diff --git a/src/interfaces/ecpg/test/thread/descriptor.pgc b/src/interfaces/ecpg/test/thread/descriptor.pgc index ff5d80e13d..7f7b4a1d0b 100644 --- a/src/interfaces/ecpg/test/thread/descriptor.pgc +++ b/src/interfaces/ecpg/test/thread/descriptor.pgc @@ -16,7 +16,7 @@ EXEC SQL include sqlca; EXEC SQL whenever sqlerror sqlprint; EXEC SQL whenever not found sqlprint; -#ifdef WIN32 +#if defined(ENABLE_THREAD_SAFETY) && defined(WIN32) static unsigned STDCALL fn(void* arg) #else static void* fn(void* arg)