Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
postgres-lambda-diff
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Jakob Huber
postgres-lambda-diff
Commits
66b42d30
Commit
66b42d30
authored
21 years ago
by
Bruce Momjian
Browse files
Options
Downloads
Patches
Plain Diff
Improve thread test program. Test only functions that need testing.
parent
fc7fd501
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/tools/thread/Makefile
+1
-8
1 addition, 8 deletions
src/tools/thread/Makefile
src/tools/thread/thread_test.c
+119
-83
119 additions, 83 deletions
src/tools/thread/thread_test.c
with
120 additions
and
91 deletions
src/tools/thread/Makefile
+
1
−
8
View file @
66b42d30
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
#
#
# Copyright (C) 2003 by PostgreSQL Global Development Team
# Copyright (C) 2003 by PostgreSQL Global Development Team
#
#
# $PostgreSQL: pgsql/src/tools/thread/Makefile,v 1.
4
2004/04/23
18:1
5:5
5
momjian Exp $
# $PostgreSQL: pgsql/src/tools/thread/Makefile,v 1.
5
2004/04/23
20:3
5:5
0
momjian Exp $
#
#
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
...
@@ -12,13 +12,6 @@ subdir = tools/thread
...
@@ -12,13 +12,6 @@ subdir = tools/thread
top_builddir
=
../../..
top_builddir
=
../../..
include
$(top_builddir)/src/Makefile.global
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
)
override
CFLAGS
+=
$(
PTHREAD_CFLAGS
)
LDFLAGS
+=
$(
PTHREAD_LIBS
)
LDFLAGS
+=
$(
PTHREAD_LIBS
)
...
...
This diff is collapsed.
Click to expand it.
src/tools/thread/thread_test.c
+
119
−
83
View file @
66b42d30
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
*
*
* test_thread_funcs.c
* test_thread_funcs.c
*
libc thread test program
*
libc thread test program
*
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.2
0
2004/04/23
18:1
5:5
5
momjian Exp $
* $PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.2
1
2004/04/23
20:3
5:5
0
momjian Exp $
*
*
* This program tests to see if your standard libc functions use
* This program tests to see if your standard libc functions use
* pthread_setspecific()/pthread_getspecific() to be thread-safe.
* pthread_setspecific()/pthread_getspecific() to be thread-safe.
...
@@ -33,188 +33,210 @@
...
@@ -33,188 +33,210 @@
#include
"postgres.h"
#include
"postgres.h"
void
func_call_1
(
void
);
void
func_call_1
(
void
);
void
func_call_2
(
void
);
void
func_call_2
(
void
);
char
myhostname
[
MAXHOSTNAMELEN
];
pthread_mutex_t
init_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
volatile
int
errno1_set
=
0
;
volatile
int
errno2_set
=
0
;
volatile
int
thread1_done
=
0
;
volatile
int
thread1_done
=
0
;
volatile
int
thread2_done
=
0
;
volatile
int
thread2_done
=
0
;
char
*
strerror_p1
;
volatile
int
errno1_set
=
0
;
char
*
strerror_p2
;
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_p1
;
struct
passwd
*
passwd_p2
;
struct
passwd
*
passwd_p2
;
bool
getpwuid_threadsafe
=
false
;
#endif
#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
struct
hostent
*
hostent_p1
;
struct
hostent
*
hostent_p1
;
struct
hostent
*
hostent_p2
;
struct
hostent
*
hostent_p2
;
char
myhostname
[
MAXHOSTNAMELEN
];
bool
gethostbyname_threadsafe
=
false
;
#endif
bool
gethostbyname_threadsafe
=
false
;
bool
platform_is_threadsafe
=
true
;
bool
getpwuid_threadsafe
=
false
;
bool
strerror_threadsafe
=
false
;
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
,
pthread_t
thread1
,
thread2
;
thread2
;
if
(
argc
>
1
)
if
(
argc
>
1
)
{
{
fprintf
(
stderr
,
"Usage: %s
\n
"
,
argv
[
0
]);
fprintf
(
stderr
,
"Usage: %s
\n
"
,
argv
[
0
]);
return
1
;
return
1
;
}
}
#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
if
(
gethostname
(
myhostname
,
MAXHOSTNAMELEN
)
!=
0
)
if
(
gethostname
(
myhostname
,
MAXHOSTNAMELEN
)
!=
0
)
{
{
fprintf
(
stderr
,
"can not get local hostname, exiting
\n
"
);
fprintf
(
stderr
,
"can not get local hostname, exiting
\n
"
);
exit
(
1
);
exit
(
1
);
}
}
#endif
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
"
);
/* Hold lock until we are ready for the child threads to exit. */
/* Hold lock until we are ready for the child threads to exit. */
pthread_mutex_lock
(
&
init_mutex
);
pthread_mutex_lock
(
&
init_mutex
);
pthread_create
(
&
thread1
,
NULL
,
(
void
*
(
*
)(
void
*
))
func_call_1
,
NULL
);
pthread_create
(
&
thread1
,
NULL
,
(
void
*
(
*
)
(
void
*
))
func_call_1
,
NULL
);
pthread_create
(
&
thread2
,
NULL
,
(
void
*
(
*
)(
void
*
))
func_call_2
,
NULL
);
pthread_create
(
&
thread2
,
NULL
,
(
void
*
(
*
)
(
void
*
))
func_call_2
,
NULL
);
while
(
thread1_done
==
0
||
thread2_done
==
0
)
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
)
if
(
strerror_p1
!=
strerror_p2
)
strerror_threadsafe
=
true
;
strerror_threadsafe
=
true
;
#endif
#ifndef HAVE_GETPWUID_R
if
(
passwd_p1
!=
passwd_p2
)
if
(
passwd_p1
!=
passwd_p2
)
getpwuid_threadsafe
=
true
;
getpwuid_threadsafe
=
true
;
#endif
#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETHOSTBYNAME_R)
if
(
hostent_p1
!=
hostent_p2
)
if
(
hostent_p1
!=
hostent_p2
)
gethostbyname_threadsafe
=
true
;
gethostbyname_threadsafe
=
true
;
#endif
pthread_mutex_unlock
(
&
init_mutex
);
/* let children exit */
pthread_mutex_unlock
(
&
init_mutex
);
/* let children exit */
pthread_join
(
thread1
,
NULL
);
/* clean up children */
pthread_join
(
thread1
,
NULL
);
/* clean up children */
pthread_join
(
thread2
,
NULL
);
pthread_join
(
thread2
,
NULL
);
printf
(
"
\n
"
);
#ifdef HAVE_STRERROR_R
#ifdef HAVE_STRERROR_R
printf
(
"Your system has sterror_r()
, so
it does
n't use
strerror().
\n
"
);
printf
(
"Your system has sterror_r()
;
it does
not need
strerror().
\n
"
);
#else
#else
printf
(
"Your system uses strerror() which is "
);
printf
(
"Your system uses strerror() which is "
);
if
(
strerror_threadsafe
)
if
(
strerror_threadsafe
)
printf
(
"thread-safe.
\n
"
);
printf
(
"thread-safe.
\n
"
);
else
else
{
{
platform_is_threadsafe
=
false
;
printf
(
"not thread-safe.
\n
"
);
printf
(
"not thread-safe.
\n
"
);
platform_is_threadsafe
=
false
;
}
}
#endif
#endif
#ifdef HAVE_GETPWUID_R
#ifdef HAVE_GETPWUID_R
printf
(
"Your system has getpwuid_r()
, so
it does
n't use
getpwuid().
\n
"
);
printf
(
"Your system has getpwuid_r()
;
it does
not need
getpwuid().
\n
"
);
#else
#else
printf
(
"Your system uses getpwuid() which is "
);
printf
(
"Your system uses getpwuid() which is "
);
if
(
getpwuid_threadsafe
)
if
(
getpwuid_threadsafe
)
printf
(
"thread-safe.
\n
"
);
printf
(
"thread-safe.
\n
"
);
else
else
{
{
platform_is_threadsafe
=
false
;
printf
(
"not thread-safe.
\n
"
);
printf
(
"not thread-safe.
\n
"
);
platform_is_threadsafe
=
false
;
}
}
#endif
#endif
#ifdef HAVE_GETADDRINFO
#ifdef HAVE_GETADDRINFO
printf
(
"Your system has getaddrinfo()
, so
it does
n't use
gethostbyname()
\n
"
printf
(
"Your system has getaddrinfo()
;
it does
not need
gethostbyname()
\n
"
" or gethostbyname_r().
\n
"
);
" or gethostbyname_r().
\n
"
);
#else
#else
#ifdef HAVE_GETHOSTBYNAME_R
#ifdef HAVE_GETHOSTBYNAME_R
printf
(
"Your system has gethostbyname_r()
, so
it does
n't use
gethostbyname().
\n
"
);
printf
(
"Your system has gethostbyname_r()
;
it does
not need
gethostbyname().
\n
"
);
#else
#else
printf
(
"Your system uses gethostbyname which is "
);
printf
(
"Your system uses gethostbyname which is "
);
if
(
gethostbyname_threadsafe
)
if
(
gethostbyname_threadsafe
)
printf
(
"thread-safe.
\n
"
);
printf
(
"thread-safe.
\n
"
);
else
else
{
{
platform_is_threadsafe
=
false
;
printf
(
"not thread-safe.
\n
"
);
printf
(
"not thread-safe.
\n
"
);
platform_is_threadsafe
=
false
;
}
}
#endif
#endif
#endif
#endif
if
(
!
platform_is_threadsafe
)
if
(
platform_is_threadsafe
)
{
{
printf
(
"
\n
** YOUR PLATFORM IS NOT THREADSAFE **
\n
"
);
printf
(
"
\n
Your platform is thread-safe.
\n
"
);
return
1
;
return
0
;
}
}
else
else
{
{
printf
(
"
\n
YOUR PLATFORM IS THREADSAFE
\n
"
);
printf
(
"
\n
**
YOUR PLATFORM IS
NOT
THREAD
-
SAFE
. **
\n
"
);
return
0
;
return
1
;
}
}
}
}
void
func_call_1
(
void
)
{
void
void
*
p
;
func_call_1
(
void
)
{
#if !defined(HAVE_GETPWUID_R) || \
(!defined(HAVE_GETADDRINFO) && \
!defined(HAVE_GETHOSTBYNAME_R))
void
*
p
;
#endif
unlink
(
"/tmp/thread_test.1"
);
unlink
(
"/tmp/thread_test.1"
);
/* create, then try to fail on exclusive create open */
/* create, then try to fail on exclusive create open */
if
(
open
(
"/tmp/thread_test.1"
,
O_RDWR
|
O_CREAT
,
0600
)
<
0
||
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
)
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 create file in /tmp or
\n
"
);
fprintf
(
stderr
,
"could not generate failure for create file in /tmp, exiting
\n
"
);
fprintf
(
stderr
,
"could not generate failure for create file in /tmp, exiting
\n
"
);
exit
(
1
);
exit
(
1
);
}
}
/*
/*
* Wait for other thread to set errno.
* Wait for other thread to set errno. We can't use thread-specific
* We can't use thread-specific locking here because it might
* locking here because it might affect errno.
* affect errno.
*/
*/
errno1_set
=
1
;
errno1_set
=
1
;
while
(
errno2_set
==
0
)
while
(
errno2_set
==
0
)
sched_yield
();
sched_yield
();
if
(
errno
!=
EEXIST
)
if
(
errno
!=
EEXIST
)
{
{
fprintf
(
stderr
,
"errno not thread-safe; exiting
\n
"
);
fprintf
(
stderr
,
"errno not thread-safe; exiting
\n
"
);
unlink
(
"/tmp/thread_test.1"
);
unlink
(
"/tmp/thread_test.1"
);
exit
(
1
);
exit
(
1
);
}
}
unlink
(
"/tmp/thread_test.1"
);
unlink
(
"/tmp/thread_test.1"
);
#ifndef HAVE_STRERROR_R
strerror_p1
=
strerror
(
EACCES
);
strerror_p1
=
strerror
(
EACCES
);
/*
/*
* If strerror() uses sys_errlist, the pointer might change for different
* If strerror() uses sys_errlist, the pointer might change for
* errno values, so we don't check to see if it varies within the thread.
* 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
);
passwd_p1
=
getpwuid
(
0
);
p
=
getpwuid
(
1
);
p
=
getpwuid
(
1
);
if
(
passwd_p1
!=
p
)
if
(
passwd_p1
!=
p
)
{
{
printf
(
"Your getpwuid() changes the static memory area between calls
\n
"
);
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 */
/* threads do this in opposite order */
hostent_p1
=
gethostbyname
(
myhostname
);
hostent_p1
=
gethostbyname
(
myhostname
);
p
=
gethostbyname
(
"localhost"
);
p
=
gethostbyname
(
"localhost"
);
if
(
hostent_p1
!=
p
)
if
(
hostent_p1
!=
p
)
{
{
printf
(
"Your gethostbyname() changes the static memory area between calls
\n
"
);
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
;
thread1_done
=
1
;
pthread_mutex_lock
(
&
init_mutex
);
/* wait for parent to test */
pthread_mutex_lock
(
&
init_mutex
);
/* wait for parent to test */
...
@@ -222,54 +244,68 @@ void func_call_1(void) {
...
@@ -222,54 +244,68 @@ void func_call_1(void) {
}
}
void
func_call_2
(
void
)
{
void
void
*
p
;
func_call_2
(
void
)
{
#if !defined(HAVE_GETPWUID_R) || \
(!defined(HAVE_GETADDRINFO) && \
!defined(HAVE_GETHOSTBYNAME_R))
void
*
p
;
#endif
unlink
(
"/tmp/thread_test.2"
);
unlink
(
"/tmp/thread_test.2"
);
/* open non-existant file */
/* open non-existant file */
if
(
open
(
"/tmp/thread_test.2"
,
O_RDONLY
,
0600
)
>=
0
)
if
(
open
(
"/tmp/thread_test.2"
,
O_RDONLY
,
0600
)
>=
0
)
{
{
fprintf
(
stderr
,
"Read-only open succeeded without create, exiting
\n
"
);
fprintf
(
stderr
,
"Read-only open succeeded without create, exiting
\n
"
);
exit
(
1
);
exit
(
1
);
}
}
/*
/*
* Wait for other thread to set errno.
* Wait for other thread to set errno. We can't use thread-specific
* We can't use thread-specific locking here because it might
* locking here because it might affect errno.
* affect errno.
*/
*/
errno2_set
=
1
;
errno2_set
=
1
;
while
(
errno1_set
==
0
)
while
(
errno1_set
==
0
)
sched_yield
();
sched_yield
();
if
(
errno
!=
ENOENT
)
if
(
errno
!=
ENOENT
)
{
{
fprintf
(
stderr
,
"errno not thread-safe; exiting
\n
"
);
fprintf
(
stderr
,
"errno not thread-safe; exiting
\n
"
);
unlink
(
"/tmp/thread_test.A"
);
unlink
(
"/tmp/thread_test.A"
);
exit
(
1
);
exit
(
1
);
}
}
unlink
(
"/tmp/thread_test.2"
);
unlink
(
"/tmp/thread_test.2"
);
#ifndef HAVE_STRERROR_R
strerror_p2
=
strerror
(
EINVAL
);
strerror_p2
=
strerror
(
EINVAL
);
/*
/*
* If strerror() uses sys_errlist, the pointer might change for different
* If strerror() uses sys_errlist, the pointer might change for
* errno values, so we don't check to see if it varies within the thread.
* 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
);
passwd_p2
=
getpwuid
(
2
);
p
=
getpwuid
(
3
);
p
=
getpwuid
(
3
);
if
(
passwd_p2
!=
p
)
if
(
passwd_p2
!=
p
)
{
{
printf
(
"Your getpwuid() changes the static memory area between calls
\n
"
);
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 */
/* threads do this in opposite order */
hostent_p2
=
gethostbyname
(
"localhost"
);
hostent_p2
=
gethostbyname
(
"localhost"
);
p
=
gethostbyname
(
myhostname
);
p
=
gethostbyname
(
myhostname
);
if
(
hostent_p2
!=
p
)
if
(
hostent_p2
!=
p
)
{
{
printf
(
"Your gethostbyname() changes the static memory area between calls
\n
"
);
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
;
thread2_done
=
1
;
pthread_mutex_lock
(
&
init_mutex
);
/* wait for parent to test */
pthread_mutex_lock
(
&
init_mutex
);
/* wait for parent to test */
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment