Commit 60e83cec authored by Michael Meskes's avatar Michael Meskes

Applied another patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp>

to get memory allocation thread-safe. He also did some cleaning up.
parent ae57efed
......@@ -2242,5 +2242,10 @@ Mi 26. Sep 12:45:51 CEST 2007
- Applied patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp>
to get prepare thread-safe.
Sun, 30 Sep 2007 13:37:31 +0200
- Applied another patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp>
to get memory allocation thread-safe. He also did some cleaning up.
- Set ecpg library version to 6.0.
- Set ecpg version to 4.4.
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.43 2007/09/26 10:57:00 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.44 2007/09/30 11:38:48 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
#include <pthread.h>
#else
#include "ecpg-pthread-win32.h"
#endif
#endif
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
......@@ -17,20 +11,17 @@
#include "sqlca.h"
#ifdef ENABLE_THREAD_SAFETY
NON_EXEC_STATIC pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t actual_connection_key;
#ifndef WIN32
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;
#else
static HANDLE connections_mutex = INVALID_HANDLE_VALUE;
static DWORD actual_connection_key;
#endif /* 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
static void
NON_EXEC_STATIC void
ecpg_actual_connection_init(void)
{
pthread_key_create(&actual_connection_key, NULL);
......@@ -39,13 +30,7 @@ ecpg_actual_connection_init(void)
void
ecpg_pthreads_init(void)
{
#ifndef WIN32
pthread_once(&actual_connection_key_once, ecpg_actual_connection_init);
#else
static long has_run = 0;
if (InterlockedCompareExchange(&has_run, 1, 0) == 0)
ecpg_actual_connection_init();
#endif
}
#endif
......@@ -134,6 +119,7 @@ ecpg_finish(struct connection * act)
struct ECPGtype_information_cache *cache,
*ptr;
ECPGdeallocate_all_conn(0, ECPG_COMPAT_PGSQL, act);
PQfinish(act->connection);
/*
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.27 2007/09/26 10:57:00 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.28 2007/09/30 11:38:48 meskes Exp $ */
#ifndef _ECPG_LIB_EXTERN_H
#define _ECPG_LIB_EXTERN_H
......@@ -146,6 +146,7 @@ bool ECPGcheck_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE);
void ECPGraise(int line, int code, const char *sqlstate, const char *str);
void ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat);
char *ECPGprepared(const char *, struct connection *, int);
bool ECPGdeallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *conn);
/* SQLSTATE values generated or processed by ecpglib (intentionally
* not exported -- users should refer to the codes directly) */
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.8 2006/11/08 10:46:47 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.9 2007/09/30 11:38:48 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include "ecpg-pthread-win32.h"
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
......@@ -25,7 +26,6 @@ ECPGalloc(long size, int lineno)
return NULL;
}
memset(new, '\0', size);
return (new);
}
......@@ -62,11 +62,48 @@ ECPGstrdup(const char *string, int lineno)
}
/* keep a list of memory we allocated for the user */
static struct auto_mem
struct auto_mem
{
void *pointer;
struct auto_mem *next;
} *auto_allocs = NULL;
};
#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)
{
ECPGfree_auto_mem();
}
NON_EXEC_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);
}
#else
static struct auto_mem *auto_allocs = NULL;
#define get_auto_allocs() (auto_allocs)
#define set_auto_allocs(am) do { auto_allocs = (am); } while(0)
#endif
void
ECPGadd_mem(void *ptr, int lineno)
......@@ -74,41 +111,43 @@ ECPGadd_mem(void *ptr, int lineno)
struct auto_mem *am = (struct auto_mem *) ECPGalloc(sizeof(struct auto_mem), lineno);
am->pointer = ptr;
am->next = auto_allocs;
auto_allocs = am;
am->next = get_auto_allocs();
set_auto_allocs(am);
}
void
ECPGfree_auto_mem(void)
{
struct auto_mem *am;
struct auto_mem *am = get_auto_allocs();
/* free all memory we have allocated for the user */
for (am = auto_allocs; am;)
if (am)
{
struct auto_mem *act = am;
am = am->next;
ECPGfree(act->pointer);
ECPGfree(act);
do
{
struct auto_mem *act = am;
am = am->next;
ECPGfree(act->pointer);
ECPGfree(act);
} while(am);
set_auto_allocs(NULL);
}
auto_allocs = NULL;
}
void
ECPGclear_auto_mem(void)
{
struct auto_mem *am;
struct auto_mem *am = get_auto_allocs();
/* only free our own structure */
for (am = auto_allocs; am;)
if (am)
{
struct auto_mem *act = am;
am = am->next;
ECPGfree(act);
do
{
struct auto_mem *act = am;
am = am->next;
ECPGfree(act);
} while(am);
set_auto_allocs(NULL);
}
auto_allocs = NULL;
}
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.36 2007/08/14 10:01:52 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.37 2007/09/30 11:38:48 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <limits.h>
#include <unistd.h>
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
#include <pthread.h>
#else
#include "ecpg-pthread-win32.h"
#endif
#endif
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
......@@ -62,11 +56,9 @@ static struct sqlca_t sqlca_init =
};
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
static pthread_key_t sqlca_key;
#ifndef WIN32
static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
#else
static DWORD sqlca_key;
#endif
#else
static struct sqlca_t sqlca =
......@@ -98,13 +90,8 @@ static struct sqlca_t sqlca =
#endif
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
#else
static HANDLE debug_mutex = INVALID_HANDLE_VALUE;
static HANDLE debug_init_mutex = INVALID_HANDLE_VALUE;
#endif /* WIN32 */
NON_EXEC_STATIC pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
NON_EXEC_STATIC pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int simple_debug = 0;
static FILE *debugstream = NULL;
......@@ -135,11 +122,10 @@ ECPGinit(const struct connection * con, const char *connection_name, const int l
static void
ecpg_sqlca_key_destructor(void *arg)
{
if (arg != NULL)
free(arg); /* sqlca structure allocated in ECPGget_sqlca */
free(arg); /* sqlca structure allocated in ECPGget_sqlca */
}
static void
NON_EXEC_STATIC void
ecpg_sqlca_key_init(void)
{
pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor);
......@@ -151,13 +137,8 @@ ECPGget_sqlca(void)
{
#ifdef ENABLE_THREAD_SAFETY
struct sqlca_t *sqlca;
#ifdef WIN32
static long has_run = 0;
if (InterlockedCompareExchange(&has_run, 1, 0) == 0)
ecpg_sqlca_key_init();
#else
pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
#endif
sqlca = pthread_getspecific(sqlca_key);
if (sqlca == NULL)
......@@ -263,22 +244,13 @@ ECPGlog(const char *format,...)
va_list ap;
struct sqlca_t *sqlca = ECPGget_sqlca();
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_lock(&debug_mutex);
#endif
if (simple_debug)
{
int bufsize = strlen(format) + 100;
char *f = (char *) malloc(bufsize);
if (f == NULL)
{
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_unlock(&debug_mutex);
#endif
return;
}
/*
* regression tests set this environment variable to get the same
......@@ -289,6 +261,10 @@ ECPGlog(const char *format,...)
else
snprintf(f, bufsize, "[%d]: %s", (int) getpid(), format);
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_lock(&debug_mutex);
#endif
va_start(ap, format);
vfprintf(debugstream, f, ap);
va_end(ap);
......@@ -300,12 +276,12 @@ ECPGlog(const char *format,...)
fflush(debugstream);
ECPGfree(f);
}
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_unlock(&debug_mutex);
pthread_mutex_unlock(&debug_mutex);
#endif
free(f);
}
}
void
......@@ -437,3 +413,25 @@ ECPGis_noind_null(enum ECPGttype type, void *ptr)
return false;
}
#ifdef WIN32
/*
* Initialize mutexes and call init-once functions on loading.
*/
BOOL WINAPI
DllMain(HANDLE module, DWORD reason, LPVOID reserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
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();
}
return TRUE;
}
#endif
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.20 2007/09/26 10:57:00 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.21 2007/09/30 11:38:48 meskes Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
......@@ -31,8 +31,8 @@ typedef struct
} stmtCacheEntry;
static int nextStmtID = 1;
static int stmtCacheNBuckets = 2039; /* # buckets - a prime # */
static int stmtCacheEntPerBucket = 8; /* # entries/bucket */
const static int stmtCacheNBuckets = 2039; /* # buckets - a prime # */
const static int stmtCacheEntPerBucket = 8; /* # entries/bucket */
static stmtCacheEntry stmtCacheEntries[16384] = {{0,{0},0,0,0}};
static struct prepared_statement *find_prepared_statement(const char *name,
......@@ -263,22 +263,24 @@ ECPGdeallocate(int lineno, int c, const char *connection_name, const char *name)
}
bool
ECPGdeallocate_all(int lineno, int compat, const char *connection_name)
ECPGdeallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
{
struct connection *con;
con = ECPGget_connection(connection_name);
/* deallocate all prepared statements */
while (con->prep_stmts)
{
if (!deallocate_one(lineno, compat, con, NULL, con->prep_stmts))
if (!deallocate_one(lineno, c, con, NULL, con->prep_stmts))
return false;
}
return true;
}
bool
ECPGdeallocate_all(int lineno, int compat, const char *connection_name)
{
return ECPGdeallocate_all_conn(lineno, compat, ECPGget_connection(connection_name));
}
char *
ECPGprepared(const char *name, struct connection *con, int lineno)
{
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.1 2007/03/29 12:02:24 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpg-pthread-win32.h,v 1.2 2007/09/30 11:38:48 meskes Exp $ */
/*
* pthread mapping macros for win32 native thread implementation
*/
#ifndef _ECPG_PTHREAD_WIN32_H
#define _ECPG_PTHREAD_WIN32_H
#define pthread_mutex_lock(x) do { \
if (*x == INVALID_HANDLE_VALUE) \
*x = CreateMutex(NULL, FALSE, NULL); \
WaitForSingleObject(*x, INFINITE); \
} while (0);
#define pthread_mutex_unlock(x) ReleaseMutex(*x)
#define pthread_getspecific(x) TlsGetValue(x)
#define pthread_setspecific(x,y) TlsSetValue(x,y)
#define pthread_key_create(x,y) *x = TlsAlloc();
#endif
#ifdef ENABLE_THREAD_SAFETY
#ifndef WIN32
#include <pthread.h>
#define NON_EXEC_STATIC static
#else
#define NON_EXEC_STATIC
typedef HANDLE pthread_mutex_t;
typedef DWORD pthread_key_t;
#define PTHREAD_MUTEX_INITIALIZER INVALID_HANDLE_VALUE
#define pthread_mutex_lock(mutex) \
WaitForSingleObject(*(mutex), INFINITE);
#define pthread_mutex_unlock(mutex) \
ReleaseMutex(*(mutex))
#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)
/* 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 BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID reserved);
#endif /* WIN32 */
#endif /* ENABLE_THREAD_SAFETY */
#endif /* _ECPG_PTHREAD_WIN32_H */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.42 2007/08/22 08:20:58 meskes Exp $ */
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.43 2007/09/30 11:38:48 meskes Exp $ */
#include "postgres_fe.h"
......@@ -496,8 +496,8 @@ static datetkn deltatktbl[] = {
{"yrs", UNITS, DTK_YEAR}, /* "years" relative */
};
static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
static const unsigned int szdatetktbl = lengthof(datetktbl);
static const unsigned int szdeltatktbl = lengthof(deltatktbl);
static datetkn *datecache[MAXDATEFIELDS] = {NULL};
......
......@@ -42,3 +42,4 @@ test: sql/parser
test: thread/thread
test: thread/thread_implicit
test: thread/prep
test: thread/alloc
......@@ -42,5 +42,6 @@ test: sql/parser
test: thread/thread
test: thread/thread_implicit
test: thread/prep
test: thread/alloc
test: connect/test1
......@@ -112,5 +112,23 @@
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGexecute line 42 Ok: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg8
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg7
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg6
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg5
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg4
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: i
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg3
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg2
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: ecpg1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: Connection regress1 closed.
[NO_PID]: sqlca: code: 0, state: 00000
......@@ -146,5 +146,9 @@
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans line 90 action = commit connection = main
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: f
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: i
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: Connection main closed.
[NO_PID]: sqlca: code: 0, state: 00000
......@@ -146,5 +146,9 @@
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGtrans line 89 action = commit connection = main
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: f
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ECPGdeallocate line 0: NAME: i
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: Connection main closed.
[NO_PID]: sqlca: code: 0, state: 00000
/* Processed by ecpg (regression mode) */
/* These include files are added by the preprocessor */
#include <ecpgtype.h>
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* End of automatic include section */
#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
#line 1 "alloc.pgc"
#include <stdlib.h>
#include "ecpg_config.h"
#ifndef ENABLE_THREAD_SAFETY
int
main(void)
{
printf("No threading enabled.\n");
return 0;
}
#else
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif
#include <stdio.h>
#define THREADS 16
#define REPEATS 50
#line 1 "sqlca.h"
#ifndef POSTGRES_SQLCA_H
#define POSTGRES_SQLCA_H
#ifndef PGDLLIMPORT
#if defined(WIN32) || defined(__CYGWIN__)
#define PGDLLIMPORT __declspec (dllimport)
#else
#define PGDLLIMPORT
#endif /* __CYGWIN__ */
#endif /* PGDLLIMPORT */
#define SQLERRMC_LEN 150
#ifdef __cplusplus
extern "C"
{
#endif
struct sqlca_t
{
char sqlcaid[8];
long sqlabc;
long sqlcode;
struct
{
int sqlerrml;
char sqlerrmc[SQLERRMC_LEN];
} sqlerrm;
char sqlerrp[8];
long sqlerrd[6];
/* Element 0: empty */
/* 1: OID of processed tuple if applicable */
/* 2: number of rows processed */
/* after an INSERT, UPDATE or */
/* DELETE statement */
/* 3: empty */
/* 4: empty */
/* 5: empty */
char sqlwarn[8];
/* Element 0: set to 'W' if at least one other is 'W' */
/* 1: if 'W' at least one character string */
/* value was truncated when it was */
/* stored into a host variable. */
/*
* 2: if 'W' a (hopefully) non-fatal notice occurred
*/ /* 3: empty */
/* 4: empty */
/* 5: empty */
/* 6: empty */
/* 7: empty */
char sqlstate[5];
};
struct sqlca_t *ECPGget_sqlca(void);
#ifndef POSTGRES_ECPG_INTERNAL
#define sqlca (*ECPGget_sqlca())
#endif
#ifdef __cplusplus
}
#endif
#endif
#line 24 "alloc.pgc"
#line 1 "regression.h"
#line 25 "alloc.pgc"
/* exec sql whenever sqlerror sqlprint ; */
#line 27 "alloc.pgc"
/* exec sql whenever not found sqlprint ; */
#line 28 "alloc.pgc"
#ifdef WIN32
static unsigned STDCALL fn(void* arg)
#else
static void* fn(void* arg)
#endif
{
int i;
/* exec sql begin declare section */
#line 39 "alloc.pgc"
int value ;
#line 40 "alloc.pgc"
char name [ 100 ] ;
#line 41 "alloc.pgc"
char ** r = NULL ;
/* exec sql end declare section */
#line 42 "alloc.pgc"
value = (int)arg;
sprintf(name, "Connection: %d", value);
{ ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , name, 0);
#line 47 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 47 "alloc.pgc"
{ ECPGsetcommit(__LINE__, "on", NULL);
#line 48 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 48 "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 51 "alloc.pgc"
if (sqlca.sqlcode == ECPG_NOT_FOUND) sqlprint();
#line 51 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 51 "alloc.pgc"
free(r);
r = NULL;
}
{ ECPGdisconnect(__LINE__, name);
#line 55 "alloc.pgc"
if (sqlca.sqlcode < 0) sqlprint();}
#line 55 "alloc.pgc"
return 0;
}
int main (int argc, char** argv)
{
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, (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);
for (i = 0; i < THREADS; ++i)
pthread_join(threads[i], NULL);
#endif
return 0;
}
#endif
......@@ -15,7 +15,7 @@
int
main(void)
{
printf("No threading enabled.\n");
printf("No threading enabled.\n");
return 0;
}
#else
......@@ -123,7 +123,7 @@ struct sqlca_t *ECPGget_sqlca(void);
#ifdef WIN32
static unsigned STDCALL fn(void* arg)
#else
void* fn(void* arg)
static void* fn(void* arg)
#endif
{
int i;
......
......@@ -6,7 +6,8 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress
TESTS = thread_implicit thread_implicit.c \
thread thread.c \
prep prep.c
prep prep.c \
alloc alloc.c
all: $(TESTS)
......@@ -5,7 +5,7 @@
int
main(void)
{
printf("No threading enabled.\n");
printf("No threading enabled.\n");
return 0;
}
#else
......@@ -30,7 +30,7 @@ exec sql whenever not found sqlprint;
#ifdef WIN32
static unsigned STDCALL fn(void* arg)
#else
void* fn(void* arg)
static void* fn(void* arg)
#endif
{
int i;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment