xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/thr_posix.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: thr_posix.c,v 1.2 2021/08/14 16:14:56 christos Exp $	*/
2 
3 /* thr_posix.c - wrapper around posix and posixish thread implementations.  */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 
20 #include <sys/cdefs.h>
21 __RCSID("$NetBSD: thr_posix.c,v 1.2 2021/08/14 16:14:56 christos Exp $");
22 
23 #include "portable.h"
24 
25 #if defined( HAVE_PTHREADS )
26 
27 #ifdef __GLIBC__
28 #undef _FEATURES_H
29 #define _XOPEN_SOURCE 500		/* For pthread_setconcurrency() on glibc */
30 #endif
31 
32 #include <ac/errno.h>
33 
34 #ifdef REPLACE_BROKEN_YIELD
35 #ifndef HAVE_NANOSLEEP
36 #include <ac/socket.h>
37 #endif
38 #include <ac/time.h>
39 #endif
40 
41 #include "ldap_pvt_thread.h" /* Get the thread interface */
42 #define LDAP_THREAD_IMPLEMENTATION
43 #define LDAP_THREAD_RDWR_IMPLEMENTATION
44 #include "ldap_thr_debug.h"	 /* May rename the symbols defined below */
45 #include <signal.h>			 /* For pthread_kill() */
46 
47 extern int ldap_int_stackguard;
48 
49 #if HAVE_PTHREADS < 6
50 #  define LDAP_INT_THREAD_ATTR_DEFAULT		pthread_attr_default
51 #  define LDAP_INT_THREAD_CONDATTR_DEFAULT	pthread_condattr_default
52 #  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT	pthread_mutexattr_default
53 #else
54 #  define LDAP_INT_THREAD_ATTR_DEFAULT		NULL
55 #  define LDAP_INT_THREAD_CONDATTR_DEFAULT	NULL
56 #  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT NULL
57 #endif
58 
59 #ifdef LDAP_THREAD_DEBUG
60 #  if defined LDAP_INT_THREAD_MUTEXATTR	/* May be defined in CPPFLAGS */
61 #  elif defined HAVE_PTHREAD_KILL_OTHER_THREADS_NP
62 	 /* LinuxThreads hack */
63 #    define LDAP_INT_THREAD_MUTEXATTR	PTHREAD_MUTEX_ERRORCHECK_NP
64 #  else
65 #    define LDAP_INT_THREAD_MUTEXATTR	PTHREAD_MUTEX_ERRORCHECK
66 #  endif
67 static pthread_mutexattr_t mutex_attr;
68 #  undef  LDAP_INT_THREAD_MUTEXATTR_DEFAULT
69 #  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT &mutex_attr
70 #endif
71 
72 static pthread_mutexattr_t mutex_attr_recursive;
73 
74 #if HAVE_PTHREADS < 7
75 #define ERRVAL(val)	((val) < 0 ? errno : 0)
76 #else
77 #define ERRVAL(val)	(val)
78 #endif
79 
80 int
ldap_int_thread_initialize(void)81 ldap_int_thread_initialize( void )
82 {
83 #ifdef LDAP_INT_THREAD_MUTEXATTR
84 	pthread_mutexattr_init( &mutex_attr );
85 	pthread_mutexattr_settype( &mutex_attr, LDAP_INT_THREAD_MUTEXATTR );
86 #endif
87 	if (pthread_mutexattr_init(&mutex_attr_recursive))
88 		return -1;
89 	if (pthread_mutexattr_settype(&mutex_attr_recursive, PTHREAD_MUTEX_RECURSIVE))
90 		return -1;
91 	return 0;
92 }
93 
94 int
ldap_int_thread_destroy(void)95 ldap_int_thread_destroy( void )
96 {
97 #ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP
98 	/* LinuxThreads: kill clones */
99 	pthread_kill_other_threads_np();
100 #endif
101 #ifdef LDAP_INT_THREAD_MUTEXATTR
102 	pthread_mutexattr_destroy( &mutex_attr );
103 #endif
104 	pthread_mutexattr_destroy( &mutex_attr_recursive );
105 	return 0;
106 }
107 
108 #ifdef LDAP_THREAD_HAVE_SETCONCURRENCY
109 int
ldap_pvt_thread_set_concurrency(int n)110 ldap_pvt_thread_set_concurrency(int n)
111 {
112 #ifdef HAVE_PTHREAD_SETCONCURRENCY
113 	return pthread_setconcurrency( n );
114 #elif defined(HAVE_THR_SETCONCURRENCY)
115 	return thr_setconcurrency( n );
116 #else
117 	return 0;
118 #endif
119 }
120 #endif
121 
122 #ifdef LDAP_THREAD_HAVE_GETCONCURRENCY
123 int
ldap_pvt_thread_get_concurrency(void)124 ldap_pvt_thread_get_concurrency(void)
125 {
126 #ifdef HAVE_PTHREAD_GETCONCURRENCY
127 	return pthread_getconcurrency();
128 #elif defined(HAVE_THR_GETCONCURRENCY)
129 	return thr_getconcurrency();
130 #else
131 	return 0;
132 #endif
133 }
134 #endif
135 
136 /* detachstate appeared in Draft 6, but without manifest constants.
137  * in Draft 7 they were called PTHREAD_CREATE_UNDETACHED and ...DETACHED.
138  * in Draft 8 on, ...UNDETACHED became ...JOINABLE.
139  */
140 #ifndef PTHREAD_CREATE_JOINABLE
141 #ifdef PTHREAD_CREATE_UNDETACHED
142 #define	PTHREAD_CREATE_JOINABLE	PTHREAD_CREATE_UNDETACHED
143 #else
144 #define	PTHREAD_CREATE_JOINABLE	0
145 #endif
146 #endif
147 
148 #ifndef PTHREAD_CREATE_DETACHED
149 #define	PTHREAD_CREATE_DETACHED	1
150 #endif
151 
152 int
ldap_pvt_thread_create(ldap_pvt_thread_t * thread,int detach,void * (* start_routine)(void *),void * arg)153 ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
154 	int detach,
155 	void *(*start_routine)( void * ),
156 	void *arg)
157 {
158 	int rtn;
159 	pthread_attr_t attr;
160 
161 /* Always create the thread attrs, so we can set stacksize if we need to */
162 #if HAVE_PTHREADS > 5
163 	pthread_attr_init(&attr);
164 #else
165 	pthread_attr_create(&attr);
166 #endif
167 
168 #ifdef LDAP_PVT_THREAD_SET_STACK_SIZE
169 	/* this should be tunable */
170 	pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE );
171 	if ( ldap_int_stackguard )
172 		pthread_attr_setguardsize( &attr, LDAP_PVT_THREAD_STACK_SIZE );
173 #endif
174 
175 #if HAVE_PTHREADS > 5
176 	detach = detach ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE;
177 #if HAVE_PTHREADS == 6
178 	pthread_attr_setdetachstate(&attr, &detach);
179 #else
180 	pthread_attr_setdetachstate(&attr, detach);
181 #endif
182 #endif
183 
184 #if HAVE_PTHREADS < 5
185 	rtn = pthread_create( thread, attr, start_routine, arg );
186 #else
187 	rtn = pthread_create( thread, &attr, start_routine, arg );
188 #endif
189 
190 #if HAVE_PTHREADS > 5
191 	pthread_attr_destroy(&attr);
192 #else
193 	pthread_attr_delete(&attr);
194 	if( detach ) {
195 		pthread_detach( thread );
196 	}
197 #endif
198 
199 #if HAVE_PTHREADS < 7
200 	if ( rtn < 0 ) rtn = errno;
201 #endif
202 	return rtn;
203 }
204 
205 void
ldap_pvt_thread_exit(void * retval)206 ldap_pvt_thread_exit( void *retval )
207 {
208 	pthread_exit( retval );
209 }
210 
211 int
ldap_pvt_thread_join(ldap_pvt_thread_t thread,void ** thread_return)212 ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
213 {
214 #if HAVE_PTHREADS < 7
215 	void *dummy;
216 	if (thread_return==NULL)
217 	  thread_return=&dummy;
218 #endif
219 	return ERRVAL( pthread_join( thread, thread_return ) );
220 }
221 
222 int
ldap_pvt_thread_kill(ldap_pvt_thread_t thread,int signo)223 ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
224 {
225 #if defined(HAVE_PTHREAD_KILL) && HAVE_PTHREADS > 4
226 	/* MacOS 10.1 is detected as v10 but has no pthread_kill() */
227 	return ERRVAL( pthread_kill( thread, signo ) );
228 #else
229 	/* pthread package with DCE */
230 	if (kill( getpid(), signo )<0)
231 		return errno;
232 	return 0;
233 #endif
234 }
235 
236 int
ldap_pvt_thread_yield(void)237 ldap_pvt_thread_yield( void )
238 {
239 #ifdef REPLACE_BROKEN_YIELD
240 #ifdef HAVE_NANOSLEEP
241 	struct timespec t = { 0, 0 };
242 	nanosleep(&t, NULL);
243 #else
244 	struct timeval tv = {0,0};
245 	select( 0, NULL, NULL, NULL, &tv );
246 #endif
247 	return 0;
248 
249 #elif defined(HAVE_THR_YIELD)
250 	thr_yield();
251 	return 0;
252 
253 #elif HAVE_PTHREADS == 10
254 	return sched_yield();
255 
256 #elif defined(_POSIX_THREAD_IS_GNU_PTH)
257 	sched_yield();
258 	return 0;
259 
260 #elif HAVE_PTHREADS == 6
261 	pthread_yield(NULL);
262 	return 0;
263 
264 #else
265 	pthread_yield();
266 	return 0;
267 #endif
268 }
269 
270 int
ldap_pvt_thread_cond_init(ldap_pvt_thread_cond_t * cond)271 ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
272 {
273 	return ERRVAL( pthread_cond_init(
274 		cond, LDAP_INT_THREAD_CONDATTR_DEFAULT ) );
275 }
276 
277 int
ldap_pvt_thread_cond_destroy(ldap_pvt_thread_cond_t * cond)278 ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
279 {
280 	return ERRVAL( pthread_cond_destroy( cond ) );
281 }
282 
283 int
ldap_pvt_thread_cond_signal(ldap_pvt_thread_cond_t * cond)284 ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
285 {
286 	return ERRVAL( pthread_cond_signal( cond ) );
287 }
288 
289 int
ldap_pvt_thread_cond_broadcast(ldap_pvt_thread_cond_t * cond)290 ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
291 {
292 	return ERRVAL( pthread_cond_broadcast( cond ) );
293 }
294 
295 int
ldap_pvt_thread_cond_wait(ldap_pvt_thread_cond_t * cond,ldap_pvt_thread_mutex_t * mutex)296 ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond,
297 		      ldap_pvt_thread_mutex_t *mutex )
298 {
299 	return ERRVAL( pthread_cond_wait( cond, mutex ) );
300 }
301 
302 int
ldap_pvt_thread_mutex_init(ldap_pvt_thread_mutex_t * mutex)303 ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
304 {
305 	return ERRVAL( pthread_mutex_init(
306 		mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT ) );
307 }
308 
309 int
ldap_pvt_thread_mutex_destroy(ldap_pvt_thread_mutex_t * mutex)310 ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
311 {
312 	return ERRVAL( pthread_mutex_destroy( mutex ) );
313 }
314 
315 int
ldap_pvt_thread_mutex_lock(ldap_pvt_thread_mutex_t * mutex)316 ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
317 {
318 	return ERRVAL( pthread_mutex_lock( mutex ) );
319 }
320 
321 int
ldap_pvt_thread_mutex_trylock(ldap_pvt_thread_mutex_t * mutex)322 ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
323 {
324 	return ERRVAL( pthread_mutex_trylock( mutex ) );
325 }
326 
327 int
ldap_pvt_thread_mutex_unlock(ldap_pvt_thread_mutex_t * mutex)328 ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
329 {
330 	return ERRVAL( pthread_mutex_unlock( mutex ) );
331 }
332 
333 int
ldap_pvt_thread_mutex_recursive_init(ldap_pvt_thread_mutex_t * mutex)334 ldap_pvt_thread_mutex_recursive_init( ldap_pvt_thread_mutex_t *mutex )
335 {
336 	return ERRVAL( pthread_mutex_init( mutex, &mutex_attr_recursive ) );
337 }
338 
ldap_pvt_thread_self(void)339 ldap_pvt_thread_t ldap_pvt_thread_self( void )
340 {
341 	return pthread_self();
342 }
343 
344 int
ldap_pvt_thread_key_create(ldap_pvt_thread_key_t * key)345 ldap_pvt_thread_key_create( ldap_pvt_thread_key_t *key )
346 {
347 	return pthread_key_create( key, NULL );
348 }
349 
350 int
ldap_pvt_thread_key_destroy(ldap_pvt_thread_key_t key)351 ldap_pvt_thread_key_destroy( ldap_pvt_thread_key_t key )
352 {
353 	return pthread_key_delete( key );
354 }
355 
356 int
ldap_pvt_thread_key_setdata(ldap_pvt_thread_key_t key,void * data)357 ldap_pvt_thread_key_setdata( ldap_pvt_thread_key_t key, void *data )
358 {
359 	return pthread_setspecific( key, data );
360 }
361 
362 int
ldap_pvt_thread_key_getdata(ldap_pvt_thread_key_t key,void ** data)363 ldap_pvt_thread_key_getdata( ldap_pvt_thread_key_t key, void **data )
364 {
365 	*data = pthread_getspecific( key );
366 	return 0;
367 }
368 
369 #ifdef LDAP_THREAD_HAVE_RDWR
370 #ifdef HAVE_PTHREAD_RWLOCK_DESTROY
371 int
ldap_pvt_thread_rdwr_init(ldap_pvt_thread_rdwr_t * rw)372 ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
373 {
374 	return ERRVAL( pthread_rwlock_init( rw, NULL ) );
375 }
376 
377 int
ldap_pvt_thread_rdwr_destroy(ldap_pvt_thread_rdwr_t * rw)378 ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
379 {
380 	return ERRVAL( pthread_rwlock_destroy( rw ) );
381 }
382 
ldap_pvt_thread_rdwr_rlock(ldap_pvt_thread_rdwr_t * rw)383 int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
384 {
385 	return ERRVAL( pthread_rwlock_rdlock( rw ) );
386 }
387 
ldap_pvt_thread_rdwr_rtrylock(ldap_pvt_thread_rdwr_t * rw)388 int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
389 {
390 	return ERRVAL( pthread_rwlock_tryrdlock( rw ) );
391 }
392 
ldap_pvt_thread_rdwr_runlock(ldap_pvt_thread_rdwr_t * rw)393 int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
394 {
395 	return ERRVAL( pthread_rwlock_unlock( rw ) );
396 }
397 
ldap_pvt_thread_rdwr_wlock(ldap_pvt_thread_rdwr_t * rw)398 int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
399 {
400 	return ERRVAL( pthread_rwlock_wrlock( rw ) );
401 }
402 
ldap_pvt_thread_rdwr_wtrylock(ldap_pvt_thread_rdwr_t * rw)403 int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
404 {
405 	return ERRVAL( pthread_rwlock_trywrlock( rw ) );
406 }
407 
ldap_pvt_thread_rdwr_wunlock(ldap_pvt_thread_rdwr_t * rw)408 int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
409 {
410 	return ERRVAL( pthread_rwlock_unlock( rw ) );
411 }
412 
413 #endif /* HAVE_PTHREAD_RWLOCK_DESTROY */
414 #endif /* LDAP_THREAD_HAVE_RDWR */
415 #endif /* HAVE_PTHREADS */
416 
417