]> git.sur5r.net Git - openldap/commitdiff
ITS#7115 blocked writers should not interfere with pool pause
authorHoward Chu <hyc@openldap.org>
Wed, 21 Dec 2011 09:24:23 +0000 (01:24 -0800)
committerHoward Chu <hyc@openldap.org>
Wed, 21 Dec 2011 09:24:23 +0000 (01:24 -0800)
include/ldap_pvt_thread.h
libraries/libldap_r/tpool.c
servers/slapd/result.c

index d9995df3780b7629da852107de9646aeae1b4758..8e94b887f8bf48de9d95615af001f3657e0b21d3 100644 (file)
@@ -261,6 +261,14 @@ LDAP_F( int )
 ldap_pvt_thread_pool_backload LDAP_P((
        ldap_pvt_thread_pool_t *pool ));
 
+LDAP_F( void )
+ldap_pvt_thread_pool_idle LDAP_P((
+       ldap_pvt_thread_pool_t *pool ));
+
+LDAP_F( void )
+ldap_pvt_thread_pool_unidle LDAP_P((
+       ldap_pvt_thread_pool_t *pool ));
+
 LDAP_F( int )
 ldap_pvt_thread_pool_pausecheck LDAP_P((
        ldap_pvt_thread_pool_t *pool ));
index 877f2191824f3d966c15fce4bf0ba77fbcebcbc8..e7881097cb564c9e477a9c612ec2f1a2642f6304 100644 (file)
@@ -711,10 +711,16 @@ ldap_int_thread_pool_wrapper (
        return(NULL);
 }
 
+#define        DO_PAUSE        0
+#define        CHECK_PAUSE     1
+#define        GO_IDLE 2
+#define        GO_UNIDLE       3
+
 static int
-handle_pause( ldap_pvt_thread_pool_t *tpool, int do_pause )
+handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
 {
        struct ldap_int_thread_pool_s *pool;
+       int ret = 0;
 
        if (tpool == NULL)
                return(-1);
@@ -724,26 +730,13 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int do_pause )
        if (pool == NULL)
                return(0);
 
-       if (! (do_pause || pool->ltp_pause))
+       if (pause_type == CHECK_PAUSE && !pool->ltp_pause)
                return(0);
 
        ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
 
-       /* If someone else has already requested a pause, we have to wait */
-       if (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);
-               do {
-                       ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
-               } while (pool->ltp_pause);
-               pool->ltp_pending_count--;
-               pool->ltp_active_count++;
-       }
-
-       if (do_pause) {
+       switch( pause_type ) {
+       case DO_PAUSE:
                /* Wait for everyone else to pause or finish */
                pool->ltp_pause = 1;
                /* Let ldap_pvt_thread_pool_submit() through to its ltp_pause test,
@@ -756,10 +749,48 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int do_pause )
                while (pool->ltp_active_count > 1) {
                        ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
                }
+               break;
+       case GO_UNIDLE:
+               pool->ltp_pending_count--;
+               pool->ltp_active_count++;
+               /* FALLTHRU */
+       case CHECK_PAUSE:
+       case GO_IDLE:
+       /* If someone else has already requested a pause, we have to wait */
+               if (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);
+                       do {
+                               ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
+                       } while (pool->ltp_pause);
+                       pool->ltp_pending_count--;
+                       pool->ltp_active_count++;
+                       ret = 1;
+               }
+               if (pause_type != GO_IDLE)
+                       break;
+               pool->ltp_pending_count++;
+               pool->ltp_active_count--;
+               break;
        }
 
        ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
-       return(!do_pause);
+       return(ret);
+}
+
+void
+ldap_pvt_thread_pool_idle( ldap_pvt_thread_pool_t *tpool )
+{
+       handle_pause( tpool, GO_IDLE );
+}
+
+void
+ldap_pvt_thread_pool_unidle( ldap_pvt_thread_pool_t *tpool )
+{
+       handle_pause( tpool, GO_UNIDLE );
 }
 
 /*
@@ -770,14 +801,14 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int do_pause )
 int
 ldap_pvt_thread_pool_pausecheck( ldap_pvt_thread_pool_t *tpool )
 {
-       return handle_pause( tpool, 0 );
+       return handle_pause( tpool, CHECK_PAUSE );
 }
 
 /* Pause the pool.  Return when all other threads are paused. */
 int
 ldap_pvt_thread_pool_pause( ldap_pvt_thread_pool_t *tpool )
 {
-       return handle_pause( tpool, 1 );
+       return handle_pause( tpool, DO_PAUSE );
 }
 
 /* End a pause */
index 8fa6cdda406d90c253eff87b4fac0f6a5b634369..ec39f7b495ac6e0e97c0f98e8804f2e1a6783459 100644 (file)
@@ -369,9 +369,11 @@ static long send_ldap_ber(
 
                ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+               ldap_pvt_thread_pool_idle( &connection_pool );
                ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
                conn->c_writewaiter = 0;
                ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
+               ldap_pvt_thread_pool_unidle( &connection_pool );
                ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
                if ( conn->c_writers < 0 ) {
                        ret = 0;