Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: tpool.c,v 1.3 2025/09/05 21:16:22 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 
     18 #include <sys/cdefs.h>
     19 __RCSID("$NetBSD: tpool.c,v 1.3 2025/09/05 21:16:22 christos Exp $");
     20 
     21 #include "portable.h"
     22 
     23 #include <stdio.h>
     24 
     25 #include <ac/signal.h>
     26 #include <ac/stdarg.h>
     27 #include <ac/stdlib.h>
     28 #include <ac/string.h>
     29 #include <ac/time.h>
     30 #include <ac/errno.h>
     31 
     32 #include "ldap-int.h"
     33 
     34 #ifdef LDAP_R_COMPILE
     35 
     36 #include "ldap_pvt_thread.h" /* Get the thread interface */
     37 #include "ldap_queue.h"
     38 #define LDAP_THREAD_POOL_IMPLEMENTATION
     39 #include "ldap_thr_debug.h"  /* May rename symbols defined below */
     40 
     41 #ifndef LDAP_THREAD_HAVE_TPOOL
     42 
     43 #ifndef CACHELINE
     44 #define CACHELINE	64
     45 #endif
     46 
     47 /* Thread-specific key with data and optional free function */
     48 typedef struct ldap_int_tpool_key_s {
     49 	void *ltk_key;
     50 	void *ltk_data;
     51 	ldap_pvt_thread_pool_keyfree_t *ltk_free;
     52 } ldap_int_tpool_key_t;
     53 
     54 /* Max number of thread-specific keys we store per thread.
     55  * We don't expect to use many...
     56  */
     57 #define	MAXKEYS	32
     58 
     59 /* Max number of threads */
     60 #define	LDAP_MAXTHR	1024	/* must be a power of 2 */
     61 
     62 /* (Theoretical) max number of pending requests */
     63 #define MAX_PENDING (INT_MAX/2)	/* INT_MAX - (room to avoid overflow) */
     64 
     65 /* pool->ltp_pause values */
     66 enum { NOT_PAUSED = 0, WANT_PAUSE = 1, PAUSED = 2 };
     67 
     68 /* Context: thread ID and thread-specific key/data pairs */
     69 typedef struct ldap_int_thread_userctx_s {
     70 	struct ldap_int_thread_poolq_s *ltu_pq;
     71 	ldap_pvt_thread_t ltu_id;
     72 	ldap_int_tpool_key_t ltu_key[MAXKEYS];
     73 } ldap_int_thread_userctx_t;
     74 
     75 
     76 /* Simple {thread ID -> context} hash table; key=ctx->ltu_id.
     77  * Protected by ldap_pvt_thread_pool_mutex.
     78  */
     79 static struct {
     80 	ldap_int_thread_userctx_t *ctx;
     81 	/* ctx is valid when not NULL or DELETED_THREAD_CTX */
     82 #	define DELETED_THREAD_CTX (&ldap_int_main_thrctx + 1) /* dummy addr */
     83 } thread_keys[LDAP_MAXTHR];
     84 
     85 #define	TID_HASH(tid, hash) do { \
     86 	unsigned const char *ptr_ = (unsigned const char *)&(tid); \
     87 	unsigned i_; \
     88 	for (i_ = 0, (hash) = ptr_[0]; ++i_ < sizeof(tid);) \
     89 		(hash) += ((hash) << 5) ^ ptr_[i_]; \
     90 } while(0)
     91 
     92 
     93 /* Task for a thread to perform */
     94 typedef struct ldap_int_thread_task_s {
     95 	union {
     96 		LDAP_STAILQ_ENTRY(ldap_int_thread_task_s) q;
     97 		LDAP_SLIST_ENTRY(ldap_int_thread_task_s) l;
     98 	} ltt_next;
     99 	ldap_pvt_thread_start_t *ltt_start_routine;
    100 	void *ltt_arg;
    101 	struct ldap_int_thread_poolq_s *ltt_queue;
    102 } ldap_int_thread_task_t;
    103 
    104 typedef LDAP_STAILQ_HEAD(tcq, ldap_int_thread_task_s) ldap_int_tpool_plist_t;
    105 
    106 struct ldap_int_thread_poolq_s {
    107 	void *ltp_free;
    108 
    109 	struct ldap_int_thread_pool_s *ltp_pool;
    110 
    111 	/* protect members below */
    112 	ldap_pvt_thread_mutex_t ltp_mutex;
    113 
    114 	/* not paused and something to do for pool_<wrapper/pause/destroy>()
    115 	 * Used for normal pool operation, to synch between submitter and
    116 	 * worker threads. Not used for pauses. In normal operation multiple
    117 	 * queues can rendezvous without acquiring the main pool lock.
    118 	 */
    119 	ldap_pvt_thread_cond_t ltp_cond;
    120 
    121 	/* ltp_pause == 0 ? &ltp_pending_list : &empty_pending_list,
    122 	 * maintained to reduce work for pool_wrapper()
    123 	 */
    124 	ldap_int_tpool_plist_t *ltp_work_list;
    125 
    126 	/* pending tasks, and unused task objects */
    127 	ldap_int_tpool_plist_t ltp_pending_list;
    128 	LDAP_SLIST_HEAD(tcl, ldap_int_thread_task_s) ltp_free_list;
    129 
    130 	/* Max number of threads in this queue */
    131 	int ltp_max_count;
    132 
    133 	/* Max pending + paused + idle tasks, negated when ltp_finishing */
    134 	int ltp_max_pending;
    135 
    136 	int ltp_pending_count;		/* Pending + paused + idle tasks */
    137 	int ltp_active_count;		/* Active, not paused/idle tasks */
    138 	int ltp_open_count;			/* Number of threads */
    139 	int ltp_starting;			/* Currently starting threads */
    140 };
    141 
    142 struct ldap_int_thread_pool_s {
    143 	LDAP_STAILQ_ENTRY(ldap_int_thread_pool_s) ltp_next;
    144 
    145 	struct ldap_int_thread_poolq_s **ltp_wqs;
    146 
    147 	/* number of poolqs */
    148 	int ltp_numqs;
    149 
    150 	/* protect members below */
    151 	ldap_pvt_thread_mutex_t ltp_mutex;
    152 
    153 	/* paused and waiting for resume
    154 	 * When a pause is in effect all workers switch to waiting on
    155 	 * this cond instead of their per-queue cond.
    156 	 */
    157 	ldap_pvt_thread_cond_t ltp_cond;
    158 
    159 	/* ltp_active_queues < 1 && ltp_pause */
    160 	ldap_pvt_thread_cond_t ltp_pcond;
    161 
    162 	/* number of active queues */
    163 	int ltp_active_queues;
    164 
    165 	/* The pool is finishing, waiting for its threads to close.
    166 	 * They close when ltp_pending_list is done.  pool_submit()
    167 	 * rejects new tasks.  ltp_max_pending = -(its old value).
    168 	 */
    169 	int ltp_finishing;
    170 
    171 	/* Some active task needs to be the sole active task.
    172 	 * Atomic variable so ldap_pvt_thread_pool_pausing() can read it.
    173 	 */
    174 	volatile sig_atomic_t ltp_pause;
    175 
    176 	/* Max number of threads in pool */
    177 	int ltp_max_count;
    178 
    179 	/* Configured max number of threads in pool, 0 for default (LDAP_MAXTHR) */
    180 	int ltp_conf_max_count;
    181 
    182 	/* Max pending + paused + idle tasks, negated when ltp_finishing */
    183 	int ltp_max_pending;
    184 };
    185 
    186 static ldap_int_tpool_plist_t empty_pending_list =
    187 	LDAP_STAILQ_HEAD_INITIALIZER(empty_pending_list);
    188 
    189 static int ldap_int_has_thread_pool = 0;
    190 static LDAP_STAILQ_HEAD(tpq, ldap_int_thread_pool_s)
    191 	ldap_int_thread_pool_list =
    192 	LDAP_STAILQ_HEAD_INITIALIZER(ldap_int_thread_pool_list);
    193 
    194 static ldap_pvt_thread_mutex_t ldap_pvt_thread_pool_mutex;
    195 
    196 static void *ldap_int_thread_pool_wrapper( void *pool );
    197 
    198 static ldap_pvt_thread_key_t	ldap_tpool_key;
    199 
    200 /* Context of the main thread */
    201 static ldap_int_thread_userctx_t ldap_int_main_thrctx;
    202 
    203 int
    204 ldap_int_thread_pool_startup ( void )
    205 {
    206 	ldap_int_main_thrctx.ltu_id = ldap_pvt_thread_self();
    207 	ldap_pvt_thread_key_create( &ldap_tpool_key );
    208 	return ldap_pvt_thread_mutex_init(&ldap_pvt_thread_pool_mutex);
    209 }
    210 
    211 int
    212 ldap_int_thread_pool_shutdown ( void )
    213 {
    214 	struct ldap_int_thread_pool_s *pool;
    215 
    216 	while ((pool = LDAP_STAILQ_FIRST(&ldap_int_thread_pool_list)) != NULL) {
    217 		(ldap_pvt_thread_pool_destroy)(&pool, 0); /* ignore thr_debug macro */
    218 	}
    219 	ldap_pvt_thread_mutex_destroy(&ldap_pvt_thread_pool_mutex);
    220 	ldap_pvt_thread_key_destroy( ldap_tpool_key );
    221 	return(0);
    222 }
    223 
    224 
    225 /* Create a thread pool */
    226 int
    227 ldap_pvt_thread_pool_init_q (
    228 	ldap_pvt_thread_pool_t *tpool,
    229 	int max_threads,
    230 	int max_pending,
    231 	int numqs )
    232 {
    233 	ldap_pvt_thread_pool_t pool;
    234 	struct ldap_int_thread_poolq_s *pq;
    235 	int i, rc, rem_thr, rem_pend;
    236 
    237 	/* multiple pools are currently not supported (ITS#4943) */
    238 	assert(!ldap_int_has_thread_pool);
    239 
    240 	if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
    241 		max_threads = 0;
    242 	if (! (1 <= max_pending && max_pending <= MAX_PENDING))
    243 		max_pending = MAX_PENDING;
    244 
    245 	*tpool = NULL;
    246 	pool = (ldap_pvt_thread_pool_t) LDAP_CALLOC(1,
    247 		sizeof(struct ldap_int_thread_pool_s));
    248 
    249 	if (pool == NULL) return(-1);
    250 
    251 	pool->ltp_wqs = LDAP_MALLOC(numqs * sizeof(struct ldap_int_thread_poolq_s *));
    252 	if (pool->ltp_wqs == NULL) {
    253 		LDAP_FREE(pool);
    254 		return(-1);
    255 	}
    256 
    257 	for (i=0; i<numqs; i++) {
    258 		char *ptr = LDAP_CALLOC(1, sizeof(struct ldap_int_thread_poolq_s) + CACHELINE-1);
    259 		if (ptr == NULL) {
    260 			for (--i; i>=0; i--)
    261 				LDAP_FREE(pool->ltp_wqs[i]->ltp_free);
    262 			LDAP_FREE(pool->ltp_wqs);
    263 			LDAP_FREE(pool);
    264 			return(-1);
    265 		}
    266 		pool->ltp_wqs[i] = (struct ldap_int_thread_poolq_s *)(((size_t)ptr + CACHELINE-1) & ~(CACHELINE-1));
    267 		pool->ltp_wqs[i]->ltp_free = ptr;
    268 	}
    269 
    270 	pool->ltp_numqs = numqs;
    271 	pool->ltp_conf_max_count = max_threads;
    272 	if ( !max_threads )
    273 		max_threads = LDAP_MAXTHR;
    274 
    275 	rc = ldap_pvt_thread_mutex_init(&pool->ltp_mutex);
    276 	if (rc != 0) {
    277 fail:
    278 		for (i=0; i<numqs; i++)
    279 			LDAP_FREE(pool->ltp_wqs[i]->ltp_free);
    280 		LDAP_FREE(pool->ltp_wqs);
    281 		LDAP_FREE(pool);
    282 		return(rc);
    283 	}
    284 
    285 	rc = ldap_pvt_thread_cond_init(&pool->ltp_cond);
    286 	if (rc != 0)
    287 		goto fail;
    288 
    289 	rc = ldap_pvt_thread_cond_init(&pool->ltp_pcond);
    290 	if (rc != 0)
    291 		goto fail;
    292 
    293 	rem_thr = max_threads % numqs;
    294 	rem_pend = max_pending % numqs;
    295 	for ( i=0; i<numqs; i++ ) {
    296 		pq = pool->ltp_wqs[i];
    297 		pq->ltp_pool = pool;
    298 		rc = ldap_pvt_thread_mutex_init(&pq->ltp_mutex);
    299 		if (rc != 0)
    300 			return(rc);
    301 		rc = ldap_pvt_thread_cond_init(&pq->ltp_cond);
    302 		if (rc != 0)
    303 			return(rc);
    304 		LDAP_STAILQ_INIT(&pq->ltp_pending_list);
    305 		pq->ltp_work_list = &pq->ltp_pending_list;
    306 		LDAP_SLIST_INIT(&pq->ltp_free_list);
    307 
    308 		pq->ltp_max_count = max_threads / numqs;
    309 		if ( rem_thr ) {
    310 			pq->ltp_max_count++;
    311 			rem_thr--;
    312 		}
    313 		pq->ltp_max_pending = max_pending / numqs;
    314 		if ( rem_pend ) {
    315 			pq->ltp_max_pending++;
    316 			rem_pend--;
    317 		}
    318 	}
    319 
    320 	ldap_int_has_thread_pool = 1;
    321 
    322 	pool->ltp_max_count = max_threads;
    323 	pool->ltp_max_pending = max_pending;
    324 
    325 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
    326 	LDAP_STAILQ_INSERT_TAIL(&ldap_int_thread_pool_list, pool, ltp_next);
    327 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
    328 
    329 	/* Start no threads just yet.  That can break if the process forks
    330 	 * later, as slapd does in order to daemonize.  On at least POSIX,
    331 	 * only the forking thread would survive in the child.  Yet fork()
    332 	 * can't unlock/clean up other threads' locks and data structures,
    333 	 * unless pthread_atfork() handlers have been set up to do so.
    334 	 */
    335 
    336 	*tpool = pool;
    337 	return(0);
    338 }
    339 
    340 int
    341 ldap_pvt_thread_pool_init (
    342 	ldap_pvt_thread_pool_t *tpool,
    343 	int max_threads,
    344 	int max_pending )
    345 {
    346 	return ldap_pvt_thread_pool_init_q( tpool, max_threads, max_pending, 1 );
    347 }
    348 
    349 /* Submit a task to be performed by the thread pool */
    350 int
    351 ldap_pvt_thread_pool_submit (
    352 	ldap_pvt_thread_pool_t *tpool,
    353 	ldap_pvt_thread_start_t *start_routine, void *arg )
    354 {
    355 	return ldap_pvt_thread_pool_submit2( tpool, start_routine, arg, NULL );
    356 }
    357 
    358 /* Submit a task to be performed by the thread pool */
    359 int
    360 ldap_pvt_thread_pool_submit2 (
    361 	ldap_pvt_thread_pool_t *tpool,
    362 	ldap_pvt_thread_start_t *start_routine, void *arg,
    363 	void **cookie )
    364 {
    365 	struct ldap_int_thread_pool_s *pool;
    366 	struct ldap_int_thread_poolq_s *pq;
    367 	ldap_int_thread_task_t *task;
    368 	ldap_pvt_thread_t thr;
    369 	int i, j;
    370 
    371 	if (tpool == NULL)
    372 		return(-1);
    373 
    374 	pool = *tpool;
    375 
    376 	if (pool == NULL)
    377 		return(-1);
    378 
    379 	if ( pool->ltp_numqs > 1 ) {
    380 		int min = pool->ltp_wqs[0]->ltp_max_pending + pool->ltp_wqs[0]->ltp_max_count;
    381 		int min_x = 0, cnt;
    382 		for ( i = 0; i < pool->ltp_numqs; i++ ) {
    383 			/* take first queue that has nothing active */
    384 			if ( !pool->ltp_wqs[i]->ltp_active_count ) {
    385 				min_x = i;
    386 				break;
    387 			}
    388 			cnt = pool->ltp_wqs[i]->ltp_active_count + pool->ltp_wqs[i]->ltp_pending_count;
    389 			if ( cnt < min ) {
    390 				min = cnt;
    391 				min_x = i;
    392 			}
    393 		}
    394 		i = min_x;
    395 	} else
    396 		i = 0;
    397 
    398 	j = i;
    399 	while(1) {
    400 		ldap_pvt_thread_mutex_lock(&pool->ltp_wqs[i]->ltp_mutex);
    401 		if (pool->ltp_wqs[i]->ltp_pending_count < pool->ltp_wqs[i]->ltp_max_pending) {
    402 			break;
    403 		}
    404 		ldap_pvt_thread_mutex_unlock(&pool->ltp_wqs[i]->ltp_mutex);
    405 		i++;
    406 		i %= pool->ltp_numqs;
    407 		if ( i == j )
    408 			return -1;
    409 	}
    410 
    411 	pq = pool->ltp_wqs[i];
    412 	task = LDAP_SLIST_FIRST(&pq->ltp_free_list);
    413 	if (task) {
    414 		LDAP_SLIST_REMOVE_HEAD(&pq->ltp_free_list, ltt_next.l);
    415 	} else {
    416 		task = (ldap_int_thread_task_t *) LDAP_MALLOC(sizeof(*task));
    417 		if (task == NULL)
    418 			goto failed;
    419 	}
    420 
    421 	task->ltt_start_routine = start_routine;
    422 	task->ltt_arg = arg;
    423 	task->ltt_queue = pq;
    424 	if ( cookie )
    425 		*cookie = task;
    426 
    427 	pq->ltp_pending_count++;
    428 	LDAP_STAILQ_INSERT_TAIL(&pq->ltp_pending_list, task, ltt_next.q);
    429 
    430 	if (pool->ltp_pause)
    431 		goto done;
    432 
    433 	/* should we open (create) a thread? */
    434 	if (pq->ltp_open_count < pq->ltp_active_count+pq->ltp_pending_count &&
    435 		pq->ltp_open_count < pq->ltp_max_count)
    436 	{
    437 		pq->ltp_starting++;
    438 		pq->ltp_open_count++;
    439 
    440 		if (0 != ldap_pvt_thread_create(
    441 			&thr, 1, ldap_int_thread_pool_wrapper, pq))
    442 		{
    443 			/* couldn't create thread.  back out of
    444 			 * ltp_open_count and check for even worse things.
    445 			 */
    446 			pq->ltp_starting--;
    447 			pq->ltp_open_count--;
    448 
    449 			if (pq->ltp_open_count == 0) {
    450 				/* no open threads at all?!?
    451 				 */
    452 				ldap_int_thread_task_t *ptr;
    453 
    454 				/* let pool_close know there are no more threads */
    455 				ldap_pvt_thread_cond_signal(&pq->ltp_cond);
    456 
    457 				LDAP_STAILQ_FOREACH(ptr, &pq->ltp_pending_list, ltt_next.q)
    458 					if (ptr == task) break;
    459 				if (ptr == task) {
    460 					/* no open threads, task not handled, so
    461 					 * back out of ltp_pending_count, free the task,
    462 					 * report the error.
    463 					 */
    464 					pq->ltp_pending_count--;
    465 					LDAP_STAILQ_REMOVE(&pq->ltp_pending_list, task,
    466 						ldap_int_thread_task_s, ltt_next.q);
    467 					LDAP_SLIST_INSERT_HEAD(&pq->ltp_free_list, task,
    468 						ltt_next.l);
    469 					goto failed;
    470 				}
    471 			}
    472 			/* there is another open thread, so this
    473 			 * task will be handled eventually.
    474 			 */
    475 		}
    476 	}
    477 	ldap_pvt_thread_cond_signal(&pq->ltp_cond);
    478 
    479  done:
    480 	ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
    481 	return(0);
    482 
    483  failed:
    484 	ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
    485 	return(-1);
    486 }
    487 
    488 static void *
    489 no_task( void *ctx, void *arg )
    490 {
    491 	return NULL;
    492 }
    493 
    494 /* Cancel a pending task that was previously submitted.
    495  * Return 1 if the task was successfully cancelled, 0 if
    496  * not found, -1 for invalid parameters
    497  */
    498 int
    499 ldap_pvt_thread_pool_retract (
    500 	void *cookie )
    501 {
    502 	ldap_int_thread_task_t *task, *ttmp;
    503 	struct ldap_int_thread_poolq_s *pq;
    504 
    505 	if (cookie == NULL)
    506 		return(-1);
    507 
    508 	ttmp = cookie;
    509 	pq = ttmp->ltt_queue;
    510 	if (pq == NULL)
    511 		return(-1);
    512 
    513 	ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
    514 	LDAP_STAILQ_FOREACH(task, &pq->ltp_pending_list, ltt_next.q)
    515 		if (task == ttmp) {
    516 			/* Could LDAP_STAILQ_REMOVE the task, but that
    517 			 * walks ltp_pending_list again to find it.
    518 			 */
    519 			task->ltt_start_routine = no_task;
    520 			task->ltt_arg = NULL;
    521 			break;
    522 		}
    523 	ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
    524 	return task != NULL;
    525 }
    526 
    527 /* Walk the pool and allow tasks to be retracted, only to be called while the
    528  * pool is paused */
    529 int
    530 ldap_pvt_thread_pool_walk(
    531 	ldap_pvt_thread_pool_t *tpool,
    532 	ldap_pvt_thread_start_t *start,
    533 	ldap_pvt_thread_walk_t *cb, void *arg )
    534 {
    535 	struct ldap_int_thread_pool_s *pool;
    536 	struct ldap_int_thread_poolq_s *pq;
    537 	ldap_int_thread_task_t *task;
    538 	int i;
    539 
    540 	if (tpool == NULL)
    541 		return(-1);
    542 
    543 	pool = *tpool;
    544 
    545 	if (pool == NULL)
    546 		return(-1);
    547 
    548 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
    549 	assert(pool->ltp_pause == PAUSED);
    550 	ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
    551 
    552 	for (i=0; i<pool->ltp_numqs; i++) {
    553 		pq = pool->ltp_wqs[i];
    554 		LDAP_STAILQ_FOREACH(task, &pq->ltp_pending_list, ltt_next.q) {
    555 			if ( task->ltt_start_routine == start ) {
    556 				if ( cb( task->ltt_start_routine, task->ltt_arg, arg ) ) {
    557 					/* retract */
    558 					task->ltt_start_routine = no_task;
    559 					task->ltt_arg = NULL;
    560 				}
    561 			}
    562 		}
    563 	}
    564 	return 0;
    565 }
    566 
    567 /* Set number of work queues in this pool. Should not be
    568  * more than the number of CPUs. */
    569 int
    570 ldap_pvt_thread_pool_queues(
    571 	ldap_pvt_thread_pool_t *tpool,
    572 	int numqs )
    573 {
    574 	struct ldap_int_thread_pool_s *pool;
    575 	struct ldap_int_thread_poolq_s *pq;
    576 	int i, rc, rem_thr, rem_pend;
    577 
    578 	if (numqs < 1 || tpool == NULL)
    579 		return(-1);
    580 
    581 	pool = *tpool;
    582 
    583 	if (pool == NULL)
    584 		return(-1);
    585 
    586 	if (numqs < pool->ltp_numqs) {
    587 		for (i=numqs; i<pool->ltp_numqs; i++)
    588 			pool->ltp_wqs[i]->ltp_max_count = 0;
    589 	} else if (numqs > pool->ltp_numqs) {
    590 		struct ldap_int_thread_poolq_s **wqs;
    591 		wqs = LDAP_REALLOC(pool->ltp_wqs, numqs * sizeof(struct ldap_int_thread_poolq_s *));
    592 		if (wqs == NULL)
    593 			return(-1);
    594 		pool->ltp_wqs = wqs;
    595 		for (i=pool->ltp_numqs; i<numqs; i++) {
    596 			char *ptr = LDAP_CALLOC(1, sizeof(struct ldap_int_thread_poolq_s) + CACHELINE-1);
    597 			if (ptr == NULL) {
    598 				for (; i<numqs; i++)
    599 					pool->ltp_wqs[i] = NULL;
    600 				return(-1);
    601 			}
    602 			pq = (struct ldap_int_thread_poolq_s *)(((size_t)ptr + CACHELINE-1) & ~(CACHELINE-1));
    603 			pq->ltp_free = ptr;
    604 			pool->ltp_wqs[i] = pq;
    605 			pq->ltp_pool = pool;
    606 			rc = ldap_pvt_thread_mutex_init(&pq->ltp_mutex);
    607 			if (rc != 0)
    608 				return(rc);
    609 			rc = ldap_pvt_thread_cond_init(&pq->ltp_cond);
    610 			if (rc != 0)
    611 				return(rc);
    612 			LDAP_STAILQ_INIT(&pq->ltp_pending_list);
    613 			pq->ltp_work_list = &pq->ltp_pending_list;
    614 			LDAP_SLIST_INIT(&pq->ltp_free_list);
    615 		}
    616 	}
    617 	rem_thr = pool->ltp_max_count % numqs;
    618 	rem_pend = pool->ltp_max_pending % numqs;
    619 	for ( i=0; i<numqs; i++ ) {
    620 		pq = pool->ltp_wqs[i];
    621 		pq->ltp_max_count = pool->ltp_max_count / numqs;
    622 		if ( rem_thr ) {
    623 			pq->ltp_max_count++;
    624 			rem_thr--;
    625 		}
    626 		pq->ltp_max_pending = pool->ltp_max_pending / numqs;
    627 		if ( rem_pend ) {
    628 			pq->ltp_max_pending++;
    629 			rem_pend--;
    630 		}
    631 	}
    632 	pool->ltp_numqs = numqs;
    633 	return 0;
    634 }
    635 
    636 /* Set max #threads.  value <= 0 means max supported #threads (LDAP_MAXTHR) */
    637 int
    638 ldap_pvt_thread_pool_maxthreads(
    639 	ldap_pvt_thread_pool_t *tpool,
    640 	int max_threads )
    641 {
    642 	struct ldap_int_thread_pool_s *pool;
    643 	struct ldap_int_thread_poolq_s *pq;
    644 	int remthr, i;
    645 
    646 	if (! (0 <= max_threads && max_threads <= LDAP_MAXTHR))
    647 		max_threads = 0;
    648 
    649 	if (tpool == NULL)
    650 		return(-1);
    651 
    652 	pool = *tpool;
    653 
    654 	if (pool == NULL)
    655 		return(-1);
    656 
    657 	pool->ltp_conf_max_count = max_threads;
    658 	if ( !max_threads )
    659 		max_threads = LDAP_MAXTHR;
    660 	pool->ltp_max_count = max_threads;
    661 
    662 	remthr = max_threads % pool->ltp_numqs;
    663 	max_threads /= pool->ltp_numqs;
    664 
    665 	for (i=0; i<pool->ltp_numqs; i++) {
    666 		pq = pool->ltp_wqs[i];
    667 		pq->ltp_max_count = max_threads;
    668 		if (remthr) {
    669 			pq->ltp_max_count++;
    670 			remthr--;
    671 		}
    672 	}
    673 	return(0);
    674 }
    675 
    676 /* Inspect the pool */
    677 int
    678 ldap_pvt_thread_pool_query(
    679 	ldap_pvt_thread_pool_t *tpool,
    680 	ldap_pvt_thread_pool_param_t param,
    681 	void *value )
    682 {
    683 	struct ldap_int_thread_pool_s	*pool;
    684 	int				count = -1;
    685 
    686 	if ( tpool == NULL || value == NULL ) {
    687 		return -1;
    688 	}
    689 
    690 	pool = *tpool;
    691 
    692 	if ( pool == NULL ) {
    693 		return 0;
    694 	}
    695 
    696 	switch ( param ) {
    697 	case LDAP_PVT_THREAD_POOL_PARAM_MAX:
    698 		count = pool->ltp_conf_max_count;
    699 		break;
    700 
    701 	case LDAP_PVT_THREAD_POOL_PARAM_MAX_PENDING:
    702 		count = pool->ltp_max_pending;
    703 		if (count < 0)
    704 			count = -count;
    705 		if (count == MAX_PENDING)
    706 			count = 0;
    707 		break;
    708 
    709 	case LDAP_PVT_THREAD_POOL_PARAM_PAUSING:
    710 		ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
    711 		count = (pool->ltp_pause != 0);
    712 		ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
    713 		break;
    714 
    715 	case LDAP_PVT_THREAD_POOL_PARAM_OPEN:
    716 	case LDAP_PVT_THREAD_POOL_PARAM_STARTING:
    717 	case LDAP_PVT_THREAD_POOL_PARAM_ACTIVE:
    718 	case LDAP_PVT_THREAD_POOL_PARAM_PENDING:
    719 	case LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD:
    720 		{
    721 			int i;
    722 			count = 0;
    723 			for (i=0; i<pool->ltp_numqs; i++) {
    724 				struct ldap_int_thread_poolq_s *pq = pool->ltp_wqs[i];
    725 				ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
    726 				switch(param) {
    727 					case LDAP_PVT_THREAD_POOL_PARAM_OPEN:
    728 						count += pq->ltp_open_count;
    729 						break;
    730 					case LDAP_PVT_THREAD_POOL_PARAM_STARTING:
    731 						count += pq->ltp_starting;
    732 						break;
    733 					case LDAP_PVT_THREAD_POOL_PARAM_ACTIVE:
    734 						count += pq->ltp_active_count;
    735 						break;
    736 					case LDAP_PVT_THREAD_POOL_PARAM_PENDING:
    737 						count += pq->ltp_pending_count;
    738 						break;
    739 					case LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD:
    740 						count += pq->ltp_pending_count + pq->ltp_active_count;
    741 						break;
    742 					default:
    743 						break;
    744 				}
    745 				ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
    746 			}
    747 			if (count < 0)
    748 				count = -count;
    749 		}
    750 		break;
    751 
    752 	case LDAP_PVT_THREAD_POOL_PARAM_ACTIVE_MAX:
    753 		break;
    754 
    755 	case LDAP_PVT_THREAD_POOL_PARAM_PENDING_MAX:
    756 		break;
    757 
    758 	case LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD_MAX:
    759 		break;
    760 
    761 	case LDAP_PVT_THREAD_POOL_PARAM_STATE:
    762 		if (pool->ltp_pause)
    763 			*((char **)value) = "pausing";
    764 		else if (!pool->ltp_finishing)
    765 			*((char **)value) = "running";
    766 		else {
    767 			int i;
    768 			for (i=0; i<pool->ltp_numqs; i++)
    769 				if (pool->ltp_wqs[i]->ltp_pending_count) break;
    770 			if (i<pool->ltp_numqs)
    771 				*((char **)value) = "finishing";
    772 			else
    773 				*((char **)value) = "stopping";
    774 		}
    775 		break;
    776 
    777 	case LDAP_PVT_THREAD_POOL_PARAM_PAUSED:
    778 		ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
    779 		count = (pool->ltp_pause == PAUSED);
    780 		ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
    781 		break;
    782 
    783 	case LDAP_PVT_THREAD_POOL_PARAM_UNKNOWN:
    784 		break;
    785 	}
    786 
    787 	if ( count > -1 ) {
    788 		*((int *)value) = count;
    789 	}
    790 
    791 	return ( count == -1 ? -1 : 0 );
    792 }
    793 
    794 /*
    795  * true if pool is pausing; does not lock any mutex to check.
    796  * 0 if not pause, 1 if pause, -1 if error or no pool.
    797  */
    798 int
    799 ldap_pvt_thread_pool_pausing( ldap_pvt_thread_pool_t *tpool )
    800 {
    801 	int rc = -1;
    802 	struct ldap_int_thread_pool_s *pool;
    803 
    804 	if ( tpool != NULL && (pool = *tpool) != NULL ) {
    805 		rc = (pool->ltp_pause != 0);
    806 	}
    807 
    808 	return rc;
    809 }
    810 
    811 /*
    812  * wrapper for ldap_pvt_thread_pool_query(), left around
    813  * for backwards compatibility
    814  */
    815 int
    816 ldap_pvt_thread_pool_backload ( ldap_pvt_thread_pool_t *tpool )
    817 {
    818 	int	rc, count;
    819 
    820 	rc = ldap_pvt_thread_pool_query( tpool,
    821 		LDAP_PVT_THREAD_POOL_PARAM_BACKLOAD, (void *)&count );
    822 
    823 	if ( rc == 0 ) {
    824 		return count;
    825 	}
    826 
    827 	return rc;
    828 }
    829 
    830 
    831 /*
    832  * wrapper for ldap_pvt_thread_pool_close+free(), left around
    833  * for backwards compatibility
    834  */
    835 int
    836 ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending )
    837 {
    838 	int rc;
    839 
    840 	if ( (rc = ldap_pvt_thread_pool_close( tpool, run_pending )) ) {
    841 		return rc;
    842 	}
    843 
    844 	return ldap_pvt_thread_pool_free( tpool );
    845 }
    846 
    847 /* Shut down the pool making its threads finish */
    848 int
    849 ldap_pvt_thread_pool_close ( ldap_pvt_thread_pool_t *tpool, int run_pending )
    850 {
    851 	struct ldap_int_thread_pool_s *pool, *pptr;
    852 	struct ldap_int_thread_poolq_s *pq;
    853 	ldap_int_thread_task_t *task;
    854 	int i;
    855 
    856 	if (tpool == NULL)
    857 		return(-1);
    858 
    859 	pool = *tpool;
    860 
    861 	if (pool == NULL) return(-1);
    862 
    863 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
    864 	LDAP_STAILQ_FOREACH(pptr, &ldap_int_thread_pool_list, ltp_next)
    865 		if (pptr == pool) break;
    866 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
    867 
    868 	if (pool != pptr) return(-1);
    869 
    870 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
    871 
    872 	pool->ltp_finishing = 1;
    873 	if (pool->ltp_max_pending > 0)
    874 		pool->ltp_max_pending = -pool->ltp_max_pending;
    875 
    876 	ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
    877 	ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
    878 
    879 	for (i=0; i<pool->ltp_numqs; i++) {
    880 		pq = pool->ltp_wqs[i];
    881 		ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
    882 		if (pq->ltp_max_pending > 0)
    883 			pq->ltp_max_pending = -pq->ltp_max_pending;
    884 		if (!run_pending) {
    885 			while ((task = LDAP_STAILQ_FIRST(&pq->ltp_pending_list)) != NULL) {
    886 				LDAP_STAILQ_REMOVE_HEAD(&pq->ltp_pending_list, ltt_next.q);
    887 				LDAP_FREE(task);
    888 			}
    889 			pq->ltp_pending_count = 0;
    890 		}
    891 
    892 		while (pq->ltp_open_count) {
    893 			ldap_pvt_thread_cond_broadcast(&pq->ltp_cond);
    894 			ldap_pvt_thread_cond_wait(&pq->ltp_cond, &pq->ltp_mutex);
    895 		}
    896 
    897 		while ((task = LDAP_SLIST_FIRST(&pq->ltp_free_list)) != NULL)
    898 		{
    899 			LDAP_SLIST_REMOVE_HEAD(&pq->ltp_free_list, ltt_next.l);
    900 			LDAP_FREE(task);
    901 		}
    902 		ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
    903 	}
    904 
    905 	return(0);
    906 }
    907 
    908 /* Destroy the pool, everything must have already shut down */
    909 int
    910 ldap_pvt_thread_pool_free ( ldap_pvt_thread_pool_t *tpool )
    911 {
    912 	struct ldap_int_thread_pool_s *pool, *pptr;
    913 	struct ldap_int_thread_poolq_s *pq;
    914 	int i;
    915 
    916 	if (tpool == NULL)
    917 		return(-1);
    918 
    919 	pool = *tpool;
    920 
    921 	if (pool == NULL) return(-1);
    922 
    923 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
    924 	LDAP_STAILQ_FOREACH(pptr, &ldap_int_thread_pool_list, ltp_next)
    925 		if (pptr == pool) break;
    926 	if (pptr == pool)
    927 		LDAP_STAILQ_REMOVE(&ldap_int_thread_pool_list, pool,
    928 			ldap_int_thread_pool_s, ltp_next);
    929 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
    930 
    931 	if (pool != pptr) return(-1);
    932 
    933 	ldap_pvt_thread_cond_destroy(&pool->ltp_pcond);
    934 	ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
    935 	ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex);
    936 	for (i=0; i<pool->ltp_numqs; i++) {
    937 		pq = pool->ltp_wqs[i];
    938 
    939 		assert( !pq->ltp_open_count );
    940 		assert( LDAP_SLIST_EMPTY(&pq->ltp_free_list) );
    941 		ldap_pvt_thread_cond_destroy(&pq->ltp_cond);
    942 		ldap_pvt_thread_mutex_destroy(&pq->ltp_mutex);
    943 		if (pq->ltp_free) {
    944 			LDAP_FREE(pq->ltp_free);
    945 		}
    946 	}
    947 	LDAP_FREE(pool->ltp_wqs);
    948 	LDAP_FREE(pool);
    949 	*tpool = NULL;
    950 	ldap_int_has_thread_pool = 0;
    951 	return(0);
    952 }
    953 
    954 /* Thread loop.  Accept and handle submitted tasks. */
    955 static void *
    956 ldap_int_thread_pool_wrapper (
    957 	void *xpool )
    958 {
    959 	struct ldap_int_thread_poolq_s *pq = xpool;
    960 	struct ldap_int_thread_pool_s *pool = pq->ltp_pool;
    961 	ldap_int_thread_task_t *task;
    962 	ldap_int_tpool_plist_t *work_list;
    963 	ldap_int_thread_userctx_t ctx, *kctx;
    964 	unsigned i, keyslot, hash;
    965 	int pool_lock = 0, freeme = 0;
    966 
    967 	assert(pool != NULL);
    968 
    969 	for ( i=0; i<MAXKEYS; i++ ) {
    970 		ctx.ltu_key[i].ltk_key = NULL;
    971 	}
    972 
    973 	ctx.ltu_pq = pq;
    974 	ctx.ltu_id = ldap_pvt_thread_self();
    975 	TID_HASH(ctx.ltu_id, hash);
    976 
    977 	ldap_pvt_thread_key_setdata( ldap_tpool_key, &ctx );
    978 
    979 	if (pool->ltp_pause) {
    980 		ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
    981 		/* thread_keys[] is read-only when paused */
    982 		while (pool->ltp_pause)
    983 			ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
    984 		ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
    985 	}
    986 
    987 	/* find a key slot to give this thread ID and store a
    988 	 * pointer to our keys there; start at the thread ID
    989 	 * itself (mod LDAP_MAXTHR) and look for an empty slot.
    990 	 */
    991 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
    992 	for (keyslot = hash & (LDAP_MAXTHR-1);
    993 		(kctx = thread_keys[keyslot].ctx) && kctx != DELETED_THREAD_CTX;
    994 		keyslot = (keyslot+1) & (LDAP_MAXTHR-1));
    995 	thread_keys[keyslot].ctx = &ctx;
    996 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
    997 
    998 	ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
    999 	pq->ltp_starting--;
   1000 	pq->ltp_active_count++;
   1001 
   1002 	for (;;) {
   1003 		work_list = pq->ltp_work_list; /* help the compiler a bit */
   1004 		task = LDAP_STAILQ_FIRST(work_list);
   1005 		if (task == NULL) {	/* paused or no pending tasks */
   1006 			if (--(pq->ltp_active_count) < 1) {
   1007 				if (pool->ltp_pause) {
   1008 					ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1009 					ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
   1010 					pool_lock = 1;
   1011 					if (--(pool->ltp_active_queues) < 1) {
   1012 						/* Notify pool_pause it is the sole active thread. */
   1013 						ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
   1014 					}
   1015 				}
   1016 			}
   1017 
   1018 			do {
   1019 				if (pool->ltp_finishing || pq->ltp_open_count > pq->ltp_max_count) {
   1020 					/* Not paused, and either finishing or too many
   1021 					 * threads running (can happen if ltp_max_count
   1022 					 * was reduced).  Let this thread die.
   1023 					 */
   1024 					goto done;
   1025 				}
   1026 
   1027 				/* We could check an idle timer here, and let the
   1028 				 * thread die if it has been inactive for a while.
   1029 				 * Only die if there are other open threads (i.e.,
   1030 				 * always have at least one thread open).
   1031 				 * The check should be like this:
   1032 				 *   if (pool->ltp_open_count>1 && pool->ltp_starting==0)
   1033 				 *       check timer, wait if ltp_pause, leave thread;
   1034 				 *
   1035 				 * Just use pthread_cond_timedwait() if we want to
   1036 				 * check idle time.
   1037 				 */
   1038 				if (pool_lock) {
   1039 					ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
   1040 					if (!pool->ltp_pause) {
   1041 						ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1042 						ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1043 						pool_lock = 0;
   1044 					}
   1045 				} else
   1046 					ldap_pvt_thread_cond_wait(&pq->ltp_cond, &pq->ltp_mutex);
   1047 
   1048 				work_list = pq->ltp_work_list;
   1049 				task = LDAP_STAILQ_FIRST(work_list);
   1050 			} while (task == NULL);
   1051 
   1052 			if (pool_lock) {
   1053 				ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1054 				ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1055 				pool_lock = 0;
   1056 			}
   1057 			pq->ltp_active_count++;
   1058 		}
   1059 
   1060 		LDAP_STAILQ_REMOVE_HEAD(work_list, ltt_next.q);
   1061 		pq->ltp_pending_count--;
   1062 		ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1063 
   1064 		task->ltt_start_routine(&ctx, task->ltt_arg);
   1065 
   1066 		ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1067 		LDAP_SLIST_INSERT_HEAD(&pq->ltp_free_list, task, ltt_next.l);
   1068 	}
   1069  done:
   1070 
   1071 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
   1072 
   1073 	/* The pool_mutex lock protects ctx->ltu_key from pool_purgekey()
   1074 	 * during this call, since it prevents new pauses. */
   1075 	ldap_pvt_thread_pool_context_reset(&ctx);
   1076 
   1077 	thread_keys[keyslot].ctx = DELETED_THREAD_CTX;
   1078 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
   1079 
   1080 	pq->ltp_open_count--;
   1081 	if (pq->ltp_open_count == 0) {
   1082 		if (pool->ltp_finishing)
   1083 			/* let pool_destroy know we're all done */
   1084 			ldap_pvt_thread_cond_signal(&pq->ltp_cond);
   1085 		else
   1086 			freeme = 1;
   1087 	}
   1088 
   1089 	if (pool_lock)
   1090 		ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1091 	else
   1092 		ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1093 
   1094 	if (freeme) {
   1095 		ldap_pvt_thread_cond_destroy(&pq->ltp_cond);
   1096 		ldap_pvt_thread_mutex_destroy(&pq->ltp_mutex);
   1097 		LDAP_FREE(pq->ltp_free);
   1098 		pq->ltp_free = NULL;
   1099 	}
   1100 	ldap_pvt_thread_exit(NULL);
   1101 	return(NULL);
   1102 }
   1103 
   1104 /* Arguments > ltp_pause to handle_pause(,PAUSE_ARG()).  arg=PAUSE_ARG
   1105  * ensures (arg-ltp_pause) sets GO_* at need and keeps DO_PAUSE/GO_*.
   1106  */
   1107 #define GO_IDLE		8
   1108 #define GO_UNIDLE	16
   1109 #define CHECK_PAUSE	32	/* if ltp_pause: GO_IDLE; wait; GO_UNIDLE */
   1110 #define DO_PAUSE	64	/* CHECK_PAUSE; pause the pool */
   1111 #define PAUSE_ARG(a) \
   1112 		((a) | ((a) & (GO_IDLE|GO_UNIDLE) ? GO_IDLE-1 : CHECK_PAUSE))
   1113 
   1114 static int
   1115 handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
   1116 {
   1117 	struct ldap_int_thread_pool_s *pool;
   1118 	struct ldap_int_thread_poolq_s *pq;
   1119 	int ret = 0, pause, max_ltp_pause;
   1120 
   1121 	if (tpool == NULL)
   1122 		return(-1);
   1123 
   1124 	pool = *tpool;
   1125 
   1126 	if (pool == NULL)
   1127 		return(0);
   1128 
   1129 	if (pause_type == CHECK_PAUSE && !pool->ltp_pause)
   1130 		return(0);
   1131 
   1132 	{
   1133 		ldap_int_thread_userctx_t *ctx = ldap_pvt_thread_pool_context();
   1134 		pq = ctx->ltu_pq;
   1135 		if ( !pq )
   1136 			return(-1);
   1137 	}
   1138 
   1139 	/* Let pool_unidle() ignore requests for new pauses */
   1140 	max_ltp_pause = pause_type==PAUSE_ARG(GO_UNIDLE) ? WANT_PAUSE : NOT_PAUSED;
   1141 
   1142 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
   1143 
   1144 	pause = pool->ltp_pause;	/* NOT_PAUSED, WANT_PAUSE or PAUSED */
   1145 
   1146 	/* If ltp_pause and not GO_IDLE|GO_UNIDLE: Set GO_IDLE,GO_UNIDLE */
   1147 	pause_type -= pause;
   1148 
   1149 	if (pause_type & GO_IDLE) {
   1150 		int do_pool = 0;
   1151 		ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1152 		pq->ltp_pending_count++;
   1153 		pq->ltp_active_count--;
   1154 		if (pause && pq->ltp_active_count < 1) {
   1155 			do_pool = 1;
   1156 		}
   1157 		ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1158 		if (do_pool) {
   1159 			pool->ltp_active_queues--;
   1160 			if (pool->ltp_active_queues < 1)
   1161 			/* Tell the task waiting to DO_PAUSE it can proceed */
   1162 				ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
   1163 		}
   1164 	}
   1165 
   1166 	if (pause_type & GO_UNIDLE) {
   1167 		/* Wait out pause if any, then cancel GO_IDLE */
   1168 		if (pause > max_ltp_pause) {
   1169 			ret = 1;
   1170 			do {
   1171 				ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
   1172 			} while (pool->ltp_pause > max_ltp_pause);
   1173 		}
   1174 		ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1175 		pq->ltp_pending_count--;
   1176 		pq->ltp_active_count++;
   1177 		ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1178 	}
   1179 
   1180 	if (pause_type & DO_PAUSE) {
   1181 		int i, j;
   1182 		/* Tell everyone else to pause or finish, then await that */
   1183 		ret = 0;
   1184 		assert(!pool->ltp_pause);
   1185 		pool->ltp_pause = WANT_PAUSE;
   1186 		pool->ltp_active_queues = 0;
   1187 
   1188 		for (i=0; i<pool->ltp_numqs; i++)
   1189 			if (pool->ltp_wqs[i] == pq) break;
   1190 
   1191 		ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1192 		/* temporarily remove ourself from active count */
   1193 		pq->ltp_active_count--;
   1194 
   1195 		j=i;
   1196 		do {
   1197 			pq = pool->ltp_wqs[j];
   1198 			if (j != i)
   1199 				ldap_pvt_thread_mutex_lock(&pq->ltp_mutex);
   1200 
   1201 			/* Hide pending tasks from ldap_pvt_thread_pool_wrapper() */
   1202 			pq->ltp_work_list = &empty_pending_list;
   1203 
   1204 			if (pq->ltp_active_count > 0)
   1205 				pool->ltp_active_queues++;
   1206 
   1207 			ldap_pvt_thread_mutex_unlock(&pq->ltp_mutex);
   1208 			if (pool->ltp_numqs > 1) {
   1209 				j++;
   1210 				j %= pool->ltp_numqs;
   1211 			}
   1212 		} while (j != i);
   1213 
   1214 		/* Wait for this task to become the sole active task */
   1215 		while (pool->ltp_active_queues > 0)
   1216 			ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
   1217 
   1218 		/* restore us to active count */
   1219 		pool->ltp_wqs[i]->ltp_active_count++;
   1220 
   1221 		assert(pool->ltp_pause == WANT_PAUSE);
   1222 		pool->ltp_pause = PAUSED;
   1223 	}
   1224 	ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1225 
   1226 	return(ret);
   1227 }
   1228 
   1229 /* Consider this task idle: It will not block pool_pause() in other tasks. */
   1230 void
   1231 ldap_pvt_thread_pool_idle( ldap_pvt_thread_pool_t *tpool )
   1232 {
   1233 	handle_pause(tpool, PAUSE_ARG(GO_IDLE));
   1234 }
   1235 
   1236 /* Cancel pool_idle(). If the pool is paused, wait it out first. */
   1237 void
   1238 ldap_pvt_thread_pool_unidle( ldap_pvt_thread_pool_t *tpool )
   1239 {
   1240 	handle_pause(tpool, PAUSE_ARG(GO_UNIDLE));
   1241 }
   1242 
   1243 /*
   1244  * If a pause was requested, wait for it.  If several threads
   1245  * are waiting to pause, let through one or more pauses.
   1246  * The calling task must be active, not idle.
   1247  * Return 1 if we waited, 0 if not, -1 at parameter error.
   1248  */
   1249 int
   1250 ldap_pvt_thread_pool_pausewait( ldap_pvt_thread_pool_t *tpool )
   1251 {
   1252 	return handle_pause(tpool, PAUSE_ARG(CHECK_PAUSE));
   1253 }
   1254 
   1255 /* Return 1 if a pause has been requested */
   1256 int
   1257 ldap_pvt_thread_pool_pausequery( ldap_pvt_thread_pool_t *tpool )
   1258 {
   1259 	struct ldap_int_thread_pool_s *pool;
   1260 	if ( !tpool )
   1261 		return -1;
   1262 
   1263 	pool = *tpool;
   1264 	if ( !pool )
   1265 		return 0;
   1266 
   1267 	return pool->ltp_pause != 0;
   1268 }
   1269 
   1270 /*
   1271  * Wait for a pause, from a non-pooled thread.
   1272  */
   1273 int
   1274 ldap_pvt_thread_pool_pausecheck_native( ldap_pvt_thread_pool_t *tpool )
   1275 {
   1276 	struct ldap_int_thread_pool_s *pool;
   1277 
   1278 	if (tpool == NULL)
   1279 		return(-1);
   1280 
   1281 	pool = *tpool;
   1282 
   1283 	if (pool == NULL)
   1284 		return(0);
   1285 
   1286 	if (!pool->ltp_pause)
   1287 		return(0);
   1288 
   1289 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
   1290 	while (pool->ltp_pause)
   1291 			ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
   1292 	ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1293 	return 1;
   1294 }
   1295 
   1296 /*
   1297  * Pause the pool.  The calling task must be active, not idle.
   1298  * Return when all other tasks are paused or idle.
   1299  */
   1300 int
   1301 ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool )
   1302 {
   1303 	return handle_pause(tpool, PAUSE_ARG(DO_PAUSE));
   1304 }
   1305 
   1306 /* End a pause */
   1307 int
   1308 ldap_pvt_thread_pool_resume (
   1309 	ldap_pvt_thread_pool_t *tpool )
   1310 {
   1311 	struct ldap_int_thread_pool_s *pool;
   1312 	struct ldap_int_thread_poolq_s *pq;
   1313 	int i;
   1314 
   1315 	if (tpool == NULL)
   1316 		return(-1);
   1317 
   1318 	pool = *tpool;
   1319 
   1320 	if (pool == NULL)
   1321 		return(0);
   1322 
   1323 	ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
   1324 	assert(pool->ltp_pause == PAUSED);
   1325 	pool->ltp_pause = 0;
   1326 	for (i=0; i<pool->ltp_numqs; i++) {
   1327 		pq = pool->ltp_wqs[i];
   1328 		pq->ltp_work_list = &pq->ltp_pending_list;
   1329 		ldap_pvt_thread_cond_broadcast(&pq->ltp_cond);
   1330 	}
   1331 	ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
   1332 	ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
   1333 	return(0);
   1334 }
   1335 
   1336 /*
   1337  * Get the key's data and optionally free function in the given context.
   1338  */
   1339 int ldap_pvt_thread_pool_getkey(
   1340 	void *xctx,
   1341 	void *key,
   1342 	void **data,
   1343 	ldap_pvt_thread_pool_keyfree_t **kfree )
   1344 {
   1345 	ldap_int_thread_userctx_t *ctx = xctx;
   1346 	int i;
   1347 
   1348 	if ( !ctx || !key || !data ) return EINVAL;
   1349 
   1350 	for ( i=0; i<MAXKEYS && ctx->ltu_key[i].ltk_key; i++ ) {
   1351 		if ( ctx->ltu_key[i].ltk_key == key ) {
   1352 			*data = ctx->ltu_key[i].ltk_data;
   1353 			if ( kfree ) *kfree = ctx->ltu_key[i].ltk_free;
   1354 			return 0;
   1355 		}
   1356 	}
   1357 	return ENOENT;
   1358 }
   1359 
   1360 static void
   1361 clear_key_idx( ldap_int_thread_userctx_t *ctx, int i )
   1362 {
   1363 	for ( ; i < MAXKEYS-1 && ctx->ltu_key[i+1].ltk_key; i++ )
   1364 		ctx->ltu_key[i] = ctx->ltu_key[i+1];
   1365 	ctx->ltu_key[i].ltk_key = NULL;
   1366 }
   1367 
   1368 /*
   1369  * Set or remove data for the key in the given context.
   1370  * key can be any unique pointer.
   1371  * kfree() is an optional function to free the data (but not the key):
   1372  *   pool_context_reset() and pool_purgekey() call kfree(key, data),
   1373  *   but pool_setkey() does not.  For pool_setkey() it is the caller's
   1374  *   responsibility to free any existing data with the same key.
   1375  *   kfree() must not call functions taking a tpool argument.
   1376  */
   1377 int ldap_pvt_thread_pool_setkey(
   1378 	void *xctx,
   1379 	void *key,
   1380 	void *data,
   1381 	ldap_pvt_thread_pool_keyfree_t *kfree,
   1382 	void **olddatap,
   1383 	ldap_pvt_thread_pool_keyfree_t **oldkfreep )
   1384 {
   1385 	ldap_int_thread_userctx_t *ctx = xctx;
   1386 	int i, found;
   1387 
   1388 	if ( !ctx || !key ) return EINVAL;
   1389 
   1390 	for ( i=found=0; i<MAXKEYS; i++ ) {
   1391 		if ( ctx->ltu_key[i].ltk_key == key ) {
   1392 			found = 1;
   1393 			break;
   1394 		} else if ( !ctx->ltu_key[i].ltk_key ) {
   1395 			break;
   1396 		}
   1397 	}
   1398 
   1399 	if ( olddatap ) {
   1400 		if ( found ) {
   1401 			*olddatap = ctx->ltu_key[i].ltk_data;
   1402 		} else {
   1403 			*olddatap = NULL;
   1404 		}
   1405 	}
   1406 
   1407 	if ( oldkfreep ) {
   1408 		if ( found ) {
   1409 			*oldkfreep = ctx->ltu_key[i].ltk_free;
   1410 		} else {
   1411 			*oldkfreep = 0;
   1412 		}
   1413 	}
   1414 
   1415 	if ( data || kfree ) {
   1416 		if ( i>=MAXKEYS )
   1417 			return ENOMEM;
   1418 		ctx->ltu_key[i].ltk_key = key;
   1419 		ctx->ltu_key[i].ltk_data = data;
   1420 		ctx->ltu_key[i].ltk_free = kfree;
   1421 	} else if ( found ) {
   1422 		clear_key_idx( ctx, i );
   1423 	}
   1424 
   1425 	return 0;
   1426 }
   1427 
   1428 /* Free all elements with this key, no matter which thread they're in.
   1429  * May only be called while the pool is paused.
   1430  */
   1431 void ldap_pvt_thread_pool_purgekey( void *key )
   1432 {
   1433 	int i, j;
   1434 	ldap_int_thread_userctx_t *ctx;
   1435 
   1436 	assert ( key != NULL );
   1437 
   1438 	ldap_pvt_thread_mutex_lock(&ldap_pvt_thread_pool_mutex);
   1439 	for ( i=0; i<LDAP_MAXTHR; i++ ) {
   1440 		ctx = thread_keys[i].ctx;
   1441 		if ( ctx && ctx != DELETED_THREAD_CTX ) {
   1442 			for ( j=0; j<MAXKEYS && ctx->ltu_key[j].ltk_key; j++ ) {
   1443 				if ( ctx->ltu_key[j].ltk_key == key ) {
   1444 					if (ctx->ltu_key[j].ltk_free)
   1445 						ctx->ltu_key[j].ltk_free( ctx->ltu_key[j].ltk_key,
   1446 						ctx->ltu_key[j].ltk_data );
   1447 					clear_key_idx( ctx, j );
   1448 					break;
   1449 				}
   1450 			}
   1451 		}
   1452 	}
   1453 	ldap_pvt_thread_mutex_unlock(&ldap_pvt_thread_pool_mutex);
   1454 }
   1455 
   1456 /*
   1457  * Find the context of the current thread.
   1458  * This is necessary if the caller does not have access to the
   1459  * thread context handle (for example, a slapd plugin calling
   1460  * slapi_search_internal()). No doubt it is more efficient
   1461  * for the application to keep track of the thread context
   1462  * handles itself.
   1463  */
   1464 void *ldap_pvt_thread_pool_context( )
   1465 {
   1466 	void *ctx = NULL;
   1467 
   1468 	ldap_pvt_thread_key_getdata( ldap_tpool_key, &ctx );
   1469 	return ctx ? ctx : (void *) &ldap_int_main_thrctx;
   1470 }
   1471 
   1472 /*
   1473  * Free the context's keys.
   1474  * Must not call functions taking a tpool argument (because this
   1475  * thread already holds ltp_mutex when called from pool_wrapper()).
   1476  */
   1477 void ldap_pvt_thread_pool_context_reset( void *vctx )
   1478 {
   1479 	ldap_int_thread_userctx_t *ctx = vctx;
   1480 	int i;
   1481 
   1482 	for ( i=MAXKEYS-1; i>=0; i--) {
   1483 		if ( !ctx->ltu_key[i].ltk_key )
   1484 			continue;
   1485 		if ( ctx->ltu_key[i].ltk_free )
   1486 			ctx->ltu_key[i].ltk_free( ctx->ltu_key[i].ltk_key,
   1487 			ctx->ltu_key[i].ltk_data );
   1488 		ctx->ltu_key[i].ltk_key = NULL;
   1489 	}
   1490 }
   1491 
   1492 ldap_pvt_thread_t ldap_pvt_thread_pool_tid( void *vctx )
   1493 {
   1494 	ldap_int_thread_userctx_t *ctx = vctx;
   1495 
   1496 	return ctx->ltu_id;
   1497 }
   1498 #endif /* LDAP_THREAD_HAVE_TPOOL */
   1499 
   1500 #endif /* LDAP_R_COMPILE */
   1501