|
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 */ |
|