mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
ITS#7115: Tighten ldap_pvt_thread_pool_unidle().
Only wait out already-started pauses, not pause reqests. ltp_pause now says whether a pause is requested or has started. This reduces the chance that slapd:send_ldap_ber() will start a pause in the middle of an operation.
This commit is contained in:
parent
a8f6deee03
commit
23f3657807
@ -50,6 +50,9 @@ typedef struct ldap_int_tpool_key_s {
|
|||||||
/* (Theoretical) max number of pending requests */
|
/* (Theoretical) max number of pending requests */
|
||||||
#define MAX_PENDING (INT_MAX/2) /* INT_MAX - (room to avoid overflow) */
|
#define MAX_PENDING (INT_MAX/2) /* INT_MAX - (room to avoid overflow) */
|
||||||
|
|
||||||
|
/* pool->ltp_pause values */
|
||||||
|
enum { NOT_PAUSED = 0, WANT_PAUSE = 1, PAUSED = 2 };
|
||||||
|
|
||||||
/* Context: thread ID and thread-specific key/data pairs */
|
/* Context: thread ID and thread-specific key/data pairs */
|
||||||
typedef struct ldap_int_thread_userctx_s {
|
typedef struct ldap_int_thread_userctx_s {
|
||||||
ldap_pvt_thread_t ltu_id;
|
ldap_pvt_thread_t ltu_id;
|
||||||
@ -462,7 +465,7 @@ ldap_pvt_thread_pool_query(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LDAP_PVT_THREAD_POOL_PARAM_PAUSING:
|
case LDAP_PVT_THREAD_POOL_PARAM_PAUSING:
|
||||||
count = pool->ltp_pause;
|
count = (pool->ltp_pause != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LDAP_PVT_THREAD_POOL_PARAM_PENDING:
|
case LDAP_PVT_THREAD_POOL_PARAM_PENDING:
|
||||||
@ -512,7 +515,7 @@ ldap_pvt_thread_pool_pausing( ldap_pvt_thread_pool_t *tpool )
|
|||||||
struct ldap_int_thread_pool_s *pool;
|
struct ldap_int_thread_pool_s *pool;
|
||||||
|
|
||||||
if ( tpool != NULL && (pool = *tpool) != NULL ) {
|
if ( tpool != NULL && (pool = *tpool) != NULL ) {
|
||||||
rc = pool->ltp_pause;
|
rc = (pool->ltp_pause != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -716,7 +719,7 @@ ldap_int_thread_pool_wrapper (
|
|||||||
*/
|
*/
|
||||||
#define GO_IDLE 8
|
#define GO_IDLE 8
|
||||||
#define GO_UNIDLE 16
|
#define GO_UNIDLE 16
|
||||||
#define CHECK_PAUSE 32 /* if (ltp_pause) { GO_IDLE; GO_UNIDLE; } */
|
#define CHECK_PAUSE 32 /* if ltp_pause: GO_IDLE; wait; GO_UNIDLE */
|
||||||
#define DO_PAUSE 64 /* CHECK_PAUSE; pause the pool */
|
#define DO_PAUSE 64 /* CHECK_PAUSE; pause the pool */
|
||||||
#define PAUSE_ARG(a) \
|
#define PAUSE_ARG(a) \
|
||||||
((a) | ((a) & (GO_IDLE|GO_UNIDLE) ? GO_IDLE-1 : CHECK_PAUSE))
|
((a) | ((a) & (GO_IDLE|GO_UNIDLE) ? GO_IDLE-1 : CHECK_PAUSE))
|
||||||
@ -725,7 +728,7 @@ static int
|
|||||||
handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
||||||
{
|
{
|
||||||
struct ldap_int_thread_pool_s *pool;
|
struct ldap_int_thread_pool_s *pool;
|
||||||
int ret = 0, pause;
|
int ret = 0, pause, max_ltp_pause;
|
||||||
|
|
||||||
if (tpool == NULL)
|
if (tpool == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
@ -738,9 +741,12 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
|||||||
if (pause_type == CHECK_PAUSE && !pool->ltp_pause)
|
if (pause_type == CHECK_PAUSE && !pool->ltp_pause)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
/* Let pool_unidle() ignore requests for new pauses */
|
||||||
|
max_ltp_pause = pause_type==PAUSE_ARG(GO_UNIDLE) ? WANT_PAUSE : NOT_PAUSED;
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
|
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
|
||||||
|
|
||||||
pause = pool->ltp_pause; /* 0 or 1 */
|
pause = pool->ltp_pause; /* NOT_PAUSED, WANT_PAUSE or PAUSED */
|
||||||
|
|
||||||
/* If ltp_pause and not GO_IDLE|GO_UNIDLE: Set GO_IDLE,GO_UNIDLE */
|
/* If ltp_pause and not GO_IDLE|GO_UNIDLE: Set GO_IDLE,GO_UNIDLE */
|
||||||
pause_type -= pause;
|
pause_type -= pause;
|
||||||
@ -756,9 +762,11 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
|||||||
|
|
||||||
if (pause_type & GO_UNIDLE) {
|
if (pause_type & GO_UNIDLE) {
|
||||||
/* Wait out pause if any, then cancel GO_IDLE */
|
/* Wait out pause if any, then cancel GO_IDLE */
|
||||||
ret = pause;
|
if (pause > max_ltp_pause) {
|
||||||
for (; pause; pause = pool->ltp_pause) {
|
ret = 1;
|
||||||
ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
|
do {
|
||||||
|
ldap_pvt_thread_cond_wait(&pool->ltp_cond, &pool->ltp_mutex);
|
||||||
|
} while (pool->ltp_pause > max_ltp_pause);
|
||||||
}
|
}
|
||||||
pool->ltp_pending_count--;
|
pool->ltp_pending_count--;
|
||||||
pool->ltp_active_count++;
|
pool->ltp_active_count++;
|
||||||
@ -768,7 +776,7 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
|||||||
/* Tell everyone else to pause or finish, then await that */
|
/* Tell everyone else to pause or finish, then await that */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
assert(!pool->ltp_pause);
|
assert(!pool->ltp_pause);
|
||||||
pool->ltp_pause = 1;
|
pool->ltp_pause = WANT_PAUSE;
|
||||||
/* Let ldap_pvt_thread_pool_submit() through to its ltp_pause test,
|
/* Let ldap_pvt_thread_pool_submit() through to its ltp_pause test,
|
||||||
* and do not finish threads in ldap_pvt_thread_pool_wrapper() */
|
* and do not finish threads in ldap_pvt_thread_pool_wrapper() */
|
||||||
pool->ltp_open_count = -pool->ltp_open_count;
|
pool->ltp_open_count = -pool->ltp_open_count;
|
||||||
@ -779,6 +787,8 @@ handle_pause( ldap_pvt_thread_pool_t *tpool, int pause_type )
|
|||||||
while (pool->ltp_active_count > 1) {
|
while (pool->ltp_active_count > 1) {
|
||||||
ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
|
ldap_pvt_thread_cond_wait(&pool->ltp_pcond, &pool->ltp_mutex);
|
||||||
}
|
}
|
||||||
|
assert(pool->ltp_pause == WANT_PAUSE);
|
||||||
|
pool->ltp_pause = PAUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
|
ldap_pvt_thread_mutex_unlock(&pool->ltp_mutex);
|
||||||
@ -792,7 +802,7 @@ ldap_pvt_thread_pool_idle( ldap_pvt_thread_pool_t *tpool )
|
|||||||
handle_pause(tpool, PAUSE_ARG(GO_IDLE));
|
handle_pause(tpool, PAUSE_ARG(GO_IDLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel pool_idle(). If a pause was requested, wait for it first. */
|
/* Cancel pool_idle(). If the pool is paused, wait it out first. */
|
||||||
void
|
void
|
||||||
ldap_pvt_thread_pool_unidle( ldap_pvt_thread_pool_t *tpool )
|
ldap_pvt_thread_pool_unidle( ldap_pvt_thread_pool_t *tpool )
|
||||||
{
|
{
|
||||||
@ -838,7 +848,7 @@ ldap_pvt_thread_pool_resume (
|
|||||||
|
|
||||||
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
|
ldap_pvt_thread_mutex_lock(&pool->ltp_mutex);
|
||||||
|
|
||||||
assert(pool->ltp_pause);
|
assert(pool->ltp_pause == PAUSED);
|
||||||
pool->ltp_pause = 0;
|
pool->ltp_pause = 0;
|
||||||
if (pool->ltp_open_count <= 0) /* true when paused, but be paranoid */
|
if (pool->ltp_open_count <= 0) /* true when paused, but be paranoid */
|
||||||
pool->ltp_open_count = -pool->ltp_open_count;
|
pool->ltp_open_count = -pool->ltp_open_count;
|
||||||
|
Loading…
Reference in New Issue
Block a user