return(0);
}
-typedef struct ldap_lazy_sem_t {
- ldap_pvt_thread_mutex_t ls_mutex;
- ldap_pvt_thread_cond_t ls_cond;
- int ls_sem_value;
- /*
- * when more than ls_lazy_count number of resources
- * becmoes available, the thread wating for the resources will
- * be waken up in order to prevent frequent blocking/waking-up
- */
- unsigned int ls_lazy_count;
- /*
- * only one thread(listener) will wait on this semaphore
- * using a flag instead of a list
- */
- int ls_wait;
-} ldap_lazy_sem_t;
-
-ldap_lazy_sem_t* thread_pool_sem = NULL;
-
-int
-ldap_lazy_sem_init( unsigned int value, unsigned int lazyness )
-{
- thread_pool_sem = (ldap_lazy_sem_t*) LDAP_CALLOC(1,
- sizeof( ldap_lazy_sem_t ));
-
- if( thread_pool_sem == NULL ) return -1;
-
- ldap_pvt_thread_mutex_init( &thread_pool_sem->ls_mutex );
- ldap_pvt_thread_cond_init( &thread_pool_sem->ls_cond );
- thread_pool_sem->ls_sem_value = value;
- thread_pool_sem->ls_lazy_count = lazyness;
- thread_pool_sem->ls_wait = 0;
-
- return 0;
-}
-
-/* FIXME: move to some approprite header */
-int ldap_lazy_sem_dec( ldap_lazy_sem_t* ls );
-int ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls );
-
-/*
- * ldap_lazy_sem_wait is used if a caller is blockable(listener).
- * Otherwise use ldap_lazy_sem_dec (worker)
- */
-int
-ldap_lazy_sem_op_submit( ldap_lazy_sem_t* ls )
-{
- if ( ls == NULL ) return -1;
-
- /* only worker thread has its thread ctx */
- if ( ldap_pvt_thread_pool_context() ) {
- /* worker thread */
- return ldap_lazy_sem_dec( ls );
- } else {
- /* listener */
- return ldap_lazy_sem_wait( ls );
- }
-}
-
-/*
- * test if given semaphore's count is zero.
- * If 0, the caller is blocked
- * If not, the count is decremented.
- */
-int
-ldap_lazy_sem_wait ( ldap_lazy_sem_t* ls )
-{
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
-lazy_sem_retry:
- if ( ls->ls_sem_value <= 0 ) {
- /* no more avaliable resources */
- ls->ls_wait = 1;
- ldap_pvt_thread_cond_wait( &ls->ls_cond, &ls->ls_mutex );
- goto lazy_sem_retry;
- } else {
- /* avaliable resources */
- ls->ls_sem_value--;
- }
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
-
-/*
- * decrement the count without blocking
- * even when the count becomes less than or equal to 0
- */
-int
-ldap_lazy_sem_dec( ldap_lazy_sem_t* ls )
-{
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
- ls->ls_sem_value--;
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
-
-/*
- * Increment the count by one and test if it is greater or
- * equal to lazyness. If it is, wake up a blocked thread.
- */
-int
-ldap_lazy_sem_post( ldap_lazy_sem_t* ls )
-{
- if( ls == NULL ) return (-1);
-
- ldap_pvt_thread_mutex_lock( &ls->ls_mutex );
-
- ls->ls_sem_value++;
- if ( ls->ls_wait ) {
- if ( ls->ls_sem_value >= ls->ls_lazy_count ) {
- ls->ls_wait = 0;
- ldap_pvt_thread_cond_signal( &ls->ls_cond );
- }
- }
-
- ldap_pvt_thread_mutex_unlock( &ls->ls_mutex );
-
- return 0;
-}
/* Create a thread pool */
int
{
struct ldap_int_thread_pool_s *pool;
ldap_int_thread_ctx_t *ctx;
- int need_thread = 0;
ldap_pvt_thread_t thr;
if (tpool == NULL)
{
pool->ltp_open_count++;
pool->ltp_starting++;
- need_thread = 1;
- }
-
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
- ldap_lazy_sem_op_submit( thread_pool_sem );
- /* FIXME: Another thread can now handle and release ctx, after
- * which a newly submitted op can reuse ctx. Then it is wrong for
- * the "if (pool->ltp_open_count == 0)" code below to release ctx.
- */
-#endif
-
- if (need_thread) {
if (0 != ldap_pvt_thread_create(
&thr, 1, ldap_int_thread_pool_wrapper, pool))
{
/* couldn't create thread. back out of
* ltp_open_count and check for even worse things.
*/
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-#endif
pool->ltp_starting--;
pool->ltp_open_count--;
if (pool->ltp_open_count == 0) {
return(-1);
}
}
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-#endif
/* there is another open thread, so this
* context will be handled eventually.
* continue on, we have signalled that
}
}
-#ifndef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-#endif
-
return(0);
}
ldap_pvt_thread_cond_destroy(&pool->ltp_cond);
ldap_pvt_thread_mutex_destroy(&pool->ltp_mutex);
LDAP_FREE(pool);
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- if ( thread_pool_sem ) {
- LDAP_FREE( thread_pool_sem );
- }
-#endif
ldap_int_has_thread_pool = 0;
return(0);
}
ctx->ltc_start_routine(&uctx, ctx->ltc_arg);
-#ifdef LDAP_PVT_THREAD_POOL_SEM_LOAD_CONTROL
- ldap_lazy_sem_post( thread_pool_sem );
-#endif
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, ctx, ltc_next.l);
pool->ltp_active_count--;