diff options
author | Bruce Momjian <bruce@momjian.us> | 2004-02-11 21:44:06 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2004-02-11 21:44:06 +0000 |
commit | c6f05593710757351535cc80a3872152d91e5cef (patch) | |
tree | b6381cb0ff9a63a2f38eda1d139b60f3946c08b6 /src | |
parent | 15b330b648553627230a11adce304103a55e0b62 (diff) | |
download | postgresql-c6f05593710757351535cc80a3872152d91e5cef.tar.gz postgresql-c6f05593710757351535cc80a3872152d91e5cef.zip |
Check and set thread-safe functions separately, rather than as a single
variable.
Remove thread locking for non-thread-safe functions, instead throw a
compile error.
Platforms will have to re-run tools/thread to record their thread
safety.
Diffstat (limited to 'src')
-rw-r--r-- | src/include/pg_config.h.in | 12 | ||||
-rw-r--r-- | src/port/thread.c | 152 | ||||
-rw-r--r-- | src/template/bsdi | 5 | ||||
-rw-r--r-- | src/template/freebsd | 3 | ||||
-rw-r--r-- | src/template/linux | 3 | ||||
-rw-r--r-- | src/template/netbsd | 3 | ||||
-rw-r--r-- | src/template/osf | 3 | ||||
-rw-r--r-- | src/template/solaris | 3 | ||||
-rw-r--r-- | src/template/unixware | 3 | ||||
-rw-r--r-- | src/tools/thread/thread_test.c | 104 |
10 files changed, 79 insertions, 212 deletions
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 3b7526f3796..7fbfa66086e 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -43,6 +43,12 @@ (--enable-thread-safety) */ #undef ENABLE_THREAD_SAFETY +/* Define if gethostbyname is not thread safe */ +#undef GETHOSTBYNAME_THREADSAFE + +/* Define if getpwuid is not thread safe */ +#undef GETPWUID_THREADSAFE + /* Define to 1 if gettimeofday() takes only 1 argument. */ #undef GETTIMEOFDAY_1ARG @@ -554,9 +560,6 @@ /* Define as the maximum alignment requirement of any C data type. */ #undef MAXIMUM_ALIGNOF -/* Define if non *_r libc functions are not thread safe */ -#undef NEED_REENTRANT_FUNCS - /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -588,6 +591,9 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define if strerror is not thread safe */ +#undef STRERROR_THREADSAFE + /* Define to 1 if your <sys/time.h> declares `struct tm'. */ #undef TM_IN_SYS_TIME diff --git a/src/port/thread.c b/src/port/thread.c index e164d017d4f..d6e1b269733 100644 --- a/src/port/thread.c +++ b/src/port/thread.c @@ -7,7 +7,7 @@ * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/port/thread.c,v 1.14 2003/11/29 22:41:31 pgsql Exp $ + * $PostgreSQL: pgsql/src/port/thread.c,v 1.15 2004/02/11 21:44:06 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ * strerror(). Other operating systems use pthread_setspecific() * and pthread_getspecific() internally to allow standard library * functions to return static data to threaded applications. And some - * operating systems have neither, meaning we have to do our own locking. + * operating systems have neither. * * Additional confusion exists because many operating systems that * use pthread_setspecific/pthread_getspecific() also have *_r versions @@ -50,18 +50,13 @@ * * The current setup is to try threading in this order: * - * use non-*_r function names if they are all thread-safe - * (NEED_REENTRANT_FUNCS=no) - * use *_r functions if they exist (configure test) - * do our own locking and copying of non-threadsafe functions - * - * The disadvantage of the last option is not the thread overhead but - * the fact that all function calls are serialized, and with gethostbyname() - * requiring a DNS lookup, that could be slow. + * use *_r function names if they exit + * (*_THREADSAFE=ye) + * use non-*_r functions if they are thread-safe * * One thread-safe solution for gethostbyname() might be to use getaddrinfo(). * - * See src/tools/thread to see if your operating system has thread-safe + * Run src/tools/thread to see if your operating system has thread-safe * non-*_r functions. */ @@ -73,7 +68,7 @@ char * pqStrerror(int errnum, char *strerrbuf, size_t buflen) { -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_STRERROR_R) +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R) /* reentrant strerror_r is available */ /* some early standards had strerror_r returning char * */ strerror_r(errnum, strerrbuf, buflen); @@ -81,18 +76,13 @@ pqStrerror(int errnum, char *strerrbuf, size_t buflen) #else -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R) - static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&strerror_lock); +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(STRERROR_THREADSAFE) +#error This platform can not create a thread-safe version because strerror is not thread-safe and there is no reentrant version #endif /* no strerror_r() available, just use strerror */ StrNCpy(strerrbuf, strerror(errnum), buflen); -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R) - pthread_mutex_unlock(&strerror_lock); -#endif - return strerrbuf; #endif } @@ -106,7 +96,7 @@ int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result) { -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_GETPWUID_R) +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R) /* * Early POSIX draft of getpwuid_r() returns 'struct passwd *'. * getpwuid_r(uid, resultbuf, buffer, buflen) @@ -117,53 +107,14 @@ pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, #else -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R) - static pthread_mutex_t getpwuid_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&getpwuid_lock); +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(GETPWUID_THREADSAFE) +#error This platform can not create a thread-safe version because getpwuid is not thread-safe and there is no reentrant version #endif /* no getpwuid_r() available, just use getpwuid() */ *result = getpwuid(uid); - -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R) - - /* Use 'buffer' memory for storage of strings used by struct passwd */ - if (*result && - strlen((*result)->pw_name) + 1 + - strlen((*result)->pw_passwd) + 1 + - strlen((*result)->pw_gecos) + 1 + - /* skip class if it exists */ - strlen((*result)->pw_dir) + 1 + - strlen((*result)->pw_shell) + 1 <= buflen) - { - memcpy(resultbuf, *result, sizeof(struct passwd)); - strcpy(buffer, (*result)->pw_name); - resultbuf->pw_name = buffer; - buffer += strlen(resultbuf->pw_name) + 1; - strcpy(buffer, (*result)->pw_passwd); - resultbuf->pw_passwd = buffer; - buffer += strlen(resultbuf->pw_passwd) + 1; - strcpy(buffer, (*result)->pw_gecos); - resultbuf->pw_gecos = buffer; - buffer += strlen(resultbuf->pw_gecos) + 1; - strcpy(buffer, (*result)->pw_dir); - resultbuf->pw_dir = buffer; - buffer += strlen(resultbuf->pw_dir) + 1; - strcpy(buffer, (*result)->pw_shell); - resultbuf->pw_shell = buffer; - buffer += strlen(resultbuf->pw_shell) + 1; - - *result = resultbuf; - } - else - { - *result = NULL; - errno = ERANGE; - } - - pthread_mutex_unlock(&getpwuid_lock); -#endif #endif + return (*result == NULL) ? -1 : 0; } #endif @@ -181,7 +132,7 @@ pqGethostbyname(const char *name, struct hostent **result, int *herrno) { -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_GETHOSTBYNAME_R) +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R) /* * broken (well early POSIX draft) gethostbyname_r() which returns * 'struct hostent *' @@ -191,87 +142,16 @@ pqGethostbyname(const char *name, #else -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) - static pthread_mutex_t gethostbyname_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&gethostbyname_lock); +#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && !defined(GETHOSTBYNAME_THREADSAFE) +#error This platform can not create a thread-safe version because getaddrinfo is not thread-safe and there is no reentrant version #endif /* no gethostbyname_r(), just use gethostbyname() */ *result = gethostbyname(name); -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) - - /* - * Use 'buffer' memory for storage of structures used by struct hostent. - * The layout is: - * - * addr pointers - * alias pointers - * addr structures - * alias structures - * name - */ - if (*result) - { - int i, pointers = 2 /* for nulls */, len = 0; - char **pbuffer; - - for (i = 0; (*result)->h_addr_list[i]; i++, pointers++) - len += (*result)->h_length; - for (i = 0; (*result)->h_aliases[i]; i++, pointers++) - len += (*result)->h_length; - - if (pointers * sizeof(char *) + MAXALIGN(len) + strlen((*result)->h_name) + 1 <= buflen) - { - memcpy(resultbuf, *result, sizeof(struct hostent)); - - pbuffer = (char **)buffer; - resultbuf->h_addr_list = pbuffer; - buffer += pointers * sizeof(char *); - - for (i = 0; (*result)->h_addr_list[i]; i++, pbuffer++) - { - memcpy(buffer, (*result)->h_addr_list[i], (*result)->h_length); - resultbuf->h_addr_list[i] = buffer; - buffer += (*result)->h_length; - } - resultbuf->h_addr_list[i] = NULL; - pbuffer++; - - resultbuf->h_aliases = pbuffer; - - for (i = 0; (*result)->h_aliases[i]; i++, pbuffer++) - { - memcpy(buffer, (*result)->h_aliases[i], (*result)->h_length); - resultbuf->h_aliases[i] = buffer; - buffer += (*result)->h_length; - } - resultbuf->h_aliases[i] = NULL; - pbuffer++; - - /* Place at end for cleaner alignment */ - buffer = MAXALIGN(buffer); - strcpy(buffer, (*result)->h_name); - resultbuf->h_name = buffer; - buffer += strlen(resultbuf->h_name) + 1; - - *result = resultbuf; - } - else - { - *result = NULL; - errno = ERANGE; - } - } -#endif - if (*result != NULL) *herrno = h_errno; -#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) - pthread_mutex_unlock(&gethostbyname_lock); -#endif - if (*result != NULL) return 0; else diff --git a/src/template/bsdi b/src/template/bsdi index 4c62ce44217..dd750bdc997 100644 --- a/src/template/bsdi +++ b/src/template/bsdi @@ -3,4 +3,7 @@ case $host_os in esac THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=no # verified 4.3 2003-09-26 +# verified 4.3.1 2004-02-11 +STRERROR_THREADSAFE=yes +GETPWUID_THREADSAFE=yes +GETHOSTBYNAME_THREADSAFE=yes diff --git a/src/template/freebsd b/src/template/freebsd index 2b155d12db9..c78b87bd761 100644 --- a/src/template/freebsd +++ b/src/template/freebsd @@ -2,8 +2,7 @@ case $host_cpu in alpha*) CFLAGS="-O";; # alpha has problems with -O2 esac -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=yes +# tools/thread/thread_test must be run THREAD_CPPFLAGS="-D_THREAD_SAFE" case $host_os in freebsd2*|freebsd3*|freebsd4*) THREAD_LIBS="-pthread";; diff --git a/src/template/linux b/src/template/linux index 529da9c1694..7469b331078 100644 --- a/src/template/linux +++ b/src/template/linux @@ -1,7 +1,6 @@ # Force _GNU_SOURCE on; plperl is broken with Perl 5.8.0 otherwise CPPFLAGS="-D_GNU_SOURCE" -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=yes # Debian kernel 2.2 2003-09-27 +# tools/thread/thread_test must be run THREAD_CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" THREAD_LIBS="-lpthread" diff --git a/src/template/netbsd b/src/template/netbsd index 0d119a01361..1cb953c7fb5 100644 --- a/src/template/netbsd +++ b/src/template/netbsd @@ -1,2 +1 @@ -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=yes # 1.6 2003-09-14 +# tools/thread/thread_test must be run diff --git a/src/template/osf b/src/template/osf index 9d2d6b81c1c..c331ed7f3dc 100644 --- a/src/template/osf +++ b/src/template/osf @@ -3,8 +3,7 @@ if test "$GCC" != yes ; then CFLAGS="-O -ieee" fi -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=no # 4.0 2003-09-13 +# tools/thread/thread_test must be run if test "$GCC" = yes then THREAD_LIBS="-pthread" else THREAD_CPPFLAGS="-pthread" diff --git a/src/template/solaris b/src/template/solaris index 489bece9489..7534c7fe578 100644 --- a/src/template/solaris +++ b/src/template/solaris @@ -9,8 +9,7 @@ case $host in i?86-*-solaris*) need_tas=yes; tas_file=solaris_i386.s ;; esac -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=yes # 5.6 2003-09-13 +# tools/thread/thread_test must be run if test "$GCC" = yes then THREAD_LIBS="-pthread" else THREAD_CPPFLAGS="-mt" diff --git a/src/template/unixware b/src/template/unixware index dc469873ccc..c1af94b5b4d 100644 --- a/src/template/unixware +++ b/src/template/unixware @@ -24,6 +24,5 @@ __EOF__ THREAD_CPPFLAGS="-K pthread" fi -THREAD_SUPPORT=yes -NEED_REENTRANT_FUNCS=no # verified 7.1.3 2003-09-03 +# tools/thread/thread_test must be run THREAD_CPPFLAGS="$THREAD_CPPFLAGS -D_REENTRANT" diff --git a/src/tools/thread/thread_test.c b/src/tools/thread/thread_test.c index 654bb155f5c..a09c8fca02d 100644 --- a/src/tools/thread/thread_test.c +++ b/src/tools/thread/thread_test.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.6 2003/12/19 23:29:15 momjian Exp $ + * $PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.7 2004/02/11 21:44:06 momjian Exp $ * * This program tests to see if your standard libc functions use * pthread_setspecific()/pthread_getspecific() to be thread-safe. @@ -33,16 +33,14 @@ void func_call_1(void); void func_call_2(void); -#ifndef HAVE_GETADDRINFO -struct hostent *hostent_p1; -struct hostent *hostent_p2; -#endif +char *strerror_p1; +char *strerror_p2; struct passwd *passwd_p1; struct passwd *passwd_p2; -char *strerror_p1; -char *strerror_p2; +struct hostent *hostent_p1; +struct hostent *hostent_p2; int main(int argc, char *argv[]) { @@ -64,48 +62,34 @@ defines to your template/$port file before compiling this program.\n\n" pthread_join(thread1, NULL); pthread_join(thread2, NULL); -#ifndef HAVE_GETADDRINFO - if (hostent_p1 == hostent_p2) - printf("Your gethostbyname() is _not_ thread-safe\n"); -#endif - if (passwd_p1 == passwd_p2) - printf("Your getpwuid() is _not_ thread-safe\n"); - if (strerror_p1 == strerror_p2) - printf("Your strerror() is _not_ thread-safe\n"); - - if ( -#ifndef HAVE_GETADDRINFO - hostent_p1 != hostent_p2 && -#endif - passwd_p1 != passwd_p2 && - strerror_p1 != strerror_p2) - { - printf("All your non-*_r functions are thread-safe.\n"); - printf("Add this to your template/$port file:\n\n"); - printf("NEED_REENTRANT_FUNCS=no\n"); - } + printf("Add this to your template/$port file:\n\n"); + + if (strerror_p1 != strerror_p2) + printf("STRERROR_THREADSAFE=yes\n"); else - { - printf("Not all non-*_r functions are thread-safe.\n"); - printf("Add this to your template/$port file:\n\n"); - printf("NEED_REENTRANT_FUNCS=yes\n"); - } + printf("STRERROR_THREADSAFE=no\n"); + + if (passwd_p1 != passwd_p2) + printf("GETPWUID_THREADSAFE=yes\n"); + else + printf("GETPWUID_THREADSAFE=no\n"); + if (hostent_p1 != hostent_p2) + printf("GETHOSTBYNAME_THREADSAFE=yes\n"); + else + printf("GETHOSTBYNAME_THREADSAFE=no\n"); + return 0; } void func_call_1(void) { void *p; -#ifndef HAVE_GETADDRINFO - hostent_p1 = gethostbyname("yahoo.com"); - p = gethostbyname("slashdot.org"); - if (hostent_p1 != p) - { - printf("Your gethostbyname() changes the static memory area between calls\n"); - hostent_p1 = NULL; /* force thread-safe failure report */ - } -#endif + strerror_p1 = strerror(EACCES); + /* + * If strerror() uses sys_errlist, the pointer might change for different + * errno values, so we don't check to see if it varies within the thread. + */ passwd_p1 = getpwuid(0); p = getpwuid(1); @@ -115,26 +99,24 @@ void func_call_1(void) { passwd_p1 = NULL; /* force thread-safe failure report */ } - strerror_p1 = strerror(EACCES); - /* - * If strerror() uses sys_errlist, the pointer might change for different - * errno values, so we don't check to see if it varies within the thread. - */ + hostent_p1 = gethostbyname("yahoo.com"); + p = gethostbyname("slashdot.org"); + if (hostent_p1 != p) + { + printf("Your gethostbyname() changes the static memory area between calls\n"); + hostent_p1 = NULL; /* force thread-safe failure report */ + } } void func_call_2(void) { void *p; -#ifndef HAVE_GETADDRINFO - hostent_p2 = gethostbyname("google.com"); - p = gethostbyname("postgresql.org"); - if (hostent_p2 != p) - { - printf("Your gethostbyname() changes the static memory area between calls\n"); - hostent_p2 = NULL; /* force thread-safe failure report */ - } -#endif + strerror_p2 = strerror(EINVAL); + /* + * If strerror() uses sys_errlist, the pointer might change for different + * errno values, so we don't check to see if it varies within the thread. + */ passwd_p2 = getpwuid(2); p = getpwuid(3); @@ -144,9 +126,11 @@ void func_call_2(void) { passwd_p2 = NULL; /* force thread-safe failure report */ } - strerror_p2 = strerror(EINVAL); - /* - * If strerror() uses sys_errlist, the pointer might change for different - * errno values, so we don't check to see if it varies within the thread. - */ + hostent_p2 = gethostbyname("google.com"); + p = gethostbyname("postgresql.org"); + if (hostent_p2 != p) + { + printf("Your gethostbyname() changes the static memory area between calls\n"); + hostent_p2 = NULL; /* force thread-safe failure report */ + } } |