|
1 | 1 | /*-------------------------------------------------------------------------
|
2 | 2 | *
|
3 | 3 | * test_thread_funcs.c
|
4 |
| - *libc thread test program |
| 4 | + *libc thread test program |
5 | 5 | *
|
6 | 6 | * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
7 | 7 | * Portions Copyright (c) 1994, Regents of the University of California
|
8 | 8 | *
|
9 |
| - *$PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.20 2004/04/2318:15:55 momjian Exp $ |
| 9 | + *$PostgreSQL: pgsql/src/tools/thread/thread_test.c,v 1.21 2004/04/2320:35:50 momjian Exp $ |
10 | 10 | *
|
11 | 11 | *This program tests to see if your standard libc functions use
|
12 | 12 | *pthread_setspecific()/pthread_getspecific() to be thread-safe.
|
|
33 | 33 |
|
34 | 34 | #include"postgres.h"
|
35 | 35 |
|
36 |
| -voidfunc_call_1(void); |
37 |
| -voidfunc_call_2(void); |
| 36 | +voidfunc_call_1(void); |
| 37 | +voidfunc_call_2(void); |
38 | 38 |
|
39 |
| -charmyhostname[MAXHOSTNAMELEN]; |
40 |
| - |
41 |
| -volatileinterrno1_set=0; |
42 |
| -volatileinterrno2_set=0; |
| 39 | +pthread_mutex_tinit_mutex=PTHREAD_MUTEX_INITIALIZER; |
43 | 40 |
|
44 | 41 | volatileintthread1_done=0;
|
45 | 42 | volatileintthread2_done=0;
|
46 | 43 |
|
47 |
| -char*strerror_p1; |
48 |
| -char*strerror_p2; |
| 44 | +volatileinterrno1_set=0; |
| 45 | +volatileinterrno2_set=0; |
49 | 46 |
|
| 47 | +#ifndefHAVE_STRERROR_R |
| 48 | +char*strerror_p1; |
| 49 | +char*strerror_p2; |
| 50 | +boolstrerror_threadsafe= false; |
| 51 | +#endif |
| 52 | + |
| 53 | +#ifndefHAVE_GETPWUID_R |
50 | 54 | structpasswd*passwd_p1;
|
51 | 55 | structpasswd*passwd_p2;
|
| 56 | +boolgetpwuid_threadsafe= false; |
| 57 | +#endif |
52 | 58 |
|
| 59 | +#if !defined(HAVE_GETADDRINFO)&& !defined(HAVE_GETHOSTBYNAME_R) |
53 | 60 | structhostent*hostent_p1;
|
54 | 61 | structhostent*hostent_p2;
|
| 62 | +charmyhostname[MAXHOSTNAMELEN]; |
| 63 | +boolgethostbyname_threadsafe= false; |
| 64 | +#endif |
55 | 65 |
|
56 |
| -boolgethostbyname_threadsafe= false; |
57 |
| -boolgetpwuid_threadsafe= false; |
58 |
| -boolstrerror_threadsafe= false; |
59 |
| -boolplatform_is_threadsafe= true; |
60 |
| - |
61 |
| -pthread_mutex_tinit_mutex=PTHREAD_MUTEX_INITIALIZER; |
| 66 | +boolplatform_is_threadsafe= true; |
62 | 67 |
|
63 |
| -intmain(intargc,char*argv[]) |
| 68 | +int |
| 69 | +main(intargc,char*argv[]) |
64 | 70 | {
|
65 |
| -pthread_tthread1, |
66 |
| -thread2; |
| 71 | +pthread_tthread1, |
| 72 | +thread2; |
67 | 73 |
|
68 | 74 | if (argc>1)
|
69 | 75 | {
|
70 |
| -fprintf(stderr,"Usage: %s\n",argv[0]); |
71 |
| -return1; |
| 76 | +fprintf(stderr,"Usage: %s\n",argv[0]); |
| 77 | +return1; |
72 | 78 | }
|
73 | 79 |
|
| 80 | +#if !defined(HAVE_GETADDRINFO)&& !defined(HAVE_GETHOSTBYNAME_R) |
74 | 81 | if (gethostname(myhostname,MAXHOSTNAMELEN)!=0)
|
75 | 82 | {
|
76 |
| -fprintf(stderr,"can not get local hostname, exiting\n"); |
77 |
| -exit(1); |
| 83 | +fprintf(stderr,"can not get local hostname, exiting\n"); |
| 84 | +exit(1); |
78 | 85 | }
|
79 |
| - |
80 |
| -printf("\ |
81 |
| -Make sure you have added any needed 'PTHREAD_CFLAGS' and 'PTHREAD_LIBS'\n\ |
82 |
| -defines to your template/$port file before compiling this program.\n\n" |
83 |
| -); |
| 86 | +#endif |
84 | 87 |
|
85 | 88 | /* Hold lock until we are ready for the child threads to exit. */
|
86 |
| -pthread_mutex_lock(&init_mutex); |
87 |
| -
|
88 |
| -pthread_create(&thread1,NULL, (void*(*)(void*))func_call_1,NULL); |
89 |
| -pthread_create(&thread2,NULL, (void*(*)(void*))func_call_2,NULL); |
| 89 | +pthread_mutex_lock(&init_mutex); |
| 90 | + |
| 91 | +pthread_create(&thread1,NULL, (void*(*)(void*))func_call_1,NULL); |
| 92 | +pthread_create(&thread2,NULL, (void*(*)(void*))func_call_2,NULL); |
90 | 93 |
|
91 | 94 | while (thread1_done==0||thread2_done==0)
|
92 |
| -sched_yield();/* if this is a portability problem, remove it */ |
| 95 | +sched_yield();/* if this is a portability problem, |
| 96 | + * remove it */ |
93 | 97 |
|
94 |
| -fprintf(stderr,"errno is thread-safe\n"); |
95 |
| - |
| 98 | +fprintf(stderr,"Your errno is thread-safe.\n"); |
| 99 | + |
| 100 | +#ifndefHAVE_STRERROR_R |
96 | 101 | if (strerror_p1!=strerror_p2)
|
97 | 102 | strerror_threadsafe= true;
|
| 103 | +#endif |
98 | 104 |
|
| 105 | +#ifndefHAVE_GETPWUID_R |
99 | 106 | if (passwd_p1!=passwd_p2)
|
100 | 107 | getpwuid_threadsafe= true;
|
| 108 | +#endif |
101 | 109 |
|
| 110 | +#if !defined(HAVE_GETADDRINFO)&& !defined(HAVE_GETHOSTBYNAME_R) |
102 | 111 | if (hostent_p1!=hostent_p2)
|
103 | 112 | gethostbyname_threadsafe= true;
|
| 113 | +#endif |
104 | 114 |
|
105 | 115 | pthread_mutex_unlock(&init_mutex);/* let children exit */
|
106 |
| -
|
| 116 | + |
107 | 117 | pthread_join(thread1,NULL);/* clean up children */
|
108 | 118 | pthread_join(thread2,NULL);
|
109 | 119 |
|
110 |
| -printf("\n"); |
111 |
| - |
112 | 120 | #ifdefHAVE_STRERROR_R
|
113 |
| -printf("Your system has sterror_r(), so itdoesn't use strerror().\n"); |
| 121 | +printf("Your system has sterror_r(); itdoes not need strerror().\n"); |
114 | 122 | #else
|
115 | 123 | printf("Your system uses strerror() which is ");
|
116 | 124 | if (strerror_threadsafe)
|
117 | 125 | printf("thread-safe.\n");
|
118 | 126 | else
|
119 | 127 | {
|
120 |
| -platform_is_threadsafe= false; |
121 | 128 | printf("not thread-safe.\n");
|
| 129 | +platform_is_threadsafe= false; |
122 | 130 | }
|
123 | 131 | #endif
|
124 | 132 |
|
125 | 133 | #ifdefHAVE_GETPWUID_R
|
126 |
| -printf("Your system has getpwuid_r(), so itdoesn't use getpwuid().\n"); |
| 134 | +printf("Your system has getpwuid_r(); itdoes not need getpwuid().\n"); |
127 | 135 | #else
|
128 | 136 | printf("Your system uses getpwuid() which is ");
|
129 | 137 | if (getpwuid_threadsafe)
|
130 | 138 | printf("thread-safe.\n");
|
131 | 139 | else
|
132 | 140 | {
|
133 |
| -platform_is_threadsafe= false; |
134 | 141 | printf("not thread-safe.\n");
|
| 142 | +platform_is_threadsafe= false; |
135 | 143 | }
|
136 | 144 | #endif
|
137 | 145 |
|
138 | 146 | #ifdefHAVE_GETADDRINFO
|
139 |
| -printf("Your system has getaddrinfo(), so itdoesn't use gethostbyname()\n" |
140 |
| -" or gethostbyname_r().\n"); |
| 147 | +printf("Your system has getaddrinfo(); itdoes not need gethostbyname()\n" |
| 148 | +" or gethostbyname_r().\n"); |
141 | 149 | #else
|
142 | 150 | #ifdefHAVE_GETHOSTBYNAME_R
|
143 |
| -printf("Your system has gethostbyname_r(), so itdoesn't use gethostbyname().\n"); |
| 151 | +printf("Your system has gethostbyname_r(); itdoes not need gethostbyname().\n"); |
144 | 152 | #else
|
145 | 153 | printf("Your system uses gethostbyname which is ");
|
146 | 154 | if (gethostbyname_threadsafe)
|
147 | 155 | printf("thread-safe.\n");
|
148 | 156 | else
|
149 | 157 | {
|
150 |
| -platform_is_threadsafe= false; |
151 | 158 | printf("not thread-safe.\n");
|
| 159 | +platform_is_threadsafe= false; |
152 | 160 | }
|
153 | 161 | #endif
|
154 | 162 | #endif
|
155 | 163 |
|
156 |
| -if (!platform_is_threadsafe) |
| 164 | +if (platform_is_threadsafe) |
157 | 165 | {
|
158 |
| -printf("\n** YOUR PLATFORM IS NOT THREADSAFE **\n"); |
159 |
| -return1; |
| 166 | +printf("\nYour platform is thread-safe.\n"); |
| 167 | +return0; |
160 | 168 | }
|
161 | 169 | else
|
162 | 170 | {
|
163 |
| -printf("\nYOURPLATFORM ISTHREADSAFE\n"); |
164 |
| -return0; |
| 171 | +printf("\n** YOURPLATFORM ISNOT THREAD-SAFE. **\n"); |
| 172 | +return1; |
165 | 173 | }
|
166 | 174 | }
|
167 | 175 |
|
168 |
| -voidfunc_call_1(void) { |
169 |
| -void*p; |
170 |
| - |
| 176 | +void |
| 177 | +func_call_1(void) |
| 178 | +{ |
| 179 | +#if !defined(HAVE_GETPWUID_R)|| \ |
| 180 | +(!defined(HAVE_GETADDRINFO)&& \ |
| 181 | + !defined(HAVE_GETHOSTBYNAME_R)) |
| 182 | +void*p; |
| 183 | +#endif |
| 184 | + |
171 | 185 | unlink("/tmp/thread_test.1");
|
172 | 186 | /* create, then try to fail on exclusive create open */
|
173 | 187 | if (open("/tmp/thread_test.1",O_RDWR |O_CREAT,0600)<0||
|
174 | 188 | open("/tmp/thread_test.1",O_RDWR |O_CREAT |O_EXCL,0600) >=0)
|
175 | 189 | {
|
176 |
| -fprintf(stderr,"Could not create file in /tmp or\n"); |
177 |
| -fprintf(stderr,"could not generate failure for create file in /tmp, exiting\n"); |
178 |
| -exit(1); |
| 190 | +fprintf(stderr,"Could not create file in /tmp or\n"); |
| 191 | +fprintf(stderr,"could not generate failure for create file in /tmp, exiting\n"); |
| 192 | +exit(1); |
179 | 193 | }
|
| 194 | + |
180 | 195 | /*
|
181 |
| - *Wait for other thread to set errno. |
182 |
| - *We can't use thread-specific locking here because it might |
183 |
| - *affect errno. |
| 196 | + * Wait for other thread to set errno. We can't use thread-specific |
| 197 | + * locking here because it might affect errno. |
184 | 198 | */
|
185 | 199 | errno1_set=1;
|
186 | 200 | while (errno2_set==0)
|
187 | 201 | sched_yield();
|
188 | 202 | if (errno!=EEXIST)
|
189 | 203 | {
|
190 |
| -fprintf(stderr,"errno not thread-safe; exiting\n"); |
191 |
| -unlink("/tmp/thread_test.1"); |
192 |
| -exit(1); |
| 204 | +fprintf(stderr,"errno not thread-safe; exiting\n"); |
| 205 | +unlink("/tmp/thread_test.1"); |
| 206 | +exit(1); |
193 | 207 | }
|
194 | 208 | unlink("/tmp/thread_test.1");
|
195 |
| - |
| 209 | + |
| 210 | +#ifndefHAVE_STRERROR_R |
196 | 211 | strerror_p1=strerror(EACCES);
|
| 212 | + |
197 | 213 | /*
|
198 |
| - *If strerror() uses sys_errlist, the pointer might change for different |
199 |
| - *errno values, so we don't check to see if it varies within the thread. |
| 214 | + * If strerror() uses sys_errlist, the pointer might change for |
| 215 | + * different errno values, so we don't check to see if it varies |
| 216 | + * within the thread. |
200 | 217 | */
|
| 218 | +#endif |
201 | 219 |
|
| 220 | +#ifndefHAVE_GETPWUID_R |
202 | 221 | passwd_p1=getpwuid(0);
|
203 | 222 | p=getpwuid(1);
|
204 | 223 | if (passwd_p1!=p)
|
205 | 224 | {
|
206 | 225 | printf("Your getpwuid() changes the static memory area between calls\n");
|
207 |
| -passwd_p1=NULL;/* force thread-safe failure report */ |
| 226 | +passwd_p1=NULL;/* force thread-safe failure report */ |
208 | 227 | }
|
| 228 | +#endif |
209 | 229 |
|
| 230 | +#if !defined(HAVE_GETADDRINFO)&& !defined(HAVE_GETHOSTBYNAME_R) |
210 | 231 | /* threads do this in opposite order */
|
211 | 232 | hostent_p1=gethostbyname(myhostname);
|
212 | 233 | p=gethostbyname("localhost");
|
213 | 234 | if (hostent_p1!=p)
|
214 | 235 | {
|
215 | 236 | printf("Your gethostbyname() changes the static memory area between calls\n");
|
216 |
| -hostent_p1=NULL;/* force thread-safe failure report */ |
| 237 | +hostent_p1=NULL;/* force thread-safe failure report */ |
217 | 238 | }
|
| 239 | +#endif |
218 | 240 |
|
219 | 241 | thread1_done=1;
|
220 | 242 | pthread_mutex_lock(&init_mutex);/* wait for parent to test */
|
221 | 243 | pthread_mutex_unlock(&init_mutex);
|
222 | 244 | }
|
223 | 245 |
|
224 | 246 |
|
225 |
| -voidfunc_call_2(void) { |
226 |
| -void*p; |
| 247 | +void |
| 248 | +func_call_2(void) |
| 249 | +{ |
| 250 | +#if !defined(HAVE_GETPWUID_R)|| \ |
| 251 | +(!defined(HAVE_GETADDRINFO)&& \ |
| 252 | + !defined(HAVE_GETHOSTBYNAME_R)) |
| 253 | +void*p; |
| 254 | +#endif |
227 | 255 |
|
228 | 256 | unlink("/tmp/thread_test.2");
|
229 | 257 | /* open non-existant file */
|
230 | 258 | if (open("/tmp/thread_test.2",O_RDONLY,0600) >=0)
|
231 | 259 | {
|
232 |
| -fprintf(stderr,"Read-only open succeeded without create, exiting\n"); |
233 |
| -exit(1); |
| 260 | +fprintf(stderr,"Read-only open succeeded without create, exiting\n"); |
| 261 | +exit(1); |
234 | 262 | }
|
| 263 | + |
235 | 264 | /*
|
236 |
| - *Wait for other thread to set errno. |
237 |
| - *We can't use thread-specific locking here because it might |
238 |
| - *affect errno. |
| 265 | + * Wait for other thread to set errno. We can't use thread-specific |
| 266 | + * locking here because it might affect errno. |
239 | 267 | */
|
240 | 268 | errno2_set=1;
|
241 | 269 | while (errno1_set==0)
|
242 | 270 | sched_yield();
|
243 | 271 | if (errno!=ENOENT)
|
244 | 272 | {
|
245 |
| -fprintf(stderr,"errno not thread-safe; exiting\n"); |
246 |
| -unlink("/tmp/thread_test.A"); |
247 |
| -exit(1); |
| 273 | +fprintf(stderr,"errno not thread-safe; exiting\n"); |
| 274 | +unlink("/tmp/thread_test.A"); |
| 275 | +exit(1); |
248 | 276 | }
|
249 | 277 | unlink("/tmp/thread_test.2");
|
250 |
| - |
| 278 | + |
| 279 | +#ifndefHAVE_STRERROR_R |
251 | 280 | strerror_p2=strerror(EINVAL);
|
| 281 | + |
252 | 282 | /*
|
253 |
| - *If strerror() uses sys_errlist, the pointer might change for different |
254 |
| - *errno values, so we don't check to see if it varies within the thread. |
| 283 | + * If strerror() uses sys_errlist, the pointer might change for |
| 284 | + * different errno values, so we don't check to see if it varies |
| 285 | + * within the thread. |
255 | 286 | */
|
| 287 | +#endif |
256 | 288 |
|
| 289 | +#ifndefHAVE_GETPWUID_R |
257 | 290 | passwd_p2=getpwuid(2);
|
258 | 291 | p=getpwuid(3);
|
259 | 292 | if (passwd_p2!=p)
|
260 | 293 | {
|
261 | 294 | printf("Your getpwuid() changes the static memory area between calls\n");
|
262 |
| -passwd_p2=NULL;/* force thread-safe failure report */ |
| 295 | +passwd_p2=NULL;/* force thread-safe failure report */ |
263 | 296 | }
|
| 297 | +#endif |
264 | 298 |
|
| 299 | +#if !defined(HAVE_GETADDRINFO)&& !defined(HAVE_GETHOSTBYNAME_R) |
265 | 300 | /* threads do this in opposite order */
|
266 | 301 | hostent_p2=gethostbyname("localhost");
|
267 | 302 | p=gethostbyname(myhostname);
|
268 | 303 | if (hostent_p2!=p)
|
269 | 304 | {
|
270 | 305 | printf("Your gethostbyname() changes the static memory area between calls\n");
|
271 |
| -hostent_p2=NULL;/* force thread-safe failure report */ |
| 306 | +hostent_p2=NULL;/* force thread-safe failure report */ |
272 | 307 | }
|
| 308 | +#endif |
273 | 309 |
|
274 | 310 | thread2_done=1;
|
275 | 311 | pthread_mutex_lock(&init_mutex);/* wait for parent to test */
|
|