]> git.sur5r.net Git - openldap/commitdiff
Replace state LDAP_INT_THREAD_POOL_PAUSING with member ltp_pause,
authorHallvard Furuseth <hallvard@openldap.org>
Wed, 9 May 2007 19:53:25 +0000 (19:53 +0000)
committerHallvard Furuseth <hallvard@openldap.org>
Wed, 9 May 2007 19:53:25 +0000 (19:53 +0000)
so a pause will work during states FINISHING and STOPPING.

Add missing waits and signals, and move waits in pool_wrapper().
Replace if(test) with while(test) when waiting for the multi-purpose
condition variable ltp_cond.

libraries/libldap_r/tpool.c

index 20df9a862fd2b4d96e5e3a00a70317448dab1189..160d5ba460e15c3e891d6eaacb942fcc793d5851 100644 (file)
@@ -34,8 +34,7 @@
 typedef enum ldap_int_thread_pool_state_e {
        LDAP_INT_THREAD_POOL_RUNNING,
        LDAP_INT_THREAD_POOL_FINISHING,
-       LDAP_INT_THREAD_POOL_STOPPING,
-       LDAP_INT_THREAD_POOL_PAUSING
+       LDAP_INT_THREAD_POOL_STOPPING
 } ldap_int_thread_pool_state_t;
 
 typedef struct ldap_int_thread_key_s {
@@ -82,6 +81,7 @@ struct ldap_int_thread_pool_s {
        LDAP_SLIST_HEAD(tcl, ldap_int_thread_ctx_s) ltp_free_list;
        LDAP_SLIST_HEAD(tclq, ldap_int_thread_ctx_s) ltp_active_list;
        ldap_int_thread_pool_state_t ltp_state;
+       int ltp_pause;
        long ltp_max_count;
        long ltp_max_pending;
        long ltp_pending_count;
@@ -343,14 +343,14 @@ ldap_pvt_thread_pool_submit (
                return(-1);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-       if ((pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING &&
-               pool->ltp_state != LDAP_INT_THREAD_POOL_PAUSING)
+       if (pool->ltp_state != LDAP_INT_THREAD_POOL_RUNNING
                || (pool->ltp_max_pending > 0
                        && pool->ltp_pending_count >= pool->ltp_max_pending))
        {
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
                return(-1);
        }
+
        ctx = LDAP_SLIST_FIRST(&pool->ltp_free_list);
        if (ctx) {
                LDAP_SLIST_REMOVE_HEAD(&pool->ltp_free_list, ltc_next.l);
@@ -368,7 +368,7 @@ ldap_pvt_thread_pool_submit (
 
        pool->ltp_pending_count++;
        LDAP_STAILQ_INSERT_TAIL(&pool->ltp_pending_list, ctx, ltc_next.q);
-       if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+       if (pool->ltp_pause) {
                ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
                return(0);
        }
@@ -530,18 +530,21 @@ ldap_pvt_thread_pool_query ( ldap_pvt_thread_pool_t *tpool, ldap_pvt_thread_pool
                        { "running",    LDAP_INT_THREAD_POOL_RUNNING },
                        { "finishing",  LDAP_INT_THREAD_POOL_FINISHING },
                        { "stopping",   LDAP_INT_THREAD_POOL_STOPPING },
-                       { "pausing",    LDAP_INT_THREAD_POOL_PAUSING },
                        { NULL }
                };
                int             i;
 
-               for ( i = 0; str2state[ i ].name != NULL; i++ ) {
-                       if ( str2state[ i ].state == pool->ltp_state ) {
-                               break;
+               if ( pool->ltp_pause ) {
+                       *((char **)value) = "pausing";
+               } else {
+                       for ( i = 0; str2state[ i ].name != NULL; i++ ) {
+                               if ( str2state[ i ].state == pool->ltp_state ) {
+                                       break;
+                               }
                        }
+                       *((char **)value) = str2state[ i ].name;
                }
-               *((char **)value) = str2state[ i ].name;
-               if ( str2state[ i ].name != NULL ) {
+               if ( *((char **)value) != NULL ) {
                        count = -2;
                }
                } break;
@@ -602,8 +605,9 @@ ldap_pvt_thread_pool_destroy ( ldap_pvt_thread_pool_t *tpool, int run_pending )
                ? LDAP_INT_THREAD_POOL_FINISHING
                : LDAP_INT_THREAD_POOL_STOPPING;
 
-       if ( pool->ltp_open_count ) {
-               ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
+       while (pool->ltp_open_count) {
+               if (!pool->ltp_pause)
+                       ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
                ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
        }
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
@@ -660,13 +664,18 @@ ldap_int_thread_pool_wrapper (
        thread_keys[i].ctx = &uctx;
        keyslot = i;
 
-       while (pool->ltp_state != LDAP_INT_THREAD_POOL_STOPPING) {
+       for (;;) {
+               while (pool->ltp_pause)
+                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+
+               if (pool->ltp_state == LDAP_INT_THREAD_POOL_STOPPING)
+                       break;
+
                ctx = LDAP_STAILQ_FIRST(&pool->ltp_pending_list);
-               if (ctx) {
-                       LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
-               } else {
+               if (ctx == NULL) {
                        if (pool->ltp_state == LDAP_INT_THREAD_POOL_FINISHING)
                                break;
+
                        if (pool->ltp_max_count > 0
                                && pool->ltp_open_count > pool->ltp_max_count)
                        {
@@ -690,12 +699,12 @@ ldap_int_thread_pool_wrapper (
                         * check idle time.
                         */
 
-                       assert(pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING
-                                  || pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING);
+                       assert(pool->ltp_state == LDAP_INT_THREAD_POOL_RUNNING);
                        ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
                        continue;
                }
 
+               LDAP_STAILQ_REMOVE_HEAD(&pool->ltp_pending_list, ltc_next.q);
                pool->ltp_pending_count--;
 
                LDAP_SLIST_INSERT_HEAD(&pool->ltp_active_list, ctx, ltc_next.al);
@@ -713,12 +722,9 @@ ldap_int_thread_pool_wrapper (
                LDAP_SLIST_INSERT_HEAD(&pool->ltp_free_list, ctx, ltc_next.l);
                pool->ltp_active_count--;
 
-               if (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
-                       if (pool->ltp_active_count < 2) {
-                               ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
-                       }
-                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
-               }
+               /* let pool_pause know when it is the sole active thread */
+               if (pool->ltp_active_count < 2)
+                       ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
        }
 
        ldap_pvt_thread_pool_context_reset(&uctx);
@@ -755,18 +761,23 @@ ldap_pvt_thread_pool_pause (
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
        /* If someone else has already requested a pause, we have to wait */
-       while (pool->ltp_state == LDAP_INT_THREAD_POOL_PAUSING) {
+       while (pool->ltp_pause) {
                pool->ltp_pending_count++;
                pool->ltp_active_count--;
+               /* let the other pool_pause() know when it can proceed */
+               if (pool->ltp_active_count < 2)
+                       ldap_pvt_thread_cond_signal(&pool->ltp_pcond);
                ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
                pool->ltp_pending_count--;
                pool->ltp_active_count++;
        }
-       /* Wait for everyone else to finish */
-       pool->ltp_state = LDAP_INT_THREAD_POOL_PAUSING;
+
+       /* Wait for everyone else to pause or finish */
+       pool->ltp_pause = 1;
        while (pool->ltp_active_count > 1) {
                ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
        }
+
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        return(0);
 }
@@ -786,8 +797,7 @@ ldap_pvt_thread_pool_resume (
                return(0);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
-
-       pool->ltp_state = LDAP_INT_THREAD_POOL_RUNNING;
+       pool->ltp_pause = 0;
        ldap_pvt_thread_cond_broadcast(&pool->ltp_cond);
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
        return(0);