diff --git a/src/tools/thread/Makefile b/src/tools/thread/Makefile index 3334d41e24..22d5d09f68 100644 --- a/src/tools/thread/Makefile +++ b/src/tools/thread/Makefile @@ -4,7 +4,7 @@ # # Copyright (C) 2003 by PostgreSQL Global Development Team # -# $PostgreSQL: pgsql/src/tools/thread/Makefile,v 1.4 2004/04/23 18:15:55 momjian Exp $ +# $PostgreSQL: pgsql/src/tools/thread/Makefile,v 1.5 2004/04/23 20:35:50 momjian Exp $ # #------------------------------------------------------------------------- @@ -12,13 +12,6 @@ subdir = tools/thread top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -ifeq ($(THREAD_SUPPORT), no) -$(error Your platform does not support threads) -endif -ifeq ($(THREAD_SUPPORT), ) -$(error You have not configured your template/$$port file. See the README) -endif - override CFLAGS += $(PTHREAD_CFLAGS) LDFLAGS += $(PTHREAD_LIBS) diff --git a/src/tools/thread/thread_test.c b/src/tools/thread/thread_test.c index d866f21dbd..0edf55226b 100644 --- a/src/tools/thread/thread_test.c +++ b/src/tools/thread/thread_test.c @@ -1,12 +1,12 @@ /*------------------------------------------------------------------------- * * test_thread_funcs.c - * libc thread test program + * libc thread test program * * 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.20 2004/04/23 18:15:55 momjian Exp $ + * $PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.21 2004/04/23 20:35:50 momjian Exp $ * * This program tests to see if your standard libc functions use * pthread_setspecific()/pthread_getspecific() to be thread-safe. @@ -33,188 +33,210 @@ #include "postgres.h" -void func_call_1(void); -void func_call_2(void); +void func_call_1(void); +void func_call_2(void); -char myhostname[MAXHOSTNAMELEN]; - -volatile int errno1_set = 0; -volatile int errno2_set = 0; +pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; volatile int thread1_done = 0; volatile int thread2_done = 0; -char *strerror_p1; -char *strerror_p2; +volatile int errno1_set = 0; +volatile int errno2_set = 0; +#ifndef HAVE_STRERROR_R +char *strerror_p1; +char *strerror_p2; +bool strerror_threadsafe = false; +#endif + +#ifndef HAVE_GETPWUID_R struct passwd *passwd_p1; struct passwd *passwd_p2; +bool getpwuid_threadsafe = false; +#endif +#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R) struct hostent *hostent_p1; struct hostent *hostent_p2; +char myhostname[MAXHOSTNAMELEN]; +bool gethostbyname_threadsafe = false; +#endif -bool gethostbyname_threadsafe = false; -bool getpwuid_threadsafe = false; -bool strerror_threadsafe = false; -bool platform_is_threadsafe = true; +bool platform_is_threadsafe = true; -pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; - -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - pthread_t thread1, - thread2; + pthread_t thread1, + thread2; if (argc > 1) { - fprintf(stderr, "Usage: %s\n", argv[0]); - return 1; + fprintf(stderr, "Usage: %s\n", argv[0]); + return 1; } +#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R) if (gethostname(myhostname, MAXHOSTNAMELEN) != 0) { - fprintf(stderr, "can not get local hostname, exiting\n"); - exit(1); + fprintf(stderr, "can not get local hostname, exiting\n"); + exit(1); } - - printf("\ -Make sure you have added any needed 'PTHREAD_CFLAGS' and 'PTHREAD_LIBS'\n\ -defines to your template/$port file before compiling this program.\n\n" -); +#endif /* Hold lock until we are ready for the child threads to exit. */ - pthread_mutex_lock(&init_mutex); - - pthread_create(&thread1, NULL, (void * (*)(void *)) func_call_1, NULL); - pthread_create(&thread2, NULL, (void * (*)(void *)) func_call_2, NULL); + pthread_mutex_lock(&init_mutex); + + pthread_create(&thread1, NULL, (void *(*) (void *)) func_call_1, NULL); + pthread_create(&thread2, NULL, (void *(*) (void *)) func_call_2, NULL); while (thread1_done == 0 || thread2_done == 0) - sched_yield(); /* if this is a portability problem, remove it */ + sched_yield(); /* if this is a portability problem, + * remove it */ - fprintf(stderr, "errno is thread-safe\n"); - + fprintf(stderr, "Your errno is thread-safe.\n"); + +#ifndef HAVE_STRERROR_R if (strerror_p1 != strerror_p2) strerror_threadsafe = true; +#endif +#ifndef HAVE_GETPWUID_R if (passwd_p1 != passwd_p2) getpwuid_threadsafe = true; +#endif +#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R) if (hostent_p1 != hostent_p2) gethostbyname_threadsafe = true; +#endif pthread_mutex_unlock(&init_mutex); /* let children exit */ - + pthread_join(thread1, NULL); /* clean up children */ pthread_join(thread2, NULL); - printf("\n"); - #ifdef HAVE_STRERROR_R - printf("Your system has sterror_r(), so it doesn't use strerror().\n"); + printf("Your system has sterror_r(); it does not need strerror().\n"); #else printf("Your system uses strerror() which is "); if (strerror_threadsafe) printf("thread-safe.\n"); else { - platform_is_threadsafe = false; printf("not thread-safe.\n"); + platform_is_threadsafe = false; } #endif #ifdef HAVE_GETPWUID_R - printf("Your system has getpwuid_r(), so it doesn't use getpwuid().\n"); + printf("Your system has getpwuid_r(); it does not need getpwuid().\n"); #else printf("Your system uses getpwuid() which is "); if (getpwuid_threadsafe) printf("thread-safe.\n"); else { - platform_is_threadsafe = false; printf("not thread-safe.\n"); + platform_is_threadsafe = false; } #endif #ifdef HAVE_GETADDRINFO - printf("Your system has getaddrinfo(), so it doesn't use gethostbyname()\n" - " or gethostbyname_r().\n"); + printf("Your system has getaddrinfo(); it does not need gethostbyname()\n" + " or gethostbyname_r().\n"); #else #ifdef HAVE_GETHOSTBYNAME_R - printf("Your system has gethostbyname_r(), so it doesn't use gethostbyname().\n"); + printf("Your system has gethostbyname_r(); it does not need gethostbyname().\n"); #else printf("Your system uses gethostbyname which is "); if (gethostbyname_threadsafe) printf("thread-safe.\n"); else { - platform_is_threadsafe = false; printf("not thread-safe.\n"); + platform_is_threadsafe = false; } #endif #endif - if (!platform_is_threadsafe) + if (platform_is_threadsafe) { - printf("\n** YOUR PLATFORM IS NOT THREADSAFE **\n"); - return 1; + printf("\nYour platform is thread-safe.\n"); + return 0; } else { - printf("\nYOUR PLATFORM IS THREADSAFE\n"); - return 0; + printf("\n** YOUR PLATFORM IS NOT THREAD-SAFE. **\n"); + return 1; } } -void func_call_1(void) { - void *p; - +void +func_call_1(void) +{ +#if !defined(HAVE_GETPWUID_R) || \ + (!defined(HAVE_GETADDRINFO) && \ + !defined(HAVE_GETHOSTBYNAME_R)) + void *p; +#endif + unlink("/tmp/thread_test.1"); /* create, then try to fail on exclusive create open */ if (open("/tmp/thread_test.1", O_RDWR | O_CREAT, 0600) < 0 || open("/tmp/thread_test.1", O_RDWR | O_CREAT | O_EXCL, 0600) >= 0) { - fprintf(stderr, "Could not create file in /tmp or\n"); - fprintf(stderr, "could not generate failure for create file in /tmp, exiting\n"); - exit(1); + fprintf(stderr, "Could not create file in /tmp or\n"); + fprintf(stderr, "could not generate failure for create file in /tmp, exiting\n"); + exit(1); } + /* - * Wait for other thread to set errno. - * We can't use thread-specific locking here because it might - * affect errno. + * Wait for other thread to set errno. We can't use thread-specific + * locking here because it might affect errno. */ errno1_set = 1; while (errno2_set == 0) sched_yield(); if (errno != EEXIST) { - fprintf(stderr, "errno not thread-safe; exiting\n"); - unlink("/tmp/thread_test.1"); - exit(1); + fprintf(stderr, "errno not thread-safe; exiting\n"); + unlink("/tmp/thread_test.1"); + exit(1); } unlink("/tmp/thread_test.1"); - - 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. - */ +#ifndef HAVE_STRERROR_R + 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. + */ +#endif + +#ifndef HAVE_GETPWUID_R passwd_p1 = getpwuid(0); p = getpwuid(1); if (passwd_p1 != p) { printf("Your getpwuid() changes the static memory area between calls\n"); - passwd_p1 = NULL; /* force thread-safe failure report */ + passwd_p1 = NULL; /* force thread-safe failure report */ } +#endif +#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R) /* threads do this in opposite order */ hostent_p1 = gethostbyname(myhostname); p = gethostbyname("localhost"); if (hostent_p1 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); - hostent_p1 = NULL; /* force thread-safe failure report */ + hostent_p1 = NULL; /* force thread-safe failure report */ } +#endif thread1_done = 1; pthread_mutex_lock(&init_mutex); /* wait for parent to test */ @@ -222,54 +244,68 @@ void func_call_1(void) { } -void func_call_2(void) { - void *p; +void +func_call_2(void) +{ +#if !defined(HAVE_GETPWUID_R) || \ + (!defined(HAVE_GETADDRINFO) && \ + !defined(HAVE_GETHOSTBYNAME_R)) + void *p; +#endif unlink("/tmp/thread_test.2"); /* open non-existant file */ if (open("/tmp/thread_test.2", O_RDONLY, 0600) >= 0) { - fprintf(stderr, "Read-only open succeeded without create, exiting\n"); - exit(1); + fprintf(stderr, "Read-only open succeeded without create, exiting\n"); + exit(1); } + /* - * Wait for other thread to set errno. - * We can't use thread-specific locking here because it might - * affect errno. + * Wait for other thread to set errno. We can't use thread-specific + * locking here because it might affect errno. */ errno2_set = 1; while (errno1_set == 0) sched_yield(); if (errno != ENOENT) { - fprintf(stderr, "errno not thread-safe; exiting\n"); - unlink("/tmp/thread_test.A"); - exit(1); + fprintf(stderr, "errno not thread-safe; exiting\n"); + unlink("/tmp/thread_test.A"); + exit(1); } unlink("/tmp/thread_test.2"); - - 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. - */ +#ifndef HAVE_STRERROR_R + 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. + */ +#endif + +#ifndef HAVE_GETPWUID_R passwd_p2 = getpwuid(2); p = getpwuid(3); if (passwd_p2 != p) { printf("Your getpwuid() changes the static memory area between calls\n"); - passwd_p2 = NULL; /* force thread-safe failure report */ + passwd_p2 = NULL; /* force thread-safe failure report */ } +#endif +#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R) /* threads do this in opposite order */ hostent_p2 = gethostbyname("localhost"); p = gethostbyname(myhostname); if (hostent_p2 != p) { printf("Your gethostbyname() changes the static memory area between calls\n"); - hostent_p2 = NULL; /* force thread-safe failure report */ + hostent_p2 = NULL; /* force thread-safe failure report */ } +#endif thread2_done = 1; pthread_mutex_lock(&init_mutex); /* wait for parent to test */