jerenkrantz 01/05/30 20:30:07
Modified: . CHANGES configure.in
include apr_lock.h
include/arch/unix locks.h
locks/beos locks.c
locks/os2 locks.c
locks/unix locks.c
locks/win32 locks.c
test .cvsignore Makefile.in
Added: test testlock.c
Log:
Implement read write locks. This commit will support POSIX pthread
rw locks on Unix platforms. This is based on earlier patches that I
posted to apr-dev, but did not receive feedback from others on.
Hence, I'm committing.
This will require a buildconf run for those of you who use Unix.
This has only really been tested on Solaris, but it should work
for those platforms that have POSIX rw locks. Other Unix
platforms will simply return APR_ENOTIMPL.
Add apr_lock_acquire_rw(). Notice that the Unix implementation
will only allow a readwrite lock to be acquired via this function.
Technically, apr_lock_acquire could obtain some sort of readwrite
lock in this case, but that might lead to confusion.
Added test/testlock.c which will attempt to test *both* APR_MUTEX
and APR_READWRITE. This was based off of the testthread.c, but has
been rewritten to use the new stdin/stdout/stderr code and just
make more sense overall. testthread.c should probably be rewritten
to test threading more specifically.
Added framework that will hopefully still let BeOS, OS/2, and Win32
compile. Any operation relating to an APR_READWRITE lock on these
platforms should just return APR_ENOTIMPL until the appropriate
people get around to it. Some structure has been added to make what
they have to implement fairly obvious. Again, I hope it compiles,
but I can't guarantee it.
Christian Gross has a Win32 readwrite lock patch floating around,
but I can't vouch for Win32 code. The other platforms probably
have ways to do it, but I'm not sure what they are.
(Sorry, I write long commit messages...)
Revision Changes Path
1.109 +4 -0 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -r1.108 -r1.109
--- CHANGES 2001/05/31 00:11:02 1.108
+++ CHANGES 2001/05/31 03:29:50 1.109
@@ -1,5 +1,9 @@
Changes with APR b1
+ *) Implement APR_READWRITE locks on Unix with POSIX rwlocks.
+ Introduce new apr_lock_acquire_rw() function which takes in
+ APR_READER or APR_WRITER. [Justin Erenkrantz]
+
*) Add apr_open_stdin. This mirrors apr_open_stderr, except it works
on stdin. [Aaron Bannert <[EMAIL PROTECTED]>]
1.310 +1 -1 apr/configure.in
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.309
retrieving revision 1.310
diff -u -r1.309 -r1.310
--- configure.in 2001/05/18 02:35:51 1.309
+++ configure.in 2001/05/31 03:29:51 1.310
@@ -280,7 +280,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
1.24 +11 -0 apr/include/apr_lock.h
Index: apr_lock.h
===================================================================
RCS file: /home/cvs/apr/include/apr_lock.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- apr_lock.h 2001/02/16 04:15:46 1.23
+++ apr_lock.h 2001/05/31 03:29:53 1.24
@@ -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.
1.27 +6 -3 apr/include/arch/unix/locks.h
Index: locks.h
===================================================================
RCS file: /home/cvs/apr/include/arch/unix/locks.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- locks.h 2001/02/25 20:39:32 1.26
+++ locks.h 2001/05/31 03:29:54 1.27
@@ -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 */
1.27 +77 -27 apr/locks/beos/locks.c
Index: locks.c
===================================================================
RCS file: /home/cvs/apr/locks/beos/locks.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- locks.c 2001/02/16 04:15:53 1.26
+++ locks.c 2001/05/31 03:29:56 1.27
@@ -62,7 +62,11 @@
{
apr_lock_t *new;
apr_status_t stat;
-
+
+ /* FIXME: Remove when read write locks implemented. */
+ if (type == APR_READWRITE)
+ return APR_ENOTIMPL;
+
new = (apr_lock_t *)apr_palloc(cont, sizeof(apr_lock_t));
if (new == NULL){
return APR_ENOMEM;
@@ -89,49 +93,95 @@
apr_status_t apr_lock_acquire(apr_lock_t *lock)
{
apr_status_t stat;
-
- if (lock->scope != APR_CROSS_PROCESS) {
- if ((stat = lock_intra(lock)) != APR_SUCCESS) {
- return stat;
- }
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->scope != APR_CROSS_PROCESS) {
+ if ((stat = lock_intra(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ if (lock->scope != APR_INTRAPROCESS) {
+ if ((stat = lock_inter(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
- if (lock->scope != APR_INTRAPROCESS) {
- if ((stat = lock_inter(lock)) != APR_SUCCESS) {
- return stat;
+
+ return APR_SUCCESS;
+}
+
+apr_status_t apr_lock_acquire_rw(apr_lock_t *lock, apr_readerwriter_e e)
+{
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ return APR_ENOTIMPL;
+ case APR_READWRITE:
+ switch (e)
+ {
+ case APR_READER:
+ break;
+ case APR_WRITER:
+ break;
}
+ return APR_ENOTIMPL;
}
+
return APR_SUCCESS;
}
apr_status_t apr_lock_release(apr_lock_t *lock)
{
apr_status_t stat;
- if (lock->scope != APR_CROSS_PROCESS) {
- if ((stat = unlock_intra(lock)) != APR_SUCCESS) {
- return stat;
- }
- }
- if (lock->scope != APR_INTRAPROCESS) {
- if ((stat = unlock_inter(lock)) != APR_SUCCESS) {
- return stat;
- }
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->scope != APR_CROSS_PROCESS) {
+ if ((stat = unlock_intra(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ if (lock->scope != APR_INTRAPROCESS) {
+ if ((stat = unlock_inter(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
+
return APR_SUCCESS;
}
apr_status_t apr_lock_destroy(apr_lock_t *lock)
{
apr_status_t stat;
- if (lock->scope != APR_CROSS_PROCESS) {
- if ((stat = destroy_intra_lock(lock)) != APR_SUCCESS) {
- return stat;
- }
- }
- if (lock->scope != APR_INTRAPROCESS) {
- if ((stat = destroy_inter_lock(lock)) != APR_SUCCESS) {
- return stat;
- }
+
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->scope != APR_CROSS_PROCESS) {
+ if ((stat = destroy_intra_lock(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ if (lock->scope != APR_INTRAPROCESS) {
+ if ((stat = destroy_inter_lock(lock)) != APR_SUCCESS) {
+ return stat;
+ }
+ }
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
+
return APR_SUCCESS;
}
1.28 +65 -23 apr/locks/os2/locks.c
Index: locks.c
===================================================================
RCS file: /home/cvs/apr/locks/os2/locks.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- locks.c 2001/03/19 12:43:25 1.27
+++ locks.c 2001/05/31 03:29:58 1.28
@@ -71,14 +71,19 @@
-apr_status_t apr_lock_create(apr_lock_t **lock, apr_locktype_e type,
apr_lockscope_e scope,
- const char *fname, apr_pool_t *cont)
+apr_status_t apr_lock_create(apr_lock_t **lock, apr_locktype_e type,
+ apr_lockscope_e scope, const char *fname,
+ apr_pool_t *cont)
{
apr_lock_t *new;
ULONG rc;
char *semname;
PIB *ppib;
+ /* FIXME: Remove when read write locks implemented. */
+ if (type == APR_READWRITE)
+ return APR_ENOTIMPL;
+
new = (apr_lock_t *)apr_palloc(cont, sizeof(apr_lock_t));
new->cntxt = cont;
new->type = type;
@@ -131,27 +136,58 @@
apr_status_t apr_lock_acquire(apr_lock_t *lock)
{
ULONG rc;
-
- rc = DosRequestMutexSem(lock->hMutex, SEM_INDEFINITE_WAIT);
- if (rc == 0) {
- lock->owner = CurrentTid;
- lock->lock_count++;
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ rc = DosRequestMutexSem(lock->hMutex, SEM_INDEFINITE_WAIT);
+
+ if (rc == 0) {
+ lock->owner = CurrentTid;
+ lock->lock_count++;
+ }
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
return APR_OS2_STATUS(rc);
}
-
+apr_status_t apr_lock_acquire_rw(apr_lock_t *lock, apr_readerwriter_e e)
+{
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ return APR_ENOTIMPL;
+ case APR_READWRITE:
+ switch (e)
+ {
+ case APR_READER:
+ break;
+ case APR_WRITER:
+ break;
+ }
+ return APR_ENOTIMPL;
+ }
+ return APR_SUCCESS;
+}
apr_status_t apr_lock_release(apr_lock_t *lock)
{
ULONG rc;
- if (lock->owner == CurrentTid && lock->lock_count > 0) {
- lock->lock_count--;
- rc = DosReleaseMutexSem(lock->hMutex);
- return APR_OS2_STATUS(rc);
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->owner == CurrentTid && lock->lock_count > 0) {
+ lock->lock_count--;
+ rc = DosReleaseMutexSem(lock->hMutex);
+ return APR_OS2_STATUS(rc);
+ }
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
return APR_SUCCESS;
@@ -164,21 +200,27 @@
ULONG rc;
apr_status_t stat = APR_SUCCESS;
- if (lock->owner == CurrentTid) {
- while (lock->lock_count > 0 && stat == APR_SUCCESS)
- stat = apr_lock_release(lock);
- }
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->owner == CurrentTid) {
+ while (lock->lock_count > 0 && stat == APR_SUCCESS)
+ stat = apr_lock_release(lock);
- if (stat != APR_SUCCESS)
- return stat;
+ if (stat != APR_SUCCESS)
+ return stat;
- if (lock->hMutex == 0)
- return APR_SUCCESS;
+ if (lock->hMutex == 0)
+ return APR_SUCCESS;
- rc = DosCloseMutexSem(lock->hMutex);
+ rc = DosCloseMutexSem(lock->hMutex);
- if (!rc)
- lock->hMutex = 0;
+ if (!rc)
+ lock->hMutex = 0;
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
+ }
return APR_OS2_STATUS(rc);
}
1.47 +80 -0 apr/locks/unix/locks.c
Index: locks.c
===================================================================
RCS file: /home/cvs/apr/locks/unix/locks.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- locks.c 2001/02/16 04:15:55 1.46
+++ locks.c 2001/05/31 03:29:59 1.47
@@ -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,18 @@
return stat;
}
}
+ break;
+ case APR_READWRITE:
+#ifdef HAVE_PTHREAD_RWLOCK_INIT
+ if (scope != APR_INTRAPROCESS)
+ return APR_ENOTIMPL;
+ pthread_rwlock_init(&new->rwlock, NULL);
+ break;
+#else
+ return APR_ENOTIMPL;
+#endif
+ }
+
*lock = new;
return APR_SUCCESS;
}
@@ -104,6 +119,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 +141,49 @@
return stat;
}
}
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
+ }
+
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 +202,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 +242,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;
}
1.37 +68 -19 apr/locks/win32/locks.c
Index: locks.c
===================================================================
RCS file: /home/cvs/apr/locks/win32/locks.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- locks.c 2001/02/16 04:15:56 1.36
+++ locks.c 2001/05/31 03:30:03 1.37
@@ -66,6 +66,10 @@
apr_lock_t *newlock;
SECURITY_ATTRIBUTES sec;
+ /* FIXME: Remove when read write locks implemented. */
+ if (type == APR_READWRITE)
+ return APR_ENOTIMPL;
+
newlock = (apr_lock_t *)apr_palloc(cont, sizeof(apr_lock_t));
newlock->cntxt = cont;
@@ -118,42 +122,87 @@
APR_DECLARE(apr_status_t) apr_lock_acquire(apr_lock_t *lock)
{
DWORD rv;
- if (lock->scope == APR_INTRAPROCESS) {
- EnterCriticalSection(&lock->section);
- return APR_SUCCESS;
- } else {
- rv = WaitForSingleObject(lock->mutex, INFINITE);
-
- if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->scope == APR_INTRAPROCESS) {
+ EnterCriticalSection(&lock->section);
return APR_SUCCESS;
+ } else {
+ rv = WaitForSingleObject(lock->mutex, INFINITE);
+
+ if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+ return APR_SUCCESS;
+ }
}
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
+
return apr_get_os_error();
}
+APR_DECLARE(apr_status_t) apr_lock_acquire_rw(apr_lock_t *lock,
+ apr_readerwriter_e e)
+{
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ return APR_ENOTIMPL;
+ case APR_READWRITE:
+ switch (e)
+ {
+ case APR_READER:
+ break;
+ case APR_WRITER:
+ break;
+ }
+ return APR_ENOTIMPL;
+ }
+
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_lock_release(apr_lock_t *lock)
{
- if (lock->scope == APR_INTRAPROCESS) {
- LeaveCriticalSection(&lock->section);
- return APR_SUCCESS;
- } else {
- if (ReleaseMutex(lock->mutex) == 0) {
- return apr_get_os_error();
+ switch (apr->lock)
+ {
+ case APR_MUTEX:
+ if (lock->scope == APR_INTRAPROCESS) {
+ LeaveCriticalSection(&lock->section);
+ return APR_SUCCESS;
+ } else {
+ if (ReleaseMutex(lock->mutex) == 0) {
+ return apr_get_os_error();
+ }
}
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
+
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_lock_destroy(apr_lock_t *lock)
{
- if (lock->scope == APR_INTRAPROCESS) {
- DeleteCriticalSection(&lock->section);
- return APR_SUCCESS;
- } else {
- if (CloseHandle(lock->mutex) == 0) {
- return apr_get_os_error();
+ switch (lock->type)
+ {
+ case APR_MUTEX:
+ if (lock->scope == APR_INTRAPROCESS) {
+ DeleteCriticalSection(&lock->section);
+ return APR_SUCCESS;
+ } else {
+ if (CloseHandle(lock->mutex) == 0) {
+ return apr_get_os_error();
+ }
}
+ break;
+ case APR_READWRITE:
+ return APR_ENOTIMPL;
}
+
return APR_SUCCESS;
}
1.23 +1 -0 apr/test/.cvsignore
Index: .cvsignore
===================================================================
RCS file: /home/cvs/apr/test/.cvsignore,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- .cvsignore 2001/05/23 14:15:49 1.22
+++ .cvsignore 2001/05/31 03:30:05 1.23
@@ -39,3 +39,4 @@
testnames
*.dbg
testmem
+testlock
1.56 +4 -0 apr/test/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/apr/test/Makefile.in,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- Makefile.in 2001/05/23 14:15:50 1.55
+++ Makefile.in 2001/05/31 03:30:05 1.56
@@ -9,6 +9,7 @@
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@ \
+ [EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@ \
@@ -72,6 +73,9 @@
[EMAIL PROTECTED]@: testthread.lo $(LOCAL_LIBS)
$(LINK) testthread.lo $(LOCAL_LIBS) $(ALL_LIBS)
+
[EMAIL PROTECTED]@: testlock.lo $(LOCAL_LIBS)
+ $(LINK) testlock.lo $(LOCAL_LIBS) $(ALL_LIBS)
[EMAIL PROTECTED]@: testsock.lo [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ [EMAIL
PROTECTED]@ $(LOCAL_LIBS)
$(LINK) testsock.lo $(LOCAL_LIBS) $(ALL_LIBS)
1.1 apr/test/testlock.c
Index: testlock.c
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
#include "apr_thread_proc.h"
#include "apr_file_io.h"
#include "apr_lock.h"
#include "apr_errno.h"
#include "apr_general.h"
#include "errno.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef BEOS
#include <unistd.h>
#endif
#if !APR_HAS_THREADS
int main(void)
{
fprintf(stderr,
"This program won't work on this platform because there is no "
"support for threads.\n");
return 0;
}
#else /* !APR_HAS_THREADS */
#define MAX_ITER 40000
void * APR_THREAD_FUNC thread_rw_func(void *data);
void * APR_THREAD_FUNC thread_func(void *data);
apr_file_t *in, *out, *err;
apr_lock_t *thread_rw_lock, *thread_lock;
apr_pool_t *context;
int i = 0, x = 0;
void * APR_THREAD_FUNC thread_rw_func(void *data)
{
int exitLoop = 1;
while (1)
{
apr_lock_acquire_rw(thread_rw_lock, APR_READER);
if (i == MAX_ITER)
exitLoop = 0;
apr_lock_release(thread_rw_lock);
if (!exitLoop)
break;
apr_lock_acquire_rw(thread_rw_lock, APR_WRITER);
if (i != MAX_ITER)
{
i++;
x++;
}
apr_lock_release(thread_rw_lock);
}
return NULL;
}
void * APR_THREAD_FUNC thread_func(void *data)
{
int exitLoop = 1;
while (1)
{
apr_lock_acquire(thread_lock);
if (i == MAX_ITER)
exitLoop = 0;
else
{
i++;
x++;
}
apr_lock_release(thread_lock);
if (!exitLoop)
break;
}
return NULL;
}
int test_rw(void)
{
apr_thread_t *t1, *t2, *t3, *t4;
apr_status_t s1, s2, s3, s4;
apr_file_printf(out, "Initializing the rw lock.");
s1 = apr_lock_create(&thread_rw_lock, APR_READWRITE, APR_INTRAPROCESS,
"lock.file", context);
if (s1 != APR_SUCCESS) {
apr_file_printf(err, "Could not create lock\n");
return s1;
}
apr_file_printf(out, " OK\n");
i = 0;
x = 0;
apr_file_printf(out, "Starting all the threads.......");
s1 = apr_thread_create(&t1, NULL, thread_rw_func, NULL, context);
s2 = apr_thread_create(&t2, NULL, thread_rw_func, NULL, context);
s3 = apr_thread_create(&t3, NULL, thread_rw_func, NULL, context);
s4 = apr_thread_create(&t4, NULL, thread_rw_func, NULL, context);
if (s1 != APR_SUCCESS || s2 != APR_SUCCESS ||
s3 != APR_SUCCESS || s4 != APR_SUCCESS) {
apr_file_printf(err, "Error starting threads\n");
return s1;
}
apr_file_printf(out, "OK\n");
apr_file_printf(out, "Waiting for threads to exit.......");
apr_thread_join(&s1, t1);
apr_thread_join(&s2, t2);
apr_thread_join(&s3, t3);
apr_thread_join(&s4, t4);
apr_file_printf(out, "OK\n");
apr_file_printf(out, "OK\n");
if (x != MAX_ITER) {
apr_file_printf(err, "The locks didn't work???? %d\n", x);
}
else {
apr_file_printf(out, "Everything is working!\n");
}
return APR_SUCCESS;
}
int test_exclusive(void)
{
apr_thread_t *t1, *t2, *t3, *t4;
apr_status_t s1, s2, s3, s4;
apr_file_printf(out, "Initializing the lock.");
s1 = apr_lock_create(&thread_lock, APR_MUTEX, APR_INTRAPROCESS,
"lock.file", context);
if (s1 != APR_SUCCESS) {
apr_file_printf(err, "Could not create lock\n");
return s1;
}
apr_file_printf(out, " OK\n");
i = 0;
x = 0;
apr_file_printf(out, "Starting all the threads.......");
s1 = apr_thread_create(&t1, NULL, thread_func, NULL, context);
s2 = apr_thread_create(&t2, NULL, thread_func, NULL, context);
s3 = apr_thread_create(&t3, NULL, thread_func, NULL, context);
s4 = apr_thread_create(&t4, NULL, thread_func, NULL, context);
if (s1 != APR_SUCCESS || s2 != APR_SUCCESS ||
s3 != APR_SUCCESS || s4 != APR_SUCCESS) {
apr_file_printf(err, "Error starting threads\n");
return s1;
}
apr_file_printf(out, "OK\n");
apr_file_printf(out, "Waiting for threads to exit.......");
apr_thread_join(&s1, t1);
apr_thread_join(&s2, t2);
apr_thread_join(&s3, t3);
apr_thread_join(&s4, t4);
apr_file_printf(out, "OK\n");
apr_file_printf(out, "OK\n");
if (x != MAX_ITER) {
apr_file_printf(err, "The locks didn't work???? %d\n", x);
}
else {
apr_file_printf(out, "Everything is working!\n");
}
return APR_SUCCESS;
}
int main(void)
{
apr_initialize();
atexit(apr_terminate);
if (apr_pool_create(&context, NULL) != APR_SUCCESS)
exit(-1);
apr_file_open_stdin(&in, context);
apr_file_open_stdout(&out, context);
apr_file_open_stderr(&err, context);
apr_file_printf(out, "OK\n");
if (test_rw() != APR_SUCCESS)
exit(-2);
if (test_exclusive() != APR_SUCCESS)
exit(-3);
return 1;
}
#endif /* !APR_HAS_THREADS */