POSIX.1c-based implementations-only. APR_ENOTIMPL for other platforms
and for Unix platforms without pthread_rwlock_init.
Comments or suggestions welcomed. I tested primarily with Solaris.
FreeBSD (-pthread) and Linux (_POSIX_C_SOURCE=199506L) have support,
but I haven't tested them. I know that FreeBSD still compiles without
-pthread option (i.e. READWRITE locks are disabled). This probably
needs a better configure test - APR_USE_POSIX_RWLOCK?
One other nit in this patch - APR_INT64_T_FMT is currently bogus (per
Ryan, these formats shouldn't be passed to the OS printf). No one but
APR uses "%qd" anymore. =)
This locking works with my modified ab - which now works with threads -
for some reason, ab is now more reliable. But, that isn't an APR
thing. I still have some work left on that (basically get it working
without threads) - not sure if a threaded ab is worth anything...
-- justin
Index: configure.in
===================================================================
RCS file: /home/cvspublic/apr/configure.in,v
retrieving revision 1.294
diff -u -r1.294 configure.in
--- configure.in 2001/04/27 18:36:03 1.294
+++ configure.in 2001/04/28 20:06:42
@@ -259,7 +259,7 @@
if test "$pthreadh" = "1"; then
APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS
APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG
- AC_CHECK_FUNCS(pthread_key_delete)
+ AC_CHECK_FUNCS(pthread_key_delete pthread_rwlock_init)
fi
fi
@@ -626,7 +626,7 @@
dnl BSD 4.4 originated 'q'. Solaris is more popular and
dnl doesn't support 'q'. Solaris wins. Exceptions can
dnl go to the OS-dependent section.
- int64_t_fmt='#define APR_INT64_T_FMT "lld"'
+ int64_t_fmt='#define APR_INT64_T_FMT "qd"'
int64_value="long long"
long_value="long long"
elif test "$ac_cv_sizeof_long_double" = "8"; then
Index: include/apr_lock.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_lock.h,v
retrieving revision 1.23
diff -u -r1.23 apr_lock.h
--- include/apr_lock.h 2001/02/16 04:15:46 1.23
+++ include/apr_lock.h 2001/04/28 20:06:43
@@ -71,6 +71,8 @@
typedef enum {APR_MUTEX, APR_READWRITE} apr_locktype_e;
+typedef enum {APR_READER, APR_WRITER} apr_readerwriter_e;
+
typedef struct apr_lock_t apr_lock_t;
/* Function definitions */
@@ -110,6 +112,15 @@
* @deffunc apr_status_t apr_lock_acquire(apr_lock_t *lock)
*/
APR_DECLARE(apr_status_t) apr_lock_acquire(apr_lock_t *lock);
+
+/**
+ * Lock a region with either a reader or writer lock.
+ * @param lock The lock to set.
+ * @param type The type of lock to acquire.
+ * @deffunc apr_status_t apr_lock_acquire_rw(apr_lock_t *lock,
apr_readerwriter_e type)
+ */
+APR_DECLARE(apr_status_t) apr_lock_acquire_rw(apr_lock_t *lock,
+ apr_readerwriter_e type);
/**
* Unlock a protected region.
Index: include/arch/unix/locks.h
===================================================================
RCS file: /home/cvspublic/apr/include/arch/unix/locks.h,v
retrieving revision 1.26
diff -u -r1.26 locks.h
--- include/arch/unix/locks.h 2001/02/25 20:39:32 1.26
+++ include/arch/unix/locks.h 2001/04/28 20:06:44
@@ -130,9 +130,12 @@
#if APR_USE_PTHREAD_SERIALIZE
pthread_mutex_t *intraproc;
#endif
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ pthread_rwlock_t rwlock;
#endif
+#endif
/* At some point, we should do a scope for both inter and intra process
- * locking here. Something like pthread_mutex with PTHREAD_PROCESS_SHARED
+ * locking here. Something like pthread_mutex with PTHREAD_PROCESS_SHARED
*/
};
@@ -149,8 +152,8 @@
apr_status_t apr_unix_unlock_inter(struct apr_lock_t *lock);
apr_status_t apr_unix_destroy_inter_lock(struct apr_lock_t *lock);
-apr_status_t apr_unix_child_init_lock(struct apr_lock_t **lock, apr_pool_t
*cont,
- const char *fname);
+apr_status_t apr_unix_child_init_lock(struct apr_lock_t **lock,
+ apr_pool_t *cont, const char *fname);
#endif /* LOCKS_H */
Index: locks/beos/locks.c
===================================================================
RCS file: /home/cvspublic/apr/locks/beos/locks.c,v
retrieving revision 1.26
diff -u -r1.26 locks.c
--- locks/beos/locks.c 2001/02/16 04:15:53 1.26
+++ locks/beos/locks.c 2001/04/28 20:06:44
@@ -103,6 +103,11 @@
return APR_SUCCESS;
}
+apr_status_t apr_lock_acquire_rw(apr_lock_t *lock, apr_readerwriter_e e)
+{
+ return APR_ENOTIMPL;
+}
+
apr_status_t apr_lock_release(apr_lock_t *lock)
{
apr_status_t stat;
Index: locks/os2/locks.c
===================================================================
RCS file: /home/cvspublic/apr/locks/os2/locks.c,v
retrieving revision 1.27
diff -u -r1.27 locks.c
--- locks/os2/locks.c 2001/03/19 12:43:25 1.27
+++ locks/os2/locks.c 2001/04/28 20:06:44
@@ -142,7 +142,10 @@
return APR_OS2_STATUS(rc);
}
-
+apr_status_t apr_lock_acquire_rw(apr_lock_t *lock, apr_readerwriter_e e)
+{
+ return APR_OS2_STATUS(APR_ENOTIMPL);
+}
apr_status_t apr_lock_release(apr_lock_t *lock)
{
Index: locks/unix/locks.c
===================================================================
RCS file: /home/cvspublic/apr/locks/unix/locks.c,v
retrieving revision 1.46
diff -u -r1.46 locks.c
--- locks/unix/locks.c 2001/02/16 04:15:55 1.46
+++ locks/unix/locks.c 2001/04/28 20:06:44
@@ -68,6 +68,9 @@
new->cntxt = cont;
new->type = type;
new->scope = scope;
+ switch (new->type)
+ {
+ case APR_MUTEX:
#if (APR_USE_FCNTL_SERIALIZE) || (APR_USE_FLOCK_SERIALIZE)
/* file-based serialization primitives */
if (scope != APR_INTRAPROCESS) {
@@ -97,6 +100,16 @@
return stat;
}
}
+ break;
+ case APR_READWRITE:
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ pthread_rwlock_init(&new->rwlock, NULL);
+ break;
+#else
+ return APR_ENOTIMPL;
+#endif
+ }
+
*lock = new;
return APR_SUCCESS;
}
@@ -104,6 +117,10 @@
apr_status_t apr_lock_acquire(apr_lock_t *lock)
{
apr_status_t stat;
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
#if APR_PROCESS_LOCK_IS_GLOBAL /* don't need intra lock for APR_LOCKALL */
if (lock->scope == APR_INTRAPROCESS) {
#else
@@ -122,13 +139,49 @@
return stat;
}
}
+ break;
+ case APR_READWRITE:
+ return apr_lock_acquire_rw(lock, APR_READER);
+ }
+
return APR_SUCCESS;
}
+apr_status_t apr_lock_acquire_rw(apr_lock_t *lock, apr_readerwriter_e e)
+{
+ apr_status_t stat = APR_SUCCESS;
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ return APR_ENOTIMPL;
+ case APR_READWRITE:
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ switch (e)
+ {
+ case APR_READER:
+ stat = pthread_rwlock_rdlock(&lock->rwlock);
+ break;
+ case APR_WRITER:
+ stat = pthread_rwlock_wrlock(&lock->rwlock);
+ break;
+ }
+ break;
+#else
+ return APR_ENOTIMPL;
+#endif
+ }
+
+ return stat;
+}
+
apr_status_t apr_lock_release(apr_lock_t *lock)
{
apr_status_t stat;
+ switch (lock->type)
+ {
+ case APR_MUTEX:
#if APR_PROCESS_LOCK_IS_GLOBAL /* don't need intra lock for APR_LOCKALL */
if (lock->scope == APR_INTRAPROCESS) {
#else
@@ -147,12 +200,27 @@
return stat;
}
}
+ break;
+ case APR_READWRITE:
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ if ((stat = pthread_rwlock_unlock(&lock->rwlock)) != 0)
+ return stat;
+ break;
+#else
+ return APR_ENOTIMPL;
+#endif
+ }
+
return APR_SUCCESS;
}
apr_status_t apr_lock_destroy(apr_lock_t *lock)
{
apr_status_t stat;
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
#if APR_PROCESS_LOCK_IS_GLOBAL /* don't need intra lock for APR_LOCKALL */
if (lock->scope == APR_INTRAPROCESS) {
#else
@@ -172,6 +240,16 @@
if ((stat = apr_unix_destroy_inter_lock(lock)) != APR_SUCCESS) {
return stat;
}
+ }
+ break;
+ case APR_READWRITE:
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ if ((stat = pthread_rwlock_destroy(&lock->rwlock)) != 0)
+ return stat;
+ break;
+#else
+ return APR_ENOTIMPL;
+#endif
}
return APR_SUCCESS;
}
Index: locks/win32/locks.c
===================================================================
RCS file: /home/cvspublic/apr/locks/win32/locks.c,v
retrieving revision 1.36
diff -u -r1.36 locks.c
--- locks/win32/locks.c 2001/02/16 04:15:56 1.36
+++ locks/win32/locks.c 2001/04/28 20:06:44
@@ -131,6 +131,12 @@
return apr_get_os_error();
}
+APR_DECLARE(apr_status_t) apr_lock_acquire_rw(apr_lock_t *lock,
+ apr_readerwriter_e e)
+{
+ return APR_ENOTIMPL;
+}
+
APR_DECLARE(apr_status_t) apr_lock_release(apr_lock_t *lock)
{
if (lock->scope == APR_INTRAPROCESS) {