1 /* $OpenLDAP: pkg/ldap/libraries/libldap_r/rmutex.c,v 1.2.2.4 2008/02/11 23:26:41 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2006-2008 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* This work was initially developed by Howard Chu for inclusion
16 * in OpenLDAP Software.
20 * This is an implementation of recursive mutexes.
25 #include <ac/stdlib.h>
28 #include <ac/string.h>
32 #include "ldap_pvt_thread.h" /* Get the thread interface */
34 struct ldap_int_thread_rmutex_s
{
35 ldap_pvt_thread_mutex_t ltrm_mutex
;
36 ldap_pvt_thread_cond_t ltrm_cond
;
37 ldap_pvt_thread_t ltrm_owner
;
39 #define LDAP_PVT_THREAD_RMUTEX_VALID 0x0cdb
44 static const ldap_pvt_thread_t tid_zero
;
47 ldap_pvt_thread_rmutex_init( ldap_pvt_thread_rmutex_t
*rmutex
)
49 struct ldap_int_thread_rmutex_s
*rm
;
51 assert( rmutex
!= NULL
);
53 rm
= (struct ldap_int_thread_rmutex_s
*) LDAP_CALLOC( 1,
54 sizeof( struct ldap_int_thread_rmutex_s
) );
56 return LDAP_NO_MEMORY
;
58 /* we should check return results */
59 ldap_pvt_thread_mutex_init( &rm
->ltrm_mutex
);
60 ldap_pvt_thread_cond_init( &rm
->ltrm_cond
);
62 rm
->ltrm_valid
= LDAP_PVT_THREAD_RMUTEX_VALID
;
69 ldap_pvt_thread_rmutex_destroy( ldap_pvt_thread_rmutex_t
*rmutex
)
71 struct ldap_int_thread_rmutex_s
*rm
;
73 assert( rmutex
!= NULL
);
77 assert( rm
->ltrm_valid
== LDAP_PVT_THREAD_RMUTEX_VALID
);
79 if( rm
->ltrm_valid
!= LDAP_PVT_THREAD_RMUTEX_VALID
)
80 return LDAP_PVT_THREAD_EINVAL
;
82 ldap_pvt_thread_mutex_lock( &rm
->ltrm_mutex
);
84 assert( rm
->ltrm_depth
>= 0 );
85 assert( rm
->ltrm_waits
>= 0 );
88 if( rm
->ltrm_depth
> 0 || rm
->ltrm_waits
> 0 ) {
89 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
90 return LDAP_PVT_THREAD_EBUSY
;
95 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
97 ldap_pvt_thread_mutex_destroy( &rm
->ltrm_mutex
);
98 ldap_pvt_thread_cond_destroy( &rm
->ltrm_cond
);
105 int ldap_pvt_thread_rmutex_lock( ldap_pvt_thread_rmutex_t
*rmutex
,
106 ldap_pvt_thread_t owner
)
108 struct ldap_int_thread_rmutex_s
*rm
;
110 assert( rmutex
!= NULL
);
113 assert( rm
!= NULL
);
114 assert( rm
->ltrm_valid
== LDAP_PVT_THREAD_RMUTEX_VALID
);
116 if( rm
->ltrm_valid
!= LDAP_PVT_THREAD_RMUTEX_VALID
)
117 return LDAP_PVT_THREAD_EINVAL
;
119 ldap_pvt_thread_mutex_lock( &rm
->ltrm_mutex
);
121 assert( rm
->ltrm_depth
>= 0 );
122 assert( rm
->ltrm_waits
>= 0 );
124 if( rm
->ltrm_depth
> 0 ) {
126 if ( !ldap_pvt_thread_equal( rm
->ltrm_owner
, owner
)) {
129 ldap_pvt_thread_cond_wait( &rm
->ltrm_cond
,
131 } while( rm
->ltrm_depth
> 0 );
134 assert( rm
->ltrm_waits
>= 0 );
135 rm
->ltrm_owner
= owner
;
138 rm
->ltrm_owner
= owner
;
143 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
148 int ldap_pvt_thread_rmutex_trylock( ldap_pvt_thread_rmutex_t
*rmutex
,
149 ldap_pvt_thread_t owner
)
151 struct ldap_int_thread_rmutex_s
*rm
;
153 assert( rmutex
!= NULL
);
156 assert( rm
!= NULL
);
157 assert( rm
->ltrm_valid
== LDAP_PVT_THREAD_RMUTEX_VALID
);
159 if( rm
->ltrm_valid
!= LDAP_PVT_THREAD_RMUTEX_VALID
)
160 return LDAP_PVT_THREAD_EINVAL
;
162 ldap_pvt_thread_mutex_lock( &rm
->ltrm_mutex
);
164 assert( rm
->ltrm_depth
>= 0 );
165 assert( rm
->ltrm_waits
>= 0 );
167 if( rm
->ltrm_depth
> 0 ) {
168 if ( !ldap_pvt_thread_equal( owner
, rm
->ltrm_owner
)) {
169 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
170 return LDAP_PVT_THREAD_EBUSY
;
173 rm
->ltrm_owner
= owner
;
178 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
183 int ldap_pvt_thread_rmutex_unlock( ldap_pvt_thread_rmutex_t
*rmutex
,
184 ldap_pvt_thread_t owner
)
186 struct ldap_int_thread_rmutex_s
*rm
;
188 assert( rmutex
!= NULL
);
191 assert( rm
!= NULL
);
192 assert( rm
->ltrm_valid
== LDAP_PVT_THREAD_RMUTEX_VALID
);
194 if( rm
->ltrm_valid
!= LDAP_PVT_THREAD_RMUTEX_VALID
)
195 return LDAP_PVT_THREAD_EINVAL
;
197 ldap_pvt_thread_mutex_lock( &rm
->ltrm_mutex
);
199 if( !ldap_pvt_thread_equal( owner
, rm
->ltrm_owner
)) {
200 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);
201 return LDAP_PVT_THREAD_EINVAL
;
205 if ( !rm
->ltrm_depth
)
206 rm
->ltrm_owner
= tid_zero
;
208 assert( rm
->ltrm_depth
>= 0 );
209 assert( rm
->ltrm_waits
>= 0 );
211 if ( !rm
->ltrm_depth
&& rm
->ltrm_waits
) {
212 ldap_pvt_thread_cond_signal( &rm
->ltrm_cond
);
215 ldap_pvt_thread_mutex_unlock( &rm
->ltrm_mutex
);