v1-0005-ecpg-Use-pg_threads.h.patch
text/x-patch
Filename: v1-0005-ecpg-Use-pg_threads.h.patch
Type: text/x-patch
Part: 4
Message:
pg_threads.h take II
Patch
Format: format-patch
Series: patch v1-0005
Subject: ecpg: Use pg_threads.h.
| File | + | − |
|---|---|---|
| src/interfaces/ecpg/ecpglib/connect.c | 18 | 37 |
| src/interfaces/ecpg/ecpglib/descriptor.c | 13 | 33 |
| src/interfaces/ecpg/ecpglib/ecpglib_extern.h | 2 | 1 |
| src/interfaces/ecpg/ecpglib/execute.c | 0 | 2 |
| src/interfaces/ecpg/ecpglib/memory.c | 17 | 59 |
| src/interfaces/ecpg/ecpglib/misc.c | 63 | 85 |
| src/interfaces/ecpg/ecpglib/sqlda.c | 1 | 1 |
| src/interfaces/ecpg/include/ecpglib.h | 0 | 2 |
| src/interfaces/ecpg/include/ecpg-pthread-win32.h | 0 | 49 |
| src/interfaces/ecpg/test/expected/thread-alloc.c | 22 | 51 |
| src/interfaces/ecpg/test/expected/thread-descriptor.c | 12 | 40 |
| src/interfaces/ecpg/test/expected/thread-prep.c | 36 | 63 |
| src/interfaces/ecpg/test/expected/thread-thread.c | 35 | 57 |
| src/interfaces/ecpg/test/expected/thread-thread_implicit.c | 35 | 57 |
| src/interfaces/ecpg/test/thread/alloc.pgc | 5 | 34 |
| src/interfaces/ecpg/test/thread/descriptor.pgc | 5 | 33 |
| src/interfaces/ecpg/test/thread/prep.pgc | 5 | 32 |
| src/interfaces/ecpg/test/thread/thread_implicit.pgc | 8 | 30 |
| src/interfaces/ecpg/test/thread/thread.pgc | 8 | 30 |
From 9b5dafb641c841c94e42af1dfab24be40ab52ed9 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Wed, 24 Jun 2026 17:19:25 +1200
Subject: [PATCH v1 05/14] ecpg: Use pg_threads.h.
* adopt pg_threads.h for threads, mutexes
* use plain thread_local for thread-local objects
* use pg_thrd_atexit for cleanup
* remove local threading abstraction
The underlying mechanism for pg_thrd_atexit is the same as before (it
uses a single thread-specific destructor), but now works on Windows too,
fixing the known leak of auto-allocated memory, descriptors and SQL
state objects on that OS.
Discussion:
Reviewed-by:
---
src/interfaces/ecpg/ecpglib/connect.c | 55 +++----
src/interfaces/ecpg/ecpglib/descriptor.c | 46 ++----
src/interfaces/ecpg/ecpglib/ecpglib_extern.h | 3 +-
src/interfaces/ecpg/ecpglib/execute.c | 2 -
src/interfaces/ecpg/ecpglib/memory.c | 76 ++-------
src/interfaces/ecpg/ecpglib/misc.c | 148 ++++++++----------
src/interfaces/ecpg/ecpglib/sqlda.c | 2 +-
.../ecpg/include/ecpg-pthread-win32.h | 49 ------
src/interfaces/ecpg/include/ecpglib.h | 2 -
.../ecpg/test/expected/thread-alloc.c | 73 +++------
.../ecpg/test/expected/thread-descriptor.c | 52 ++----
.../ecpg/test/expected/thread-prep.c | 99 +++++-------
.../ecpg/test/expected/thread-thread.c | 92 +++++------
.../test/expected/thread-thread_implicit.c | 92 +++++------
src/interfaces/ecpg/test/thread/alloc.pgc | 39 +----
.../ecpg/test/thread/descriptor.pgc | 38 +----
src/interfaces/ecpg/test/thread/prep.pgc | 37 +----
src/interfaces/ecpg/test/thread/thread.pgc | 38 +----
.../ecpg/test/thread/thread_implicit.pgc | 38 +----
19 files changed, 285 insertions(+), 696 deletions(-)
delete mode 100644 src/interfaces/ecpg/include/ecpg-pthread-win32.h
diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
index 36b97fcdba0..01af16c8625 100644
--- a/src/interfaces/ecpg/ecpglib/connect.c
+++ b/src/interfaces/ecpg/ecpglib/connect.c
@@ -3,35 +3,22 @@
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
-#include "ecpg-pthread-win32.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
#include "ecpgtype.h"
+#include "port/pg_threads.h"
#include "sqlca.h"
#ifdef HAVE_USELOCALE
locale_t ecpg_clocale = (locale_t) 0;
#endif
-static pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_key_t actual_connection_key;
-static pthread_once_t actual_connection_key_once = PTHREAD_ONCE_INIT;
+static pg_mtx_t connections_mutex = PG_MTX_INIT;
+static thread_local struct connection *actual_connection_thread_local;
static struct connection *actual_connection_global = NULL;
static struct connection *all_connections = NULL;
-static void
-ecpg_actual_connection_init(void)
-{
- pthread_key_create(&actual_connection_key, NULL);
-}
-
-void
-ecpg_pthreads_init(void)
-{
- pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
-}
-
static struct connection *
ecpg_get_connection_nr(const char *connection_name)
{
@@ -39,9 +26,7 @@ ecpg_get_connection_nr(const char *connection_name)
if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
{
- ecpg_pthreads_init(); /* ensure actual_connection_key is valid */
-
- ret = pthread_getspecific(actual_connection_key);
+ ret = actual_connection_thread_local;
/*
* if no connection in TSD for this thread, get the global default
@@ -79,9 +64,7 @@ ecpg_get_connection(const char *connection_name)
if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
{
- ecpg_pthreads_init(); /* ensure actual_connection_key is valid */
-
- ret = pthread_getspecific(actual_connection_key);
+ ret = actual_connection_thread_local;
/*
* if no connection in TSD for this thread, get the global default
@@ -94,11 +77,11 @@ ecpg_get_connection(const char *connection_name)
}
else
{
- pthread_mutex_lock(&connections_mutex);
+ pg_mtx_lock(&connections_mutex);
ret = ecpg_get_connection_nr(connection_name);
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
}
return ret;
@@ -132,8 +115,8 @@ ecpg_finish(struct connection *act)
con->next = act->next;
}
- if (pthread_getspecific(actual_connection_key) == act)
- pthread_setspecific(actual_connection_key, all_connections);
+ if (actual_connection_thread_local == act)
+ actual_connection_thread_local = all_connections;
if (actual_connection_global == act)
actual_connection_global = all_connections;
@@ -199,7 +182,7 @@ ECPGsetconn(int lineno, const char *connection_name)
if (!ecpg_init(con, connection_name, lineno))
return false;
- pthread_setspecific(actual_connection_key, con);
+ actual_connection_thread_local = con;
return true;
}
@@ -311,8 +294,6 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
if (dbname == NULL && connection_name == NULL)
connection_name = "DEFAULT";
- ecpg_pthreads_init();
-
/* check if the identifier is unique */
if (ecpg_get_connection(connection_name))
{
@@ -501,7 +482,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
}
/* add connection to our list */
- pthread_mutex_lock(&connections_mutex);
+ pg_mtx_lock(&connections_mutex);
/*
* ... but first, make certain we have created ecpg_clocale. Rely on
@@ -513,7 +494,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
ecpg_clocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
if (!ecpg_clocale)
{
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
if (host)
@@ -547,7 +528,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
this->next = all_connections;
all_connections = this;
- pthread_setspecific(actual_connection_key, all_connections);
+ actual_connection_thread_local = all_connections;
actual_connection_global = all_connections;
ecpg_log("ECPGconnect: opening database %s on %s port %s %s%s %s%s\n",
@@ -668,7 +649,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
ecpg_log("ECPGconnect: %s", errmsg);
ecpg_finish(this);
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
ecpg_raise(lineno, ECPG_CONNECT, ECPG_SQLSTATE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION, db);
if (realname)
@@ -680,7 +661,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
if (realname)
ecpg_free(realname);
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
this->autocommit = autocommit;
@@ -702,7 +683,7 @@ ECPGdisconnect(int lineno, const char *connection_name)
return false;
}
- pthread_mutex_lock(&connections_mutex);
+ pg_mtx_lock(&connections_mutex);
if (strcmp(connection_name, "ALL") == 0)
{
@@ -721,14 +702,14 @@ ECPGdisconnect(int lineno, const char *connection_name)
if (!ecpg_init(con, connection_name, lineno))
{
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
return false;
}
else
ecpg_finish(con);
}
- pthread_mutex_unlock(&connections_mutex);
+ pg_mtx_unlock(&connections_mutex);
return true;
}
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 4e816879617..2caa6e9b4e1 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -8,11 +8,11 @@
#include "postgres_fe.h"
#include "catalog/pg_type_d.h"
-#include "ecpg-pthread-win32.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
#include "ecpgtype.h"
+#include "port/pg_threads.h"
#include "sql3types.h"
#include "sqlca.h"
#include "sqlda.h"
@@ -20,36 +20,10 @@
static void descriptor_free(struct descriptor *desc);
/* We manage descriptors separately for each thread. */
-static pthread_key_t descriptor_key;
-static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT;
+static thread_local struct descriptor *descriptors_thread_local;
static void descriptor_deallocate_all(struct descriptor *list);
-static void
-descriptor_destructor(void *arg)
-{
- descriptor_deallocate_all(arg);
-}
-
-static void
-descriptor_key_init(void)
-{
- pthread_key_create(&descriptor_key, descriptor_destructor);
-}
-
-static struct descriptor *
-get_descriptors(void)
-{
- pthread_once(&descriptor_once, descriptor_key_init);
- return (struct descriptor *) pthread_getspecific(descriptor_key);
-}
-
-static void
-set_descriptors(struct descriptor *value)
-{
- pthread_setspecific(descriptor_key, value);
-}
-
/* old internal convenience function that might go away later */
static PGresult *
ecpg_result_by_descriptor(int line, const char *name)
@@ -776,14 +750,14 @@ ECPGdeallocate_desc(int line, const char *name)
}
ecpg_init_sqlca(sqlca);
- for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
+ for (desc = descriptors_thread_local, prev = NULL; desc; prev = desc, desc = desc->next)
{
if (strcmp(name, desc->name) == 0)
{
if (prev)
prev->next = desc->next;
else
- set_descriptors(desc->next);
+ descriptors_thread_local = desc->next;
descriptor_free(desc);
return true;
}
@@ -822,7 +796,7 @@ ECPGallocate_desc(int line, const char *name)
new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
if (!new)
return false;
- new->next = get_descriptors();
+ new->next = descriptors_thread_local;
new->name = ecpg_alloc(strlen(name) + 1, line);
if (!new->name)
{
@@ -840,7 +814,7 @@ ECPGallocate_desc(int line, const char *name)
return false;
}
strcpy(new->name, name);
- set_descriptors(new);
+ descriptors_thread_local = new;
return true;
}
@@ -850,7 +824,7 @@ ecpg_find_desc(int line, const char *name)
{
struct descriptor *desc;
- for (desc = get_descriptors(); desc; desc = desc->next)
+ for (desc = descriptors_thread_local; desc; desc = desc->next)
{
if (strcmp(name, desc->name) == 0)
return desc;
@@ -1006,3 +980,9 @@ ECPGdescribe(int line, int compat, bool input, const char *connection_name, cons
return ret;
}
+
+void
+ecpg_descriptor_on_thread_exit(void)
+{
+ descriptor_deallocate_all(descriptors_thread_local);
+}
diff --git a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
index 0b8cea6196d..487a771015f 100644
--- a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
+++ b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h
@@ -166,7 +166,6 @@ bool ecpg_get_data(const PGresult *, int, int, int, enum ECPGttype type,
enum ECPGttype, char *, char *, long, long, long,
enum ARRAY_TYPE, enum COMPAT_MODE, bool);
-void ecpg_pthreads_init(void);
struct connection *ecpg_get_connection(const char *connection_name);
char *ecpg_alloc(long size, int lineno);
char *ecpg_auto_alloc(long size, int lineno);
@@ -233,6 +232,8 @@ unsigned ecpg_hex_dec_len(unsigned srclen);
unsigned ecpg_hex_enc_len(unsigned srclen);
unsigned ecpg_hex_encode(const char *src, unsigned len, char *dst);
+void ecpg_descriptor_on_thread_exit(void);
+
#ifdef ENABLE_NLS
extern char *ecpg_gettext(const char *msgid) pg_attribute_format_arg(1);
#else
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 02380dafd9d..2085b62ec4b 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1963,8 +1963,6 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
return false;
}
- ecpg_pthreads_init();
-
con = ecpg_get_connection(connection_name);
if (!ecpg_init(con, connection_name, lineno))
diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c
index 236029c73e2..1277d2e2d11 100644
--- a/src/interfaces/ecpg/ecpglib/memory.c
+++ b/src/interfaces/ecpg/ecpglib/memory.c
@@ -3,11 +3,11 @@
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
-#include "ecpg-pthread-win32.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
#include "ecpgtype.h"
+#include "port/pg_threads.h"
void
ecpg_free(void *ptr)
@@ -77,35 +77,7 @@ struct auto_mem
struct auto_mem *next;
};
-static pthread_key_t auto_mem_key;
-static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT;
-
-static void ecpg_clear_auto_mem_list(struct auto_mem *list);
-
-static void
-auto_mem_destructor(void *arg)
-{
- ecpg_clear_auto_mem_list((struct auto_mem *) arg);
-}
-
-static void
-auto_mem_key_init(void)
-{
- pthread_key_create(&auto_mem_key, auto_mem_destructor);
-}
-
-static struct auto_mem *
-get_auto_allocs(void)
-{
- pthread_once(&auto_mem_once, auto_mem_key_init);
- return (struct auto_mem *) pthread_getspecific(auto_mem_key);
-}
-
-static void
-set_auto_allocs(struct auto_mem *am)
-{
- pthread_setspecific(auto_mem_key, am);
-}
+static thread_local struct auto_mem *auto_mem_thread_local;
char *
ecpg_auto_alloc(long size, int lineno)
@@ -132,50 +104,36 @@ ecpg_add_mem(void *ptr, int lineno)
return false;
am->pointer = ptr;
- am->next = get_auto_allocs();
- set_auto_allocs(am);
+ am->next = auto_mem_thread_local;
+ auto_mem_thread_local = am;
return true;
}
void
ECPGfree_auto_mem(void)
{
- struct auto_mem *am = get_auto_allocs();
-
/* free all memory we have allocated for the user */
- if (am)
+ while (auto_mem_thread_local)
{
- do
- {
- struct auto_mem *act = am;
-
- am = am->next;
- ecpg_free(act->pointer);
- ecpg_free(act);
- } while (am);
- set_auto_allocs(NULL);
+ struct auto_mem *act = auto_mem_thread_local;
+ struct auto_mem *next = act->next;
+
+ ecpg_free(act->pointer);
+ ecpg_free(act);
+ auto_mem_thread_local = next;
}
}
void
ecpg_clear_auto_mem(void)
-{
- ecpg_clear_auto_mem_list(get_auto_allocs());
-}
-
-static void
-ecpg_clear_auto_mem_list(struct auto_mem *am)
{
/* only free our own structure */
- if (am)
+ while (auto_mem_thread_local)
{
- do
- {
- struct auto_mem *act = am;
-
- am = am->next;
- ecpg_free(act);
- } while (am);
- set_auto_allocs(NULL);
+ struct auto_mem *act = auto_mem_thread_local;
+ struct auto_mem *next = act->next;
+
+ ecpg_free(act);
+ auto_mem_thread_local = next;
}
}
diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c
index 354a2e731fc..dbe1c919822 100644
--- a/src/interfaces/ecpg/ecpglib/misc.c
+++ b/src/interfaces/ecpg/ecpglib/misc.c
@@ -6,7 +6,6 @@
#include <limits.h>
#include <unistd.h>
-#include "ecpg-pthread-win32.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
@@ -16,6 +15,7 @@
#include "pgtypes_interval.h"
#include "pgtypes_numeric.h"
#include "pgtypes_timestamp.h"
+#include "port/pg_threads.h"
#include "sqlca.h"
#ifndef LONG_LONG_MIN
@@ -55,11 +55,13 @@ static struct sqlca_t sqlca_init =
}
};
-static pthread_key_t sqlca_key;
-static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
+static thread_local struct sqlca_t *sqlca_thread_local;
-static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pg_thrd_atexit_t ecpg_on_thread_exit_id;
+static bool ecpg_on_thread_exit_initialized;
+
+static pg_mtx_t debug_mutex = PG_MTX_INIT;
+static pg_mtx_t debug_init_mutex = PG_MTX_INIT;
static volatile int simple_debug = 0;
static FILE *debugstream = NULL;
@@ -93,34 +95,64 @@ ecpg_init(const struct connection *con, const char *connection_name, const int l
}
static void
-ecpg_sqlca_key_destructor(void *arg)
+ecpg_on_thread_exit(void)
{
- free(arg); /* sqlca structure allocated in ECPGget_sqlca */
+ /* Clean up thread-local data in memory.c. */
+ ecpg_clear_auto_mem();
+
+ /* Clean up thread-local data in descriptor.h. */
+ ecpg_descriptor_on_thread_exit();
+
+ /* Clean up thread-local SQL state object. */
+ if (sqlca_thread_local)
+ free(sqlca_thread_local);
}
-static void
-ecpg_sqlca_key_init(void)
+static bool
+ecpg_on_thread_exit_initialize(void)
{
- pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor);
+ bool result = false;
+ static pg_mtx_t mutex = PG_MTX_INIT;
+
+ /*
+ * This is only reached when sqlca_thread_local is not already set, ie
+ * once per thread (unless it failed last time and we're trying again), so
+ * keep things simple with a big lock.
+ */
+ pg_mtx_lock(&mutex);
+ if (ecpg_on_thread_exit_initialized)
+ {
+ result = true;
+ }
+ else if (pg_thrd_atexit_create(&ecpg_on_thread_exit_id) == pg_thrd_success)
+ {
+ result = true;
+ ecpg_on_thread_exit_initialized = true;
+ }
+ pg_mtx_unlock(&mutex);
+
+ /* Make sure the cleanup function is enabled in this thread. */
+ if (result)
+ pg_thrd_atexit_enable(ecpg_on_thread_exit_id, ecpg_on_thread_exit);
+
+ return result;
}
struct sqlca_t *
ECPGget_sqlca(void)
{
- struct sqlca_t *sqlca;
+ if (sqlca_thread_local)
+ return sqlca_thread_local;
- pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
+ if (!ecpg_on_thread_exit_initialize())
+ return NULL;
- sqlca = pthread_getspecific(sqlca_key);
- if (sqlca == NULL)
- {
- sqlca = malloc(sizeof(struct sqlca_t));
- if (sqlca == NULL)
- return NULL;
- ecpg_init_sqlca(sqlca);
- pthread_setspecific(sqlca_key, sqlca);
- }
- return sqlca;
+ sqlca_thread_local = malloc(sizeof(struct sqlca_t));
+ if (sqlca_thread_local == NULL)
+ return NULL;
+ ecpg_init_sqlca(sqlca_thread_local);
+
+ return sqlca_thread_local;
}
bool
@@ -204,10 +236,10 @@ void
ECPGdebug(int n, FILE *dbgs)
{
/* Interlock against concurrent executions of ECPGdebug() */
- pthread_mutex_lock(&debug_init_mutex);
+ pg_mtx_lock(&debug_init_mutex);
/* Prevent ecpg_log() from printing while we change settings */
- pthread_mutex_lock(&debug_mutex);
+ pg_mtx_lock(&debug_mutex);
if (n > 100)
{
@@ -220,12 +252,12 @@ ECPGdebug(int n, FILE *dbgs)
debugstream = dbgs;
/* We must release debug_mutex before invoking ecpg_log() ... */
- pthread_mutex_unlock(&debug_mutex);
+ pg_mtx_unlock(&debug_mutex);
/* ... but keep holding debug_init_mutex to avoid racy printout */
ecpg_log("ECPGdebug: set to %d\n", simple_debug);
- pthread_mutex_unlock(&debug_init_mutex);
+ pg_mtx_unlock(&debug_init_mutex);
}
void
@@ -264,7 +296,7 @@ ecpg_log(const char *format, ...)
sqlca = ECPGget_sqlca();
- pthread_mutex_lock(&debug_mutex);
+ pg_mtx_lock(&debug_mutex);
/* Now that we hold the mutex, recheck simple_debug */
if (simple_debug)
@@ -283,7 +315,7 @@ ecpg_log(const char *format, ...)
fflush(debugstream);
}
- pthread_mutex_unlock(&debug_mutex);
+ pg_mtx_unlock(&debug_mutex);
free(fmt);
}
@@ -424,60 +456,6 @@ ECPGis_noind_null(enum ECPGttype type, const void *ptr)
return false;
}
-#ifdef WIN32
-
-int
-pthread_mutex_init(pthread_mutex_t *mp, void *attr)
-{
- mp->initstate = 0;
- return 0;
-}
-
-int
-pthread_mutex_lock(pthread_mutex_t *mp)
-{
- /* Initialize the csection if not already done */
- if (mp->initstate != 1)
- {
- LONG istate;
-
- while ((istate = InterlockedExchange(&mp->initstate, 2)) == 2)
- Sleep(0); /* wait, another thread is doing this */
- if (istate != 1)
- InitializeCriticalSection(&mp->csection);
- InterlockedExchange(&mp->initstate, 1);
- }
- EnterCriticalSection(&mp->csection);
- return 0;
-}
-
-int
-pthread_mutex_unlock(pthread_mutex_t *mp)
-{
- if (mp->initstate != 1)
- return EINVAL;
- LeaveCriticalSection(&mp->csection);
- return 0;
-}
-
-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)
- {
- fn();
- *once = true;
- }
- pthread_mutex_unlock(&win32_pthread_once_lock);
- }
-}
-#endif /* WIN32 */
-
#ifdef ENABLE_NLS
char *
@@ -491,7 +469,7 @@ ecpg_gettext(const char *msgid)
* might as well do it the same way everywhere.
*/
static volatile bool already_bound = false;
- static pthread_mutex_t binddomain_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pg_mtx_t binddomain_mutex = PG_MTX_INIT;
if (!already_bound)
{
@@ -502,7 +480,7 @@ ecpg_gettext(const char *msgid)
int save_errno = errno;
#endif
- (void) pthread_mutex_lock(&binddomain_mutex);
+ pg_mtx_lock(&binddomain_mutex);
if (!already_bound)
{
@@ -519,7 +497,7 @@ ecpg_gettext(const char *msgid)
already_bound = true;
}
- (void) pthread_mutex_unlock(&binddomain_mutex);
+ pg_mtx_unlock(&binddomain_mutex);
#ifdef WIN32
SetLastError(save_errno);
diff --git a/src/interfaces/ecpg/ecpglib/sqlda.c b/src/interfaces/ecpg/ecpglib/sqlda.c
index 081e32666f6..97914299111 100644
--- a/src/interfaces/ecpg/ecpglib/sqlda.c
+++ b/src/interfaces/ecpg/ecpglib/sqlda.c
@@ -11,11 +11,11 @@
#include "catalog/pg_type_d.h"
#include "decimal.h"
-#include "ecpg-pthread-win32.h"
#include "ecpgerrno.h"
#include "ecpglib.h"
#include "ecpglib_extern.h"
#include "ecpgtype.h"
+#include "port/pg_threads.h"
#include "sqlca.h"
#include "sqlda-compat.h"
#include "sqlda-native.h"
diff --git a/src/interfaces/ecpg/include/ecpg-pthread-win32.h b/src/interfaces/ecpg/include/ecpg-pthread-win32.h
deleted file mode 100644
index 7b6ba46b349..00000000000
--- a/src/interfaces/ecpg/include/ecpg-pthread-win32.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* src/interfaces/ecpg/include/ecpg-pthread-win32.h */
-/*
- * pthread mapping macros for win32 native thread implementation
- */
-#ifndef _ECPG_PTHREAD_WIN32_H
-#define _ECPG_PTHREAD_WIN32_H
-
-#ifndef WIN32
-
-#include <pthread.h>
-#else
-
-typedef struct pthread_mutex_t
-{
- /* initstate = 0: not initialized; 1: init done; 2: init in progress */
- LONG initstate;
- CRITICAL_SECTION csection;
-} pthread_mutex_t;
-
-typedef DWORD pthread_key_t;
-typedef bool pthread_once_t;
-
-#define PTHREAD_MUTEX_INITIALIZER { 0 }
-#define PTHREAD_ONCE_INIT false
-
-int pthread_mutex_init(pthread_mutex_t *, void *attr);
-int pthread_mutex_lock(pthread_mutex_t *);
-int pthread_mutex_unlock(pthread_mutex_t *);
-
-void win32_pthread_once(volatile pthread_once_t *once, void (*fn) (void));
-
-#define pthread_getspecific(key) \
- TlsGetValue((key))
-
-#define pthread_setspecific(key, value) \
- TlsSetValue((key), (value))
-
-/* FIXME: destructor is never called in Win32. */
-#define pthread_key_create(key, destructor) \
- do { *(key) = TlsAlloc(); ((void)(destructor)); } while(0)
-
-#define pthread_once(once, fn) \
- do { \
- if (!*(once)) \
- win32_pthread_once((once), (fn)); \
- } while(0)
-#endif /* WIN32 */
-
-#endif /* _ECPG_PTHREAD_WIN32_H */
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 1d971d5893d..ea87d343d9d 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -70,8 +70,6 @@ void *ECPGget_var(int number);
/* dynamic result allocation */
void ECPGfree_auto_mem(void);
-void ecpg_pthreads_init(void);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/interfaces/ecpg/test/expected/thread-alloc.c b/src/interfaces/ecpg/test/expected/thread-alloc.c
index 912d94c134c..5225967db44 100644
--- a/src/interfaces/ecpg/test/expected/thread-alloc.c
+++ b/src/interfaces/ecpg/test/expected/thread-alloc.c
@@ -10,16 +10,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
-#include <stdio.h>
+#include "port/pg_threads.h"
#define THREADS 16
#define REPEATS 50
@@ -93,7 +84,7 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
-#line 18 "alloc.pgc"
+#line 9 "alloc.pgc"
#line 1 "regression.h"
@@ -103,21 +94,17 @@ struct sqlca_t *ECPGget_sqlca(void);
-#line 19 "alloc.pgc"
+#line 10 "alloc.pgc"
/* exec sql whenever sqlerror sqlprint ; */
-#line 21 "alloc.pgc"
+#line 12 "alloc.pgc"
/* exec sql whenever not found sqlprint ; */
-#line 22 "alloc.pgc"
+#line 13 "alloc.pgc"
-#ifdef WIN32
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
@@ -126,54 +113,54 @@ static void* fn(void* arg)
-#line 33 "alloc.pgc"
+#line 20 "alloc.pgc"
int value ;
-#line 34 "alloc.pgc"
+#line 21 "alloc.pgc"
char name [ 100 ] ;
-#line 35 "alloc.pgc"
+#line 22 "alloc.pgc"
char ** r = NULL ;
/* exec sql end declare section */
-#line 36 "alloc.pgc"
+#line 23 "alloc.pgc"
value = (intptr_t) arg;
sprintf(name, "Connection: %d", value);
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , name, 0);
-#line 41 "alloc.pgc"
+#line 28 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 41 "alloc.pgc"
+#line 28 "alloc.pgc"
{ ECPGsetcommit(__LINE__, "on", NULL);
-#line 42 "alloc.pgc"
+#line 29 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 42 "alloc.pgc"
+#line 29 "alloc.pgc"
for (i = 1; i <= REPEATS; ++i)
{
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select relname from pg_class where relname = 'pg_class'", ECPGt_EOIT,
ECPGt_char,&(r),(long)0,(long)0,(1)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
-#line 45 "alloc.pgc"
+#line 32 "alloc.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) sqlprint();
-#line 45 "alloc.pgc"
+#line 32 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 45 "alloc.pgc"
+#line 32 "alloc.pgc"
free(r);
r = NULL;
}
{ ECPGdisconnect(__LINE__, name);
-#line 49 "alloc.pgc"
+#line 36 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 49 "alloc.pgc"
+#line 36 "alloc.pgc"
return 0;
@@ -182,28 +169,12 @@ if (sqlca.sqlcode < 0) sqlprint();}
int main(void)
{
intptr_t i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
-
-#ifdef WIN32
- for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
- }
+ pg_thrd_t threads[THREADS];
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
+ pg_thrd_create(&threads[i], fn, (void *) i);
for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, (void *) i);
- for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/thread-descriptor.c b/src/interfaces/ecpg/test/expected/thread-descriptor.c
index f9322b3e9bb..37630d39b8a 100644
--- a/src/interfaces/ecpg/test/expected/thread-descriptor.c
+++ b/src/interfaces/ecpg/test/expected/thread-descriptor.c
@@ -7,15 +7,7 @@
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
#line 1 "descriptor.pgc"
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
-#include <stdio.h>
+#include "port/pg_threads.h"
#define THREADS 16
#define REPEATS 50000
@@ -89,36 +81,32 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
-#line 14 "descriptor.pgc"
+#line 6 "descriptor.pgc"
/* exec sql whenever sqlerror sqlprint ; */
-#line 15 "descriptor.pgc"
+#line 7 "descriptor.pgc"
/* exec sql whenever not found sqlprint ; */
-#line 16 "descriptor.pgc"
+#line 8 "descriptor.pgc"
-#if defined(WIN32)
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
for (i = 1; i <= REPEATS; ++i)
{
ECPGallocate_desc(__LINE__, "mydesc");
-#line 28 "descriptor.pgc"
+#line 16 "descriptor.pgc"
if (sqlca.sqlcode < 0) sqlprint();
-#line 28 "descriptor.pgc"
+#line 16 "descriptor.pgc"
ECPGdeallocate_desc(__LINE__, "mydesc");
-#line 29 "descriptor.pgc"
+#line 17 "descriptor.pgc"
if (sqlca.sqlcode < 0) sqlprint();
-#line 29 "descriptor.pgc"
+#line 17 "descriptor.pgc"
}
@@ -128,28 +116,12 @@ if (sqlca.sqlcode < 0) sqlprint();
int main(void)
{
int i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
-
-#ifdef WIN32
- for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, NULL, 0, &id);
- }
+ pg_thrd_t threads[THREADS];
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
- for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, NULL);
+ pg_thrd_create(&threads[i], fn, NULL);
for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/thread-prep.c b/src/interfaces/ecpg/test/expected/thread-prep.c
index 4fb19e3fd1c..96e30e9e680 100644
--- a/src/interfaces/ecpg/test/expected/thread-prep.c
+++ b/src/interfaces/ecpg/test/expected/thread-prep.c
@@ -10,15 +10,8 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
+#include "port/pg_threads.h"
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
#include <stdio.h>
#define THREADS 16
@@ -93,7 +86,7 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
-#line 18 "prep.pgc"
+#line 11 "prep.pgc"
#line 1 "regression.h"
@@ -103,21 +96,17 @@ struct sqlca_t *ECPGget_sqlca(void);
-#line 19 "prep.pgc"
+#line 12 "prep.pgc"
/* exec sql whenever sqlerror sqlprint ; */
-#line 21 "prep.pgc"
+#line 14 "prep.pgc"
/* exec sql whenever not found sqlprint ; */
-#line 22 "prep.pgc"
+#line 15 "prep.pgc"
-#ifdef WIN32
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
@@ -126,64 +115,64 @@ static void* fn(void* arg)
-#line 33 "prep.pgc"
+#line 22 "prep.pgc"
int value ;
-#line 34 "prep.pgc"
+#line 23 "prep.pgc"
char name [ 100 ] ;
-#line 35 "prep.pgc"
+#line 24 "prep.pgc"
char query [ 256 ] = "INSERT INTO T VALUES ( ? )" ;
/* exec sql end declare section */
-#line 36 "prep.pgc"
+#line 25 "prep.pgc"
value = (intptr_t) arg;
sprintf(name, "Connection: %d", value);
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , name, 0);
-#line 41 "prep.pgc"
+#line 30 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 41 "prep.pgc"
+#line 30 "prep.pgc"
{ ECPGsetcommit(__LINE__, "on", NULL);
-#line 42 "prep.pgc"
+#line 31 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 42 "prep.pgc"
+#line 31 "prep.pgc"
for (i = 1; i <= REPEATS; ++i)
{
{ ECPGprepare(__LINE__, NULL, 0, "i", query);
-#line 45 "prep.pgc"
+#line 34 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 45 "prep.pgc"
+#line 34 "prep.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, "i",
ECPGt_int,&(value),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
-#line 46 "prep.pgc"
+#line 35 "prep.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) sqlprint();
-#line 46 "prep.pgc"
+#line 35 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 46 "prep.pgc"
+#line 35 "prep.pgc"
}
{ ECPGdeallocate(__LINE__, 0, NULL, "i");
-#line 48 "prep.pgc"
+#line 37 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 48 "prep.pgc"
+#line 37 "prep.pgc"
{ ECPGdisconnect(__LINE__, name);
-#line 49 "prep.pgc"
+#line 38 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 49 "prep.pgc"
+#line 38 "prep.pgc"
return 0;
@@ -192,59 +181,43 @@ if (sqlca.sqlcode < 0) sqlprint();}
int main(void)
{
intptr_t i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
+ pg_thrd_t threads[THREADS];
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0);
-#line 63 "prep.pgc"
+#line 48 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 63 "prep.pgc"
+#line 48 "prep.pgc"
{ ECPGsetcommit(__LINE__, "on", NULL);
-#line 64 "prep.pgc"
+#line 49 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 64 "prep.pgc"
+#line 49 "prep.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table if exists T", ECPGt_EOIT, ECPGt_EORT);
-#line 65 "prep.pgc"
+#line 50 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 65 "prep.pgc"
+#line 50 "prep.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table T ( i int )", ECPGt_EOIT, ECPGt_EORT);
-#line 66 "prep.pgc"
+#line 51 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 66 "prep.pgc"
+#line 51 "prep.pgc"
{ ECPGdisconnect(__LINE__, "CURRENT");
-#line 67 "prep.pgc"
+#line 52 "prep.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 67 "prep.pgc"
+#line 52 "prep.pgc"
-#ifdef WIN32
for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
- }
-
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
+ pg_thrd_create(&threads[i], fn, (void *) i);
for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
- for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, (void *) i);
- for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/thread-thread.c b/src/interfaces/ecpg/test/expected/thread-thread.c
index 71da6f2e07d..5a981b23ba7 100644
--- a/src/interfaces/ecpg/test/expected/thread-thread.c
+++ b/src/interfaces/ecpg/test/expected/thread-thread.c
@@ -14,13 +14,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#include <locale.h>
-#endif
+#include "port/pg_threads.h"
#line 1 "regression.h"
@@ -30,29 +24,25 @@
-#line 16 "thread.pgc"
+#line 10 "thread.pgc"
-void *test_thread(void *arg);
+int test_thread(void *arg);
int nthreads = 10;
int iterations = 20;
int main(void)
{
-#ifndef WIN32
- pthread_t *threads;
-#else
- HANDLE *threads;
-#endif
+ pg_thrd_t *threads;
intptr_t n;
/* exec sql begin declare section */
-#line 32 "thread.pgc"
+#line 22 "thread.pgc"
int l_rows ;
/* exec sql end declare section */
-#line 33 "thread.pgc"
+#line 23 "thread.pgc"
/* Do not switch on debug output for regression tests. The threads get executed in
@@ -61,22 +51,22 @@ int main(void)
/* setup test_thread table */
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
-#line 40 "thread.pgc"
+#line 30 "thread.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table test_thread", ECPGt_EOIT, ECPGt_EORT);}
-#line 41 "thread.pgc"
+#line 31 "thread.pgc"
/* DROP might fail */
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 42 "thread.pgc"
+#line 32 "thread.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test_thread ( tstamp timestamp not null default cast ( timeofday ( ) as timestamp ) , thread text not null , iteration integer not null , primary key ( thread , iteration ) )", ECPGt_EOIT, ECPGt_EORT);}
-#line 47 "thread.pgc"
+#line 37 "thread.pgc"
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 48 "thread.pgc"
+#line 38 "thread.pgc"
{ ECPGdisconnect(__LINE__, "CURRENT");}
-#line 49 "thread.pgc"
+#line 39 "thread.pgc"
/* create, and start, threads */
@@ -87,39 +77,27 @@ int main(void)
return 1;
}
for( n = 0; n < nthreads; n++ )
- {
-#ifndef WIN32
- pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
-#else
- threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n + 1), 0, NULL);
-#endif
- }
+ pg_thrd_create(&threads[n], test_thread, (void *) (n + 1));
/* wait for thread completion */
-#ifndef WIN32
for( n = 0; n < nthreads; n++ )
- {
- pthread_join(threads[n], NULL);
- }
-#else
- WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
-#endif
+ pg_thrd_join(threads[n], NULL);
free(threads);
/* and check results */
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
-#line 79 "thread.pgc"
+#line 57 "thread.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from test_thread", ECPGt_EOIT,
ECPGt_int,&(l_rows),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
-#line 80 "thread.pgc"
+#line 58 "thread.pgc"
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 81 "thread.pgc"
+#line 59 "thread.pgc"
{ ECPGdisconnect(__LINE__, "CURRENT");}
-#line 82 "thread.pgc"
+#line 60 "thread.pgc"
if( l_rows == (nthreads * iterations) )
printf("Success.\n");
@@ -129,7 +107,7 @@ int main(void)
return 0;
}
-void *test_thread(void *arg)
+int test_thread(void *arg)
{
long threadnum = (intptr_t) arg;
@@ -137,13 +115,13 @@ void *test_thread(void *arg)
-#line 96 "thread.pgc"
+#line 74 "thread.pgc"
int l_i ;
-#line 97 "thread.pgc"
+#line 75 "thread.pgc"
char l_connection [ 128 ] ;
/* exec sql end declare section */
-#line 98 "thread.pgc"
+#line 76 "thread.pgc"
/* build up connection name, and connect to database */
@@ -153,24 +131,24 @@ void *test_thread(void *arg)
_snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
#endif
/* exec sql whenever sqlerror sqlprint ; */
-#line 106 "thread.pgc"
+#line 84 "thread.pgc"
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , l_connection, 0);
-#line 107 "thread.pgc"
+#line 85 "thread.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 107 "thread.pgc"
+#line 85 "thread.pgc"
if( sqlca.sqlcode != 0 )
{
printf("%s: ERROR: cannot connect to database!\n", l_connection);
- return NULL;
+ return 0;
}
{ ECPGtrans(__LINE__, l_connection, "begin");
-#line 113 "thread.pgc"
+#line 91 "thread.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 113 "thread.pgc"
+#line 91 "thread.pgc"
/* insert into test_thread table */
@@ -181,10 +159,10 @@ if (sqlca.sqlcode < 0) sqlprint();}
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(l_i),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
-#line 118 "thread.pgc"
+#line 96 "thread.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 118 "thread.pgc"
+#line 96 "thread.pgc"
if( sqlca.sqlcode != 0 )
printf("%s: ERROR: insert failed!\n", l_connection);
@@ -192,16 +170,16 @@ if (sqlca.sqlcode < 0) sqlprint();}
/* all done */
{ ECPGtrans(__LINE__, l_connection, "commit");
-#line 124 "thread.pgc"
+#line 102 "thread.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 124 "thread.pgc"
+#line 102 "thread.pgc"
{ ECPGdisconnect(__LINE__, l_connection);
-#line 125 "thread.pgc"
+#line 103 "thread.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 125 "thread.pgc"
+#line 103 "thread.pgc"
- return NULL;
+ return 0;
}
diff --git a/src/interfaces/ecpg/test/expected/thread-thread_implicit.c b/src/interfaces/ecpg/test/expected/thread-thread_implicit.c
index 259fc09dad6..588e1c2ef31 100644
--- a/src/interfaces/ecpg/test/expected/thread-thread_implicit.c
+++ b/src/interfaces/ecpg/test/expected/thread-thread_implicit.c
@@ -14,13 +14,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#include <locale.h>
-#endif
+#include "port/pg_threads.h"
#line 1 "regression.h"
@@ -30,29 +24,25 @@
-#line 16 "thread_implicit.pgc"
+#line 10 "thread_implicit.pgc"
-void *test_thread(void *arg);
+int test_thread(void *arg);
int nthreads = 10;
int iterations = 20;
int main(void)
{
-#ifndef WIN32
- pthread_t *threads;
-#else
- HANDLE *threads;
-#endif
+ pg_thrd_t *threads;
intptr_t n;
/* exec sql begin declare section */
-#line 32 "thread_implicit.pgc"
+#line 22 "thread_implicit.pgc"
int l_rows ;
/* exec sql end declare section */
-#line 33 "thread_implicit.pgc"
+#line 23 "thread_implicit.pgc"
/* Do not switch on debug output for regression tests. The threads get executed in
@@ -61,22 +51,22 @@ int main(void)
/* setup test_thread table */
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
-#line 40 "thread_implicit.pgc"
+#line 30 "thread_implicit.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table test_thread", ECPGt_EOIT, ECPGt_EORT);}
-#line 41 "thread_implicit.pgc"
+#line 31 "thread_implicit.pgc"
/* DROP might fail */
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 42 "thread_implicit.pgc"
+#line 32 "thread_implicit.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test_thread ( tstamp timestamp not null default cast ( timeofday ( ) as timestamp ) , thread text not null , iteration integer not null , primary key ( thread , iteration ) )", ECPGt_EOIT, ECPGt_EORT);}
-#line 47 "thread_implicit.pgc"
+#line 37 "thread_implicit.pgc"
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 48 "thread_implicit.pgc"
+#line 38 "thread_implicit.pgc"
{ ECPGdisconnect(__LINE__, "CURRENT");}
-#line 49 "thread_implicit.pgc"
+#line 39 "thread_implicit.pgc"
/* create, and start, threads */
@@ -87,39 +77,27 @@ int main(void)
return 1;
}
for( n = 0; n < nthreads; n++ )
- {
-#ifndef WIN32
- pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
-#else
- threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n+1), 0, NULL);
-#endif
- }
+ pg_thrd_create(&threads[n], test_thread, (void *) (n + 1));
/* wait for thread completion */
-#ifndef WIN32
for( n = 0; n < nthreads; n++ )
- {
- pthread_join(threads[n], NULL);
- }
-#else
- WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
-#endif
+ pg_thrd_join(threads[n], NULL);
free(threads);
/* and check results */
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); }
-#line 79 "thread_implicit.pgc"
+#line 57 "thread_implicit.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from test_thread", ECPGt_EOIT,
ECPGt_int,&(l_rows),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
-#line 80 "thread_implicit.pgc"
+#line 58 "thread_implicit.pgc"
{ ECPGtrans(__LINE__, NULL, "commit");}
-#line 81 "thread_implicit.pgc"
+#line 59 "thread_implicit.pgc"
{ ECPGdisconnect(__LINE__, "CURRENT");}
-#line 82 "thread_implicit.pgc"
+#line 60 "thread_implicit.pgc"
if( l_rows == (nthreads * iterations) )
printf("Success.\n");
@@ -129,7 +107,7 @@ int main(void)
return 0;
}
-void *test_thread(void *arg)
+int test_thread(void *arg)
{
long threadnum = (intptr_t) arg;
@@ -137,13 +115,13 @@ void *test_thread(void *arg)
-#line 96 "thread_implicit.pgc"
+#line 74 "thread_implicit.pgc"
int l_i ;
-#line 97 "thread_implicit.pgc"
+#line 75 "thread_implicit.pgc"
char l_connection [ 128 ] ;
/* exec sql end declare section */
-#line 98 "thread_implicit.pgc"
+#line 76 "thread_implicit.pgc"
/* build up connection name, and connect to database */
@@ -153,24 +131,24 @@ void *test_thread(void *arg)
_snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
#endif
/* exec sql whenever sqlerror sqlprint ; */
-#line 106 "thread_implicit.pgc"
+#line 84 "thread_implicit.pgc"
{ ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , l_connection, 0);
-#line 107 "thread_implicit.pgc"
+#line 85 "thread_implicit.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 107 "thread_implicit.pgc"
+#line 85 "thread_implicit.pgc"
if( sqlca.sqlcode != 0 )
{
printf("%s: ERROR: cannot connect to database!\n", l_connection);
- return NULL;
+ return 0;
}
{ ECPGtrans(__LINE__, NULL, "begin");
-#line 113 "thread_implicit.pgc"
+#line 91 "thread_implicit.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 113 "thread_implicit.pgc"
+#line 91 "thread_implicit.pgc"
/* insert into test_thread table */
@@ -181,10 +159,10 @@ if (sqlca.sqlcode < 0) sqlprint();}
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(l_i),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
-#line 118 "thread_implicit.pgc"
+#line 96 "thread_implicit.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 118 "thread_implicit.pgc"
+#line 96 "thread_implicit.pgc"
if( sqlca.sqlcode != 0 )
printf("%s: ERROR: insert failed!\n", l_connection);
@@ -192,16 +170,16 @@ if (sqlca.sqlcode < 0) sqlprint();}
/* all done */
{ ECPGtrans(__LINE__, NULL, "commit");
-#line 124 "thread_implicit.pgc"
+#line 102 "thread_implicit.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 124 "thread_implicit.pgc"
+#line 102 "thread_implicit.pgc"
{ ECPGdisconnect(__LINE__, l_connection);
-#line 125 "thread_implicit.pgc"
+#line 103 "thread_implicit.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
-#line 125 "thread_implicit.pgc"
+#line 103 "thread_implicit.pgc"
- return NULL;
+ return 0;
}
diff --git a/src/interfaces/ecpg/test/thread/alloc.pgc b/src/interfaces/ecpg/test/thread/alloc.pgc
index 39faa6dc2ef..92097866ba4 100644
--- a/src/interfaces/ecpg/test/thread/alloc.pgc
+++ b/src/interfaces/ecpg/test/thread/alloc.pgc
@@ -1,16 +1,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
-#include <stdio.h>
+#include "port/pg_threads.h"
#define THREADS 16
#define REPEATS 50
@@ -21,11 +12,7 @@ exec sql include ../regression;
exec sql whenever sqlerror sqlprint;
exec sql whenever not found sqlprint;
-#ifdef WIN32
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
@@ -54,28 +41,12 @@ static void* fn(void* arg)
int main(void)
{
intptr_t i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
-
-#ifdef WIN32
- for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
- }
+ pg_thrd_t threads[THREADS];
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
- for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, (void *) i);
+ pg_thrd_create(&threads[i], fn, (void *) i);
for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/thread/descriptor.pgc b/src/interfaces/ecpg/test/thread/descriptor.pgc
index b1485ac2a5c..1fd41dd666f 100644
--- a/src/interfaces/ecpg/test/thread/descriptor.pgc
+++ b/src/interfaces/ecpg/test/thread/descriptor.pgc
@@ -1,12 +1,4 @@
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
-#include <stdio.h>
+#include "port/pg_threads.h"
#define THREADS 16
#define REPEATS 50000
@@ -15,11 +7,7 @@ EXEC SQL include sqlca;
EXEC SQL whenever sqlerror sqlprint;
EXEC SQL whenever not found sqlprint;
-#if defined(WIN32)
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
@@ -35,28 +23,12 @@ static void* fn(void* arg)
int main(void)
{
int i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
+ pg_thrd_t threads[THREADS];
-#ifdef WIN32
for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, NULL, 0, &id);
- }
-
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
- for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
- for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, NULL);
+ pg_thrd_create(&threads[i], fn, NULL);
for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/thread/prep.pgc b/src/interfaces/ecpg/test/thread/prep.pgc
index a389a6ae39e..c4119a236a8 100644
--- a/src/interfaces/ecpg/test/thread/prep.pgc
+++ b/src/interfaces/ecpg/test/thread/prep.pgc
@@ -1,15 +1,8 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
+#include "port/pg_threads.h"
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <process.h>
-#include <locale.h>
-#else
-#include <pthread.h>
-#endif
#include <stdio.h>
#define THREADS 16
@@ -21,11 +14,7 @@ exec sql include ../regression;
exec sql whenever sqlerror sqlprint;
exec sql whenever not found sqlprint;
-#ifdef WIN32
-static unsigned __stdcall fn(void* arg)
-#else
-static void* fn(void* arg)
-#endif
+static int fn(void* arg)
{
int i;
@@ -54,11 +43,7 @@ static void* fn(void* arg)
int main(void)
{
intptr_t i;
-#ifdef WIN32
- HANDLE threads[THREADS];
-#else
- pthread_t threads[THREADS];
-#endif
+ pg_thrd_t threads[THREADS];
EXEC SQL CONNECT TO REGRESSDB1;
EXEC SQL SET AUTOCOMMIT TO ON;
@@ -66,22 +51,10 @@ int main(void)
EXEC SQL CREATE TABLE T ( i int );
EXEC SQL DISCONNECT;
-#ifdef WIN32
for (i = 0; i < THREADS; ++i)
- {
- unsigned id;
- threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
- }
-
- WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
- for (i = 0; i < THREADS; ++i)
- CloseHandle(threads[i]);
-#else
- for (i = 0; i < THREADS; ++i)
- pthread_create(&threads[i], NULL, fn, (void *) i);
+ pg_thrd_create(&threads[i], fn, (void *) i);
for (i = 0; i < THREADS; ++i)
- pthread_join(threads[i], NULL);
-#endif
+ pg_thrd_join(threads[i], NULL);
return 0;
}
diff --git a/src/interfaces/ecpg/test/thread/thread.pgc b/src/interfaces/ecpg/test/thread/thread.pgc
index 36ff91fe816..9e90ffc2643 100644
--- a/src/interfaces/ecpg/test/thread/thread.pgc
+++ b/src/interfaces/ecpg/test/thread/thread.pgc
@@ -5,28 +5,18 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#include <locale.h>
-#endif
+#include "port/pg_threads.h"
exec sql include ../regression;
-void *test_thread(void *arg);
+int test_thread(void *arg);
int nthreads = 10;
int iterations = 20;
int main(void)
{
-#ifndef WIN32
- pthread_t *threads;
-#else
- HANDLE *threads;
-#endif
+ pg_thrd_t *threads;
intptr_t n;
EXEC SQL BEGIN DECLARE SECTION;
int l_rows;
@@ -56,23 +46,11 @@ int main(void)
return 1;
}
for( n = 0; n < nthreads; n++ )
- {
-#ifndef WIN32
- pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
-#else
- threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n + 1), 0, NULL);
-#endif
- }
+ pg_thrd_create(&threads[n], test_thread, (void *) (n + 1));
/* wait for thread completion */
-#ifndef WIN32
for( n = 0; n < nthreads; n++ )
- {
- pthread_join(threads[n], NULL);
- }
-#else
- WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
-#endif
+ pg_thrd_join(threads[n], NULL);
free(threads);
/* and check results */
@@ -88,7 +66,7 @@ int main(void)
return 0;
}
-void *test_thread(void *arg)
+int test_thread(void *arg)
{
long threadnum = (intptr_t) arg;
@@ -108,7 +86,7 @@ void *test_thread(void *arg)
if( sqlca.sqlcode != 0 )
{
printf("%s: ERROR: cannot connect to database!\n", l_connection);
- return NULL;
+ return 0;
}
EXEC SQL AT :l_connection BEGIN;
@@ -123,5 +101,5 @@ void *test_thread(void *arg)
/* all done */
EXEC SQL AT :l_connection COMMIT;
EXEC SQL DISCONNECT :l_connection;
- return NULL;
+ return 0;
}
diff --git a/src/interfaces/ecpg/test/thread/thread_implicit.pgc b/src/interfaces/ecpg/test/thread/thread_implicit.pgc
index 711a8e26cc6..a0cbe07abc2 100644
--- a/src/interfaces/ecpg/test/thread/thread_implicit.pgc
+++ b/src/interfaces/ecpg/test/thread/thread_implicit.pgc
@@ -5,28 +5,18 @@
#include <stdint.h>
#include <stdlib.h>
#include "ecpg_config.h"
-
-#ifndef WIN32
-#include <pthread.h>
-#else
-#include <windows.h>
-#include <locale.h>
-#endif
+#include "port/pg_threads.h"
exec sql include ../regression;
-void *test_thread(void *arg);
+int test_thread(void *arg);
int nthreads = 10;
int iterations = 20;
int main(void)
{
-#ifndef WIN32
- pthread_t *threads;
-#else
- HANDLE *threads;
-#endif
+ pg_thrd_t *threads;
intptr_t n;
EXEC SQL BEGIN DECLARE SECTION;
int l_rows;
@@ -56,23 +46,11 @@ int main(void)
return 1;
}
for( n = 0; n < nthreads; n++ )
- {
-#ifndef WIN32
- pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
-#else
- threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n+1), 0, NULL);
-#endif
- }
+ pg_thrd_create(&threads[n], test_thread, (void *) (n + 1));
/* wait for thread completion */
-#ifndef WIN32
for( n = 0; n < nthreads; n++ )
- {
- pthread_join(threads[n], NULL);
- }
-#else
- WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
-#endif
+ pg_thrd_join(threads[n], NULL);
free(threads);
/* and check results */
@@ -88,7 +66,7 @@ int main(void)
return 0;
}
-void *test_thread(void *arg)
+int test_thread(void *arg)
{
long threadnum = (intptr_t) arg;
@@ -108,7 +86,7 @@ void *test_thread(void *arg)
if( sqlca.sqlcode != 0 )
{
printf("%s: ERROR: cannot connect to database!\n", l_connection);
- return NULL;
+ return 0;
}
EXEC SQL BEGIN;
@@ -123,5 +101,5 @@ void *test_thread(void *arg)
/* all done */
EXEC SQL COMMIT;
EXEC SQL DISCONNECT :l_connection;
- return NULL;
+ return 0;
}
--
2.47.3