mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-15 03:01:09 +08:00
Fix dbcache/entry lock deadlock. If dbcache lock is held, it's
okay to read and write LDBM specific fields (state, refcnt, LRU. The id field, though is read-only once set. cache_find_entry_dn2id(), hence, does not require any entry locks. cache_find_entry_id() must do a entry_rdwr_trylock() and back off if busy. Add new rdwr lock code with trylock() functionality. Implement entry_rdwr_trylock().
This commit is contained in:
parent
6b05425d0f
commit
366701bdf7
@ -180,6 +180,9 @@ LDAP_F int
|
|||||||
ldap_pvt_thread_set_concurrency LDAP_P(( int ));
|
ldap_pvt_thread_set_concurrency LDAP_P(( int ));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LDAP_PVT_THREAD_CREATE_JOINABLE 0
|
||||||
|
#define LDAP_PVT_THREAD_CREATE_DETACHED 1
|
||||||
|
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_create LDAP_P((
|
ldap_pvt_thread_create LDAP_P((
|
||||||
ldap_pvt_thread_t * thread,
|
ldap_pvt_thread_t * thread,
|
||||||
@ -232,15 +235,17 @@ LDAP_F int
|
|||||||
ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
|
ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
|
||||||
|
|
||||||
typedef struct ldap_pvt_thread_rdwr_var {
|
typedef struct ldap_pvt_thread_rdwr_var {
|
||||||
int lt_readers_reading;
|
ldap_pvt_thread_mutex_t ltrw_mutex;
|
||||||
int lt_writer_writing;
|
ldap_pvt_thread_cond_t ltrw_read; /* wait for read */
|
||||||
ldap_pvt_thread_mutex_t lt_mutex;
|
ldap_pvt_thread_cond_t ltrw_write; /* wait for write */
|
||||||
ldap_pvt_thread_cond_t lt_lock_free;
|
int ltrw_valid;
|
||||||
|
#define LDAP_PVT_THREAD_RDWR_VALUE 0x0bad
|
||||||
|
int ltrw_r_active;
|
||||||
|
int ltrw_w_active;
|
||||||
|
int ltrw_r_wait;
|
||||||
|
int ltrw_w_wait;
|
||||||
} ldap_pvt_thread_rdwr_t;
|
} ldap_pvt_thread_rdwr_t;
|
||||||
|
|
||||||
#define LDAP_PVT_THREAD_CREATE_DETACHED 1
|
|
||||||
#define LDAP_PVT_THREAD_CREATE_JOINABLE 0
|
|
||||||
|
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_init LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
@ -248,21 +253,28 @@ ldap_pvt_thread_rdwr_destroy LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
|||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_rlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_rlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
|
ldap_pvt_thread_rdwr_rtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_runlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_runlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_wlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_wlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
|
ldap_pvt_thread_rdwr_wtrylock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_wunlock LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
|
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_rchk LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_readers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_wchk LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_writers LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
LDAP_F int
|
LDAP_F int
|
||||||
ldap_pvt_thread_rdwr_rwchk LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
ldap_pvt_thread_rdwr_active LDAP_P((ldap_pvt_thread_rdwr_t *rdwrp));
|
||||||
#endif /* LDAP_DEBUG */
|
#endif /* LDAP_DEBUG */
|
||||||
|
|
||||||
|
#define LDAP_PVT_THREAD_EINVAL EINVAL
|
||||||
|
#define LDAP_PVT_THREAD_EBUSY EINVAL
|
||||||
|
|
||||||
LDAP_END_DECL
|
LDAP_END_DECL
|
||||||
|
|
||||||
#endif /* _LDAP_THREAD_H */
|
#endif /* _LDAP_THREAD_H */
|
||||||
|
@ -1,100 +1,197 @@
|
|||||||
/*
|
/*
|
||||||
** This basic implementation of Reader/Writer locks does not
|
** This is an improved implementation of Reader/Writer locks does
|
||||||
** protect writers from starvation. That is, if a writer is
|
** not protect writers from starvation. That is, if a writer is
|
||||||
** currently waiting on a reader, any new reader will get
|
** currently waiting on a reader, any new reader will get
|
||||||
** the lock before the writer.
|
** the lock before the writer.
|
||||||
|
**
|
||||||
|
** Does not support cancellation nor does any status checking.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* An example source module to accompany...
|
* Adapted from:
|
||||||
*
|
* "Programming with Posix Threads"
|
||||||
* "Using POSIX Threads: Programming with Pthreads"
|
* by David R Butenhof
|
||||||
* by Brad nichols, Dick Buttlar, Jackie Farrell
|
* Addison-Wesley
|
||||||
* O'Reilly & Associates, Inc.
|
|
||||||
*
|
|
||||||
********************************************************
|
********************************************************
|
||||||
* rdwr.c --
|
|
||||||
*
|
|
||||||
* Library of functions implementing reader/writer locks
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "portable.h"
|
#include "portable.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <ac/errno.h>
|
||||||
#include "ldap_pvt_thread.h"
|
#include "ldap_pvt_thread.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_pvt_thread_rdwr_init(ldap_pvt_thread_rdwr_t *rdwrp )
|
ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
|
||||||
{
|
{
|
||||||
rdwrp->lt_readers_reading = 0;
|
memset( rw, 0, sizeof(ldap_pvt_thread_rdwr_t) );
|
||||||
rdwrp->lt_writer_writing = 0;
|
|
||||||
ldap_pvt_thread_mutex_init(&(rdwrp->lt_mutex) );
|
/* we should check return results */
|
||||||
ldap_pvt_thread_cond_init(&(rdwrp->lt_lock_free) );
|
ldap_pvt_thread_mutex_init( &rw->ltrw_mutex );
|
||||||
|
ldap_pvt_thread_cond_init( &rw->ltrw_read );
|
||||||
|
ldap_pvt_thread_cond_init( &rw->ltrw_write );
|
||||||
|
|
||||||
|
rw->ltrw_valid = LDAP_PVT_THREAD_RDWR_VALUE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ldap_pvt_thread_rdwr_destroy(ldap_pvt_thread_rdwr_t *rdwrp )
|
ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
|
||||||
{
|
{
|
||||||
ldap_pvt_thread_mutex_destroy(&(rdwrp->lt_mutex) );
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
ldap_pvt_thread_cond_destroy(&(rdwrp->lt_lock_free) );
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
/* active threads? */
|
||||||
|
if( rw->ltrw_r_active > 0 || rw->ltrw_w_active > 1) {
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
return LDAP_PVT_THREAD_EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* waiting threads? */
|
||||||
|
if( rw->ltrw_r_wait > 0 || rw->ltrw_w_wait > 0) {
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
return LDAP_PVT_THREAD_EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
rw->ltrw_valid = 0;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_destroy( &rw->ltrw_mutex );
|
||||||
|
ldap_pvt_thread_cond_destroy( &rw->ltrw_read );
|
||||||
|
ldap_pvt_thread_cond_destroy( &rw->ltrw_write );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_rlock(ldap_pvt_thread_rdwr_t *rdwrp){
|
int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
|
{
|
||||||
while(rdwrp->lt_writer_writing) {
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free),
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
&(rdwrp->lt_mutex));
|
|
||||||
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
if( rw->ltrw_w_active > 1 ) {
|
||||||
|
/* writer is active */
|
||||||
|
|
||||||
|
rw->ltrw_r_wait++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ldap_pvt_thread_cond_wait(
|
||||||
|
&rw->ltrw_read, &rw->ltrw_mutex );
|
||||||
|
} while( rw->ltrw_w_active > 1 );
|
||||||
|
|
||||||
|
rw->ltrw_r_wait--;
|
||||||
}
|
}
|
||||||
rdwrp->lt_readers_reading++;
|
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
rw->ltrw_r_active++;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_runlock(ldap_pvt_thread_rdwr_t *rdwrp)
|
int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
{
|
{
|
||||||
ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
if (rdwrp->lt_readers_reading == 0) {
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
|
||||||
return -1;
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
}
|
|
||||||
else {
|
if( rw->ltrw_w_active > 1) {
|
||||||
rdwrp->lt_readers_reading--;
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
if (rdwrp->lt_readers_reading == 0) {
|
return LDAP_PVT_THREAD_EBUSY;
|
||||||
ldap_pvt_thread_cond_signal(&(rdwrp->lt_lock_free));
|
|
||||||
}
|
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_wlock(ldap_pvt_thread_rdwr_t *rdwrp)
|
rw->ltrw_r_active++;
|
||||||
{
|
|
||||||
ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
while(rdwrp->lt_writer_writing || rdwrp->lt_readers_reading) {
|
|
||||||
ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free),
|
|
||||||
&(rdwrp->lt_mutex));
|
|
||||||
}
|
|
||||||
rdwrp->lt_writer_writing++;
|
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_wunlock(ldap_pvt_thread_rdwr_t *rdwrp)
|
int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
{
|
{
|
||||||
ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
if (rdwrp->lt_writer_writing == 0) {
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
|
||||||
return -1;
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
rw->ltrw_r_active--;
|
||||||
|
|
||||||
|
if (rw->ltrw_r_active == 0 && rw->ltrw_w_wait > 0 ) {
|
||||||
|
ldap_pvt_thread_cond_signal( &rw->ltrw_write );
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
rdwrp->lt_writer_writing = 0;
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
ldap_pvt_thread_cond_broadcast(&(rdwrp->lt_lock_free));
|
|
||||||
ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
|
{
|
||||||
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
if ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 ) {
|
||||||
|
rw->ltrw_w_wait++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ldap_pvt_thread_cond_wait(
|
||||||
|
&rw->ltrw_write, &rw->ltrw_mutex );
|
||||||
|
} while ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 );
|
||||||
|
|
||||||
|
rw->ltrw_w_wait--;
|
||||||
|
}
|
||||||
|
|
||||||
|
rw->ltrw_w_active++;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
|
{
|
||||||
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
if ( rw->ltrw_w_active > 0 || rw->ltrw_r_active > 0 ) {
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
return LDAP_PVT_THREAD_EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
rw->ltrw_w_active++;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
|
||||||
|
{
|
||||||
|
if( rw->ltrw_valid != LDAP_PVT_THREAD_RDWR_VALUE )
|
||||||
|
return LDAP_PVT_THREAD_EINVAL;
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_lock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
rw->ltrw_w_active--;
|
||||||
|
|
||||||
|
if (rw->ltrw_r_wait > 0) {
|
||||||
|
ldap_pvt_thread_cond_broadcast( &rw->ltrw_read );
|
||||||
|
|
||||||
|
} else if (rw->ltrw_w_wait > 0) {
|
||||||
|
ldap_pvt_thread_cond_signal( &rw->ltrw_write );
|
||||||
|
}
|
||||||
|
|
||||||
|
ldap_pvt_thread_mutex_unlock( &rw->ltrw_mutex );
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
@ -109,19 +206,20 @@ int ldap_pvt_thread_rdwr_wunlock(ldap_pvt_thread_rdwr_t *rdwrp)
|
|||||||
* a lock are caught.
|
* a lock are caught.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_rchk(ldap_pvt_thread_rdwr_t *rdwrp)
|
int ldap_pvt_thread_rdwr_readers(ldap_pvt_thread_rdwr_t *rw)
|
||||||
{
|
{
|
||||||
return(rdwrp->lt_readers_reading!=0);
|
return( rw->ltrw_r_active );
|
||||||
}
|
}
|
||||||
|
|
||||||
int ldap_pvt_thread_rdwr_wchk(ldap_pvt_thread_rdwr_t *rdwrp)
|
int ldap_pvt_thread_rdwr_writers(ldap_pvt_thread_rdwr_t *rw)
|
||||||
{
|
{
|
||||||
return(rdwrp->lt_writer_writing!=0);
|
return( rw->ltrw_w_active );
|
||||||
}
|
}
|
||||||
int ldap_pvt_thread_rdwr_rwchk(ldap_pvt_thread_rdwr_t *rdwrp)
|
|
||||||
|
int ldap_pvt_thread_rdwr_active(ldap_pvt_thread_rdwr_t *rw)
|
||||||
{
|
{
|
||||||
return(ldap_pvt_thread_rdwr_rchk(rdwrp) ||
|
return(ldap_pvt_thread_rdwr_readers(rw) +
|
||||||
ldap_pvt_thread_rdwr_wchk(rdwrp));
|
ldap_pvt_thread_rdwr_writers(rw));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LDAP_DEBUG */
|
#endif /* LDAP_DEBUG */
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <ac/errno.h>
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ cache_set_state( struct cache *cache, Entry *e, int state )
|
|||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef not_used
|
||||||
static void
|
static void
|
||||||
cache_return_entry( struct cache *cache, Entry *e )
|
cache_return_entry( struct cache *cache, Entry *e )
|
||||||
{
|
{
|
||||||
@ -71,14 +73,25 @@ cache_return_entry( struct cache *cache, Entry *e )
|
|||||||
/* free cache mutex */
|
/* free cache mutex */
|
||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cache_return_entry_rw( struct cache *cache, Entry *e, int rw )
|
cache_return_entry_rw( struct cache *cache, Entry *e, int rw )
|
||||||
{
|
{
|
||||||
Debug( LDAP_DEBUG_TRACE, "====> cache_return_entry_%s\n",
|
Debug( LDAP_DEBUG_TRACE, "====> cache_return_entry_%s\n",
|
||||||
rw ? "w" : "r", 0, 0);
|
rw ? "w" : "r", 0, 0);
|
||||||
|
|
||||||
|
/* set cache mutex */
|
||||||
|
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||||
|
|
||||||
entry_rdwr_unlock(e, rw);;
|
entry_rdwr_unlock(e, rw);;
|
||||||
cache_return_entry(cache, e);
|
|
||||||
|
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) {
|
||||||
|
entry_free( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free cache mutex */
|
||||||
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -202,7 +215,7 @@ cache_add_entry_lock(
|
|||||||
|
|
||||||
/* XXX check for writer lock - should also check no readers pending */
|
/* XXX check for writer lock - should also check no readers pending */
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
assert(!ldap_pvt_thread_rdwr_rwchk(&e->e_rdwr));
|
assert(!ldap_pvt_thread_rdwr_active( &e->e_rdwr ));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* delete from cache and lru q */
|
/* delete from cache and lru q */
|
||||||
@ -241,6 +254,11 @@ cache_find_entry_dn2id(
|
|||||||
if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
|
if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
|
||||||
cache_entrydn_cmp )) != NULL )
|
cache_entrydn_cmp )) != NULL )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* ep now points to an unlocked entry
|
||||||
|
* we do not need to lock the entry if we only
|
||||||
|
* check the state, refcnt, LRU, and id.
|
||||||
|
*/
|
||||||
free(e.e_ndn);
|
free(e.e_ndn);
|
||||||
|
|
||||||
Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id: found dn: %s\n",
|
Debug(LDAP_DEBUG_TRACE, "====> cache_find_entry_dn2id: found dn: %s\n",
|
||||||
@ -257,42 +275,16 @@ cache_find_entry_dn2id(
|
|||||||
return( NOID );
|
return( NOID );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX is this safe without writer lock? */
|
|
||||||
ep->e_refcnt++;
|
|
||||||
|
|
||||||
/* lru */
|
/* lru */
|
||||||
LRU_DELETE( cache, ep );
|
LRU_DELETE( cache, ep );
|
||||||
LRU_ADD( cache, ep );
|
LRU_ADD( cache, ep );
|
||||||
|
|
||||||
/* acquire reader lock */
|
|
||||||
entry_rdwr_lock(ep, 0);
|
|
||||||
|
|
||||||
/* re-check */
|
|
||||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
|
||||||
ep->e_state == ENTRY_STATE_CREATING )
|
|
||||||
{
|
|
||||||
/* XXX check that is is required */
|
|
||||||
ep->e_refcnt--;
|
|
||||||
|
|
||||||
/* free reader lock */
|
|
||||||
entry_rdwr_unlock(ep, 0);
|
|
||||||
/* free cache mutex */
|
|
||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
|
||||||
|
|
||||||
return( NOID );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save id */
|
/* save id */
|
||||||
id = ep->e_id;
|
id = ep->e_id;
|
||||||
|
|
||||||
/* free reader lock */
|
|
||||||
entry_rdwr_unlock(ep, 0);
|
|
||||||
|
|
||||||
/* free cache mutex */
|
/* free cache mutex */
|
||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
|
|
||||||
cache_return_entry( &li->li_cache, ep );
|
|
||||||
|
|
||||||
return( id );
|
return( id );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,11 +310,12 @@ cache_find_entry_id(
|
|||||||
Entry e;
|
Entry e;
|
||||||
Entry *ep;
|
Entry *ep;
|
||||||
|
|
||||||
|
e.e_id = id;
|
||||||
|
|
||||||
|
try_again:
|
||||||
/* set cache mutex */
|
/* set cache mutex */
|
||||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||||
|
|
||||||
e.e_id = id;
|
|
||||||
|
|
||||||
if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
|
if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
|
||||||
cache_entryid_cmp )) != NULL )
|
cache_entryid_cmp )) != NULL )
|
||||||
{
|
{
|
||||||
@ -340,35 +333,25 @@ cache_find_entry_id(
|
|||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
/* XXX is this safe without writer lock? */
|
|
||||||
ep->e_refcnt++;
|
/* acquire reader lock */
|
||||||
|
if ( entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
|
||||||
|
/* could not acquire entry lock...
|
||||||
|
* owner cannot free as we have the cache locked.
|
||||||
|
* so, unlock the cache, yield, and try again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* free cache mutex */
|
||||||
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
|
ldap_pvt_thread_yield();
|
||||||
|
goto try_again;
|
||||||
|
}
|
||||||
|
|
||||||
/* lru */
|
/* lru */
|
||||||
LRU_DELETE( cache, ep );
|
LRU_DELETE( cache, ep );
|
||||||
LRU_ADD( cache, ep );
|
LRU_ADD( cache, ep );
|
||||||
|
|
||||||
/* acquire reader lock */
|
ep->e_refcnt++;
|
||||||
entry_rdwr_lock(ep, 0);
|
|
||||||
|
|
||||||
/* re-check */
|
|
||||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
|
||||||
ep->e_state == ENTRY_STATE_CREATING ) {
|
|
||||||
|
|
||||||
/* XXX check that is is required */
|
|
||||||
ep->e_refcnt--;
|
|
||||||
|
|
||||||
/* free reader lock */
|
|
||||||
entry_rdwr_unlock(ep, 0);
|
|
||||||
|
|
||||||
/* free cache mutex */
|
|
||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( rw ) {
|
|
||||||
entry_rdwr_unlock(ep, 0);
|
|
||||||
entry_rdwr_lock(ep, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free cache mutex */
|
/* free cache mutex */
|
||||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||||
@ -405,7 +388,7 @@ cache_delete_entry(
|
|||||||
|
|
||||||
/* XXX check for writer lock - should also check no readers pending */
|
/* XXX check for writer lock - should also check no readers pending */
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
assert(ldap_pvt_thread_rdwr_wchk(&e->e_rdwr));
|
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* set cache mutex */
|
/* set cache mutex */
|
||||||
|
@ -64,18 +64,13 @@ id2entry_delete( Backend *be, Entry *e )
|
|||||||
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %lu, \"%s\" )\n", e->e_id,
|
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %lu, \"%s\" )\n", e->e_id,
|
||||||
e->e_dn, 0 );
|
e->e_dn, 0 );
|
||||||
|
|
||||||
/* XXX - check for writer lock - should also check no reader pending */
|
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
assert(ldap_pvt_thread_rdwr_wchk(&e->e_rdwr));
|
/* check for writer lock */
|
||||||
|
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ldbm_datum_init( key );
|
ldbm_datum_init( key );
|
||||||
|
|
||||||
/* XXX - check for writer lock - should also check no reader pending */
|
|
||||||
Debug (LDAP_DEBUG_TRACE,
|
|
||||||
"rdwr_Xchk: readers_reading: %d writer_writing: %d\n",
|
|
||||||
e->e_rdwr.lt_readers_reading, e->e_rdwr.lt_writer_writing, 0);
|
|
||||||
|
|
||||||
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
||||||
== NULL ) {
|
== NULL ) {
|
||||||
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <ac/ctype.h>
|
#include <ac/ctype.h>
|
||||||
|
#include <ac/errno.h>
|
||||||
#include <ac/socket.h>
|
#include <ac/socket.h>
|
||||||
#include <ac/string.h>
|
#include <ac/string.h>
|
||||||
|
|
||||||
@ -218,11 +219,20 @@ entry_free( Entry *e )
|
|||||||
int i;
|
int i;
|
||||||
Attribute *a, *next;
|
Attribute *a, *next;
|
||||||
|
|
||||||
/* XXX check that no reader/writer locks exist */
|
/* check that no reader/writer locks exist */
|
||||||
|
|
||||||
|
if ( ldap_pvt_thread_rdwr_wtrylock( &e->e_rdwr ) ==
|
||||||
|
LDAP_PVT_THREAD_EBUSY )
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_ANY, "entry_free(%ld): active (%d, %d)\n",
|
||||||
|
e->e_id,
|
||||||
|
ldap_pvt_thread_rdwr_readers( &e->e_rdwr ),
|
||||||
|
ldap_pvt_thread_rdwr_writers( &e->e_rdwr ));
|
||||||
|
|
||||||
#ifdef LDAP_DEBUG
|
#ifdef LDAP_DEBUG
|
||||||
assert( !ldap_pvt_thread_rdwr_wchk(&e->e_rdwr) &&
|
assert(!ldap_pvt_thread_rdwr_active( &e->e_rdwr ));
|
||||||
!ldap_pvt_thread_rdwr_rchk(&e->e_rdwr) );
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if ( e->e_dn != NULL ) {
|
if ( e->e_dn != NULL ) {
|
||||||
free( e->e_dn );
|
free( e->e_dn );
|
||||||
@ -260,6 +270,17 @@ entry_rdwr_wlock(Entry *e)
|
|||||||
return entry_rdwr_lock( e, 1 );
|
return entry_rdwr_lock( e, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
entry_rdwr_trylock(Entry *e, int rw)
|
||||||
|
{
|
||||||
|
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
|
||||||
|
rw ? "w" : "r", e->e_id, 0);
|
||||||
|
if (rw)
|
||||||
|
return ldap_pvt_thread_rdwr_wtrylock(&e->e_rdwr);
|
||||||
|
else
|
||||||
|
return ldap_pvt_thread_rdwr_rtrylock(&e->e_rdwr);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
entry_rdwr_unlock(Entry *e, int rw)
|
entry_rdwr_unlock(Entry *e, int rw)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user