[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#6164) send_ldap_ber() spins holding c_write1_mutex



Full_Name: Hallvard B Furuseth
Version: HEAD
OS: 
URL: 
Submission from: (NULL) (129.240.6.233)
Submitted by: hallvard


send_ldap_ber() has a suspicious-looking waitloop doing this:

	if ( ldap_pvt_thread_mutex_trylock( &conn->c_mutex )) {
		ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
		ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );

Unlock does not mean a thread waiting for c_write1_mutex will acquire
it immediately.  Such a thread may have to wait until it is scheduled,
at which time the looping thread has locked the mutex again.

On the Linux box on my desk, a pure unlock-lock loop goes through
50000-100000 iterations before another thread waiting for the lock
acquires it.  OTOH, on a heavily used box it takes ~50 iterations.

A sched_yield() between the unlock and lock reduces #iterations to 1.
No idea if that is the right solution, nor how serious the problem is.

The lock/unlock statements themselves are from result.c rev 1.323,
but then with some more locking between them which disappeared in
later revisions.

My lock-unlock test program:

#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>

static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static unsigned count;

static void *waiter(void *arg) {
    pthread_mutex_lock(&m);
    printf("Locked after %u iterations.\n", count);
    exit(0);
}

int main() {
    pthread_t t;
    pthread_mutex_lock(&m);
    pthread_create(&t, NULL, waiter, NULL);
    select(0, NULL, NULL, NULL, &(struct timeval){0, 100000});
    for (count = 1 ;; ++count) {
	pthread_mutex_unlock(&m);
	pthread_mutex_lock(&m);
    }
}