]> git.sur5r.net Git - openldap/commitdiff
Added recursive mutex implementation
authorHoward Chu <hyc@openldap.org>
Fri, 28 Apr 2006 20:12:45 +0000 (20:12 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 28 Apr 2006 20:12:45 +0000 (20:12 +0000)
include/ldap_int_thread.h
include/ldap_pvt_thread.h
libraries/libldap_r/Makefile.in
libraries/libldap_r/rmutex.c [new file with mode: 0644]
libraries/libldap_r/threads.c

index ccf293bf2a6c973a7a36cc80449f704b1fad15f5..46c79ae8de6d59b29b63961d5dd23c22070dd80f 100644 (file)
@@ -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
 
 
index 3f2d48fb11407a27ea387d056086ce945ec6f39f..76a371ebf52f8b21f304013c9954bbb044287b26 100644 (file)
@@ -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 ));
 
index 7ad2ceca35aeef689350b563d3855e95da12b81e..2629234e0f6986e3a0b8ddfeb25df054fb195a76 100644 (file)
@@ -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 \
diff --git a/libraries/libldap_r/rmutex.c b/libraries/libldap_r/rmutex.c
new file mode 100644 (file)
index 0000000..eb04f56
--- /dev/null
@@ -0,0 +1,225 @@
+/* $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;
+}
+
index 9caee1469bcfb8e502ae19e63bbdf544e0783fbc..c810ad56be709f17ef1260080f1384ad47fd8138 100644 (file)
@@ -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;
 }