Skip to content
Snippets Groups Projects
Commit 0a7808fb authored by Howard Chu's avatar Howard Chu
Browse files

Added recursive mutex implementation

parent 51a65afb
No related branches found
No related tags found
No related merge requests found
......@@ -227,6 +227,7 @@ LDAP_F(int) ldap_int_thread_pool_shutdown ( void );
typedef struct ldap_int_thread_pool_s * ldap_int_thread_pool_t;
#endif
typedef struct ldap_int_thread_rmutex_s * ldap_int_thread_rmutex_t;
LDAP_END_DECL
......
......@@ -33,6 +33,7 @@ typedef ldap_int_thread_mutex_t ldap_pvt_thread_mutex_t;
typedef ldap_int_thread_cond_t ldap_pvt_thread_cond_t;
typedef ldap_int_thread_rdwr_t ldap_pvt_thread_rdwr_t;
#endif
typedef ldap_int_thread_rmutex_t ldap_pvt_thread_rmutex_t;
#endif /* !LDAP_PVT_THREAD_H_DONE */
#if 0 && defined(LDAP_DEVEL)
......@@ -122,6 +123,21 @@ ldap_pvt_thread_mutex_trylock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
LDAP_F( int )
ldap_pvt_thread_mutex_unlock LDAP_P(( ldap_pvt_thread_mutex_t *mutex ));
LDAP_F( int )
ldap_pvt_thread_rmutex_init LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
LDAP_F( int )
ldap_pvt_thread_rmutex_destroy LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
LDAP_F( int )
ldap_pvt_thread_rmutex_lock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
LDAP_F( int )
ldap_pvt_thread_rmutex_trylock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
LDAP_F( int )
ldap_pvt_thread_rmutex_unlock LDAP_P(( ldap_pvt_thread_rmutex_t *rmutex ));
LDAP_F( ldap_pvt_thread_t )
ldap_pvt_thread_self LDAP_P(( void ));
......
......@@ -29,10 +29,10 @@ XXSRCS = apitest.c test.c \
init.c options.c print.c string.c util-int.c schema.c \
charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \
turn.c ppolicy.c dds.c txn.c
SRCS = threads.c rdwr.c tpool.c rq.c \
SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \
thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
thr_pth.c thr_stub.c thr_debug.c
OBJS = threads.lo rdwr.lo tpool.lo rq.lo \
OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \
thr_posix.lo thr_cthreads.lo thr_thr.lo thr_lwp.lo thr_nt.lo \
thr_pth.lo thr_stub.lo thr_debug.lo \
bind.lo open.lo result.lo error.lo compare.lo search.lo \
......
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2006 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* This work was initially developed by Howard Chu for inclusion
* in OpenLDAP Software.
*/
/*
* This is an implementation of recursive mutexes.
*/
#include "portable.h"
#include <ac/stdlib.h>
#include <ac/errno.h>
#include <ac/string.h>
#include <ac/time.h>
#include "ldap-int.h"
#include "ldap_pvt_thread.h" /* Get the thread interface */
struct ldap_int_thread_rmutex_s {
ldap_pvt_thread_mutex_t ltrm_mutex;
ldap_pvt_thread_cond_t ltrm_cond;
ldap_pvt_thread_t ltrm_owner;
int ltrm_valid;
#define LDAP_PVT_THREAD_RMUTEX_VALID 0x0cdb
int ltrm_depth;
int ltrm_waits;
};
static const ldap_pvt_thread_t tid_zero;
int
ldap_pvt_thread_rmutex_init( ldap_pvt_thread_rmutex_t *rmutex )
{
struct ldap_int_thread_rmutex_s *rm;
assert( rmutex != NULL );
rm = (struct ldap_int_thread_rmutex_s *) LDAP_CALLOC( 1,
sizeof( struct ldap_int_thread_rmutex_s ) );
if ( !rm )
return LDAP_NO_MEMORY;
/* we should check return results */
ldap_pvt_thread_mutex_init( &rm->ltrm_mutex );
ldap_pvt_thread_cond_init( &rm->ltrm_cond );
rm->ltrm_valid = LDAP_PVT_THREAD_RMUTEX_VALID;
*rmutex = rm;
return 0;
}
int
ldap_pvt_thread_rmutex_destroy( ldap_pvt_thread_rmutex_t *rmutex )
{
struct ldap_int_thread_rmutex_s *rm;
assert( rmutex != NULL );
rm = *rmutex;
assert( rm != NULL );
assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
return LDAP_PVT_THREAD_EINVAL;
ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
assert( rm->ltrm_depth >= 0 );
assert( rm->ltrm_waits >= 0 );
/* in use? */
if( rm->ltrm_depth > 0 || rm->ltrm_waits > 0 ) {
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return LDAP_PVT_THREAD_EBUSY;
}
rm->ltrm_valid = 0;
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
ldap_pvt_thread_mutex_destroy( &rm->ltrm_mutex );
ldap_pvt_thread_cond_destroy( &rm->ltrm_cond );
LDAP_FREE(rm);
*rmutex = NULL;
return 0;
}
int ldap_pvt_thread_rmutex_lock( ldap_pvt_thread_rmutex_t *rmutex )
{
struct ldap_int_thread_rmutex_s *rm;
ldap_pvt_thread_t tid;
assert( rmutex != NULL );
rm = *rmutex;
assert( rm != NULL );
assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
return LDAP_PVT_THREAD_EINVAL;
ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
assert( rm->ltrm_depth >= 0 );
assert( rm->ltrm_waits >= 0 );
tid = ldap_pvt_thread_self();
if( rm->ltrm_depth > 0 ) {
/* already locked */
if ( !ldap_pvt_thread_equal( rm->ltrm_owner, tid )) {
rm->ltrm_waits++;
do {
ldap_pvt_thread_cond_wait( &rm->ltrm_cond,
&rm->ltrm_mutex );
} while( rm->ltrm_depth > 0 );
rm->ltrm_waits--;
assert( rm->ltrm_waits >= 0 );
rm->ltrm_owner = tid;
}
} else {
rm->ltrm_owner = tid;
}
rm->ltrm_depth++;
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return 0;
}
int ldap_pvt_thread_rmutex_trylock( ldap_pvt_thread_rmutex_t *rmutex )
{
struct ldap_int_thread_rmutex_s *rm;
ldap_pvt_thread_t tid;
assert( rmutex != NULL );
rm = *rmutex;
assert( rm != NULL );
assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
return LDAP_PVT_THREAD_EINVAL;
ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
assert( rm->ltrm_depth >= 0 );
assert( rm->ltrm_waits >= 0 );
tid = ldap_pvt_thread_self();
if( rm->ltrm_depth > 0 ) {
if ( !ldap_pvt_thread_equal( tid, rm->ltrm_owner )) {
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return LDAP_PVT_THREAD_EBUSY;
}
} else {
rm->ltrm_owner = tid;
}
rm->ltrm_depth++;
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return 0;
}
int ldap_pvt_thread_rmutex_unlock( ldap_pvt_thread_rmutex_t *rmutex )
{
struct ldap_int_thread_rmutex_s *rm;
ldap_pvt_thread_t tid;
assert( rmutex != NULL );
rm = *rmutex;
assert( rm != NULL );
assert( rm->ltrm_valid == LDAP_PVT_THREAD_RMUTEX_VALID );
if( rm->ltrm_valid != LDAP_PVT_THREAD_RMUTEX_VALID )
return LDAP_PVT_THREAD_EINVAL;
ldap_pvt_thread_mutex_lock( &rm->ltrm_mutex );
tid = ldap_pvt_thread_self();
if( !ldap_pvt_thread_equal( tid, rm->ltrm_owner )) {
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return LDAP_PVT_THREAD_EINVAL;
}
rm->ltrm_depth--;
if ( !rm->ltrm_depth )
rm->ltrm_owner = tid_zero;
assert( rm->ltrm_depth >= 0 );
assert( rm->ltrm_waits >= 0 );
if ( !rm->ltrm_depth && rm->ltrm_waits ) {
ldap_pvt_thread_cond_signal( &rm->ltrm_cond );
}
ldap_pvt_thread_mutex_unlock( &rm->ltrm_mutex );
return 0;
}
......@@ -38,6 +38,7 @@ int ldap_pvt_thread_initialize( void )
{
int rc;
static int init = 0;
ldap_pvt_thread_rmutex_t rm;
/* we only get one shot at this */
if( init++ ) return -1;
......@@ -50,6 +51,14 @@ int ldap_pvt_thread_initialize( void )
if( rc ) return rc;
#endif
/* kludge to pull symbol definitions in */
ldap_pvt_thread_rmutex_init( &rm );
ldap_pvt_thread_rmutex_lock( &rm );
ldap_pvt_thread_rmutex_trylock( &rm );
ldap_pvt_thread_rmutex_unlock( &rm );
ldap_pvt_thread_rmutex_unlock( &rm );
ldap_pvt_thread_rmutex_destroy( &rm );
return 0;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment