You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by dr...@apache.org on 2001/10/28 14:05:51 UTC
cvs commit: apr/locks/beos proc_mutex.c thread_mutex.c thread_rwlock.c
dreid 01/10/28 05:05:51
Modified: locks/beos proc_mutex.c thread_mutex.c thread_rwlock.c
Log:
Add the actual code for most of the new lock methods. Just the conditional
implementation to add at some point.
Revision Changes Path
1.4 +65 -6 apr/locks/beos/proc_mutex.c
Index: proc_mutex.c
===================================================================
RCS file: /home/cvs/apr/locks/beos/proc_mutex.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- proc_mutex.c 2001/10/19 23:25:28 1.3
+++ proc_mutex.c 2001/10/28 13:05:51 1.4
@@ -60,13 +60,51 @@
#include "apr_strings.h"
#include "apr_portable.h"
+static apr_status_t _proc_mutex_cleanup(void * data)
+{
+ apr_proc_mutex_t *lock = (apr_proc_mutex_t*)data;
+ if (lock->LockCount != 0) {
+ /* we're still locked... */
+ while (atomic_add(&lock->LockCount , -1) > 1){
+ /* OK we had more than one person waiting on the lock so
+ * the sem is also locked. Release it until we have no more
+ * locks left.
+ */
+ release_sem (lock->Lock);
+ }
+ }
+ delete_sem(lock->Lock);
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
const char *fname,
apr_pool_t *pool)
{
- return APR_ENOTIMPL;
+ apr_proc_mutex_t *new;
+ apr_status_t stat = APR_SUCCESS;
+
+ new = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+ if (new == NULL){
+ return APR_ENOMEM;
+ }
+
+ if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) {
+ _proc_mutex_cleanup(new);
+ return stat;
+ }
+ new->LockCount = 0;
+ new->Lock = stat;
+ new->pool = pool;
+
+ apr_pool_cleanup_register(new->pool, (void *)new, _proc_mutex_cleanup,
+ apr_pool_cleanup_null);
+
+ (*mutex) = new;
+ return APR_SUCCESS;
}
+#if APR_HAS_CREATE_LOCKS_NP
APR_DECLARE(apr_status_t) apr_proc_mutex_create_np(apr_proc_mutex_t **mutex,
const char *fname,
apr_lockmech_e_np mech,
@@ -74,6 +112,7 @@
{
return APR_ENOTIMPL;
}
+#endif
APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex,
const char *fname,
@@ -84,7 +123,15 @@
APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ return stat;
+ }
+ }
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
@@ -94,12 +141,25 @@
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+
+ if (atomic_add(&mutex->LockCount, -1) > 1) {
+ if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, 1);
+ return stat;
+ }
+ }
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ apr_status_t stat;
+ if ((stat = _proc_mutex_cleanup(mutex)) == APR_SUCCESS) {
+ apr_pool_cleanup_kill(mutex->pool, mutex, _proc_mutex_cleanup);
+ return APR_SUCCESS;
+ }
+ return stat;
}
APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
@@ -122,8 +182,7 @@
return APR_ENOPOOL;
}
if ((*pmutex) == NULL) {
- (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool,
- sizeof(apr_proc_mutex_t));
+ (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
(*pmutex)->pool = pool;
}
(*pmutex)->Lock = ospmutex->sem;
1.4 +103 -11 apr/locks/beos/thread_mutex.c
Index: thread_mutex.c
===================================================================
RCS file: /home/cvs/apr/locks/beos/thread_mutex.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- thread_mutex.c 2001/10/17 00:33:00 1.3
+++ thread_mutex.c 2001/10/28 13:05:51 1.4
@@ -60,21 +60,91 @@
#include "apr_strings.h"
#include "apr_portable.h"
-static apr_status_t thread_mutex_cleanup(void *data)
+static apr_status_t _thread_mutex_cleanup(void * data)
{
- return APR_ENOTIMPL;
-}
+ apr_thread_mutex_t *lock = (apr_thread_mutex_t*)data;
+ if (lock->LockCount != 0) {
+ /* we're still locked... */
+ while (atomic_add(&lock->LockCount , -1) > 1){
+ /* OK we had more than one person waiting on the lock so
+ * the sem is also locked. Release it until we have no more
+ * locks left.
+ */
+ release_sem (lock->Lock);
+ }
+ }
+ delete_sem(lock->Lock);
+ return APR_SUCCESS;
+}
APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
unsigned int flags,
apr_pool_t *pool)
{
- return APR_ENOTIMPL;
+ apr_thread_mutex_t *new_m;
+ apr_status_t stat = APR_SUCCESS;
+
+ new_m = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+ if (new_m == NULL){
+ return APR_ENOMEM;
+ }
+
+ if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) {
+ _thread_mutex_cleanup(new_m);
+ return stat;
+ }
+ new_m->LockCount = 0;
+ new_m->Lock = stat;
+ new_m->pool = pool;
+ new_m->nested = flags & APR_THREAD_MUTEX_NESTED;
+
+ apr_pool_cleanup_register(new_m->pool, (void *)new_m, _thread_mutex_cleanup,
+ apr_pool_cleanup_null);
+
+ (*mutex) = new_m;
+ return APR_SUCCESS;
+}
+
+#if APR_HAS_CREATE_LOCKS_NP
+APR_DECLARE(apr_status_t) apr_thread_mutex_create_np(apr_thread_mutex_t **mutex,
+ const char *fname,
+ apr_lockmech_e_np mech,
+ apr_pool_t *pool)
+{
+ return APR_ENOTIMPL;
+}
+#endif
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_child_init(apr_thread_mutex_t **mutex,
+ const char *fname,
+ apr_pool_t *pool)
+{
+ return APR_SUCCESS;
}
-
+
APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+
+ if (mutex->nested && mutex->owner == find_thread(NULL)) {
+ mutex->owner_ref++;
+ return APR_SUCCESS;
+ }
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+ /* Oh dear, acquire_sem failed!! */
+ atomic_add(&mutex->LockCount, -1);
+ return stat;
+ }
+ }
+
+ if (mutex->nested) {
+ mutex->owner = find_thread(NULL);
+ mutex->owner_ref = 1;
+ }
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
@@ -84,13 +154,35 @@
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+
+ if (mutex->nested && mutex->owner == find_thread(NULL)) {
+ mutex->owner_ref--;
+ if (mutex->owner_ref > 0)
+ return APR_SUCCESS;
+ }
+
+ if (atomic_add(&mutex->LockCount, -1) > 1) {
+ if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, 1);
+ return stat;
+ }
+ }
+
+ if (mutex->nested) {
+ mutex->owner = -1;
+ mutex->owner_ref = 0;
+ }
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ apr_status_t stat;
+ if ((stat = _thread_mutex_cleanup(mutex)) == APR_SUCCESS) {
+ apr_pool_cleanup_kill(mutex->pool, mutex, _thread_mutex_cleanup);
+ return APR_SUCCESS;
+ }
+ return stat;
}
-
-APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
-
1.3 +133 -5 apr/locks/beos/thread_rwlock.c
Index: thread_rwlock.c
===================================================================
RCS file: /home/cvs/apr/locks/beos/thread_rwlock.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- thread_rwlock.c 2001/09/29 05:04:44 1.2
+++ thread_rwlock.c 2001/10/28 13:05:51 1.3
@@ -60,15 +60,82 @@
#include "apr_strings.h"
#include "apr_portable.h"
+#define BIG_NUM 100000
+
+static apr_status_t _thread_rw_cleanup(void * data)
+{
+ apr_thread_rwlock_t *mutex = (apr_thread_rwlock_t*)data;
+
+ if (mutex->ReadCount != 0) {
+ while (atomic_add(&mutex->ReadCount , -1) > 1){
+ release_sem (mutex->Read);
+ }
+ }
+ if (mutex->WriteCount != 0) {
+ while (atomic_add(&mutex->WriteCount , -1) > 1){
+ release_sem (mutex->Write);
+ }
+ }
+ if (mutex->LockCount != 0) {
+ while (atomic_add(&mutex->LockCount , -1) > 1){
+ release_sem (mutex->Lock);
+ }
+ }
+
+ delete_sem(mutex->Read);
+ delete_sem(mutex->Write);
+ delete_sem(mutex->Lock);
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock,
apr_pool_t *pool)
{
- return APR_ENOTIMPL;
+ apr_thread_rwlock_t *new;
+
+ new = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t));
+ if (new == NULL){
+ return APR_ENOMEM;
+ }
+
+ new->pool = pool;
+ /* we need to make 3 locks... */
+ new->ReadCount = 0;
+ new->WriteCount = 0;
+ new->LockCount = 0;
+ new->Read = create_sem(0, "APR_ReadLock");
+ new->Write = create_sem(0, "APR_WriteLock");
+ new->Lock = create_sem(0, "APR_Lock");
+
+ if (new->Lock < 0 || new->Read < 0 || new->Write < 0) {
+ _thread_rw_cleanup(new);
+ return -1;
+ }
+
+ apr_pool_cleanup_register(new->pool, (void *)new, _thread_rw_cleanup,
+ apr_pool_cleanup_null);
+ (*rwlock) = new;
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock)
{
- return APR_ENOTIMPL;
+ int32 rv = APR_SUCCESS;
+
+ if (find_thread(NULL) == rwlock->writer) {
+ /* we're the writer - no problem */
+ rwlock->Nested++;
+ } else {
+ /* we're not the writer */
+ int32 r = atomic_add(&rwlock->ReadCount, 1);
+ if (r < 0) {
+ /* Oh dear, writer holds lock, wait for sem */
+ rv = acquire_sem_etc(rwlock->Read, 1, B_DO_NOT_RESCHEDULE,
+ B_INFINITE_TIMEOUT);
+ }
+ }
+
+ return rv;
}
APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock)
@@ -78,7 +145,33 @@
APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock)
{
- return APR_ENOTIMPL;
+ int rv = APR_SUCCESS;
+
+ if (find_thread(NULL) == rwlock->writer) {
+ rwlock->Nested++;
+ } else {
+ /* we're not the writer... */
+ if (atomic_add(&rwlock->LockCount, 1) >= 1) {
+ /* we're locked - acquire the sem */
+ rv = acquire_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE,
+ B_INFINITE_TIMEOUT);
+ }
+ if (rv == APR_SUCCESS) {
+ /* decrement the ReadCount to a large -ve number so that
+ * we block on new readers...
+ */
+ int32 readers = atomic_add(&rwlock->ReadCount, -BIG_NUM);
+ if (readers > 0) {
+ /* readers are holding the lock */
+ rv = acquire_sem_etc(rwlock->Write, readers, B_DO_NOT_RESCHEDULE,
+ B_INFINITE_TIMEOUT);
+ }
+ if (rv == APR_SUCCESS)
+ rwlock->writer = find_thread(NULL);
+ }
+ }
+
+ return rv;
}
APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock)
@@ -88,12 +181,47 @@
APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock)
{
- return APR_ENOTIMPL;
+ apr_status_t rv = APR_SUCCESS;
+ int32 readers;
+
+ /* we know we hold the lock, so don't check it :) */
+ if (find_thread(NULL) == rwlock->writer) {
+ /* we know we hold the lock, so don't check it :) */
+ if (rwlock->Nested > 1) {
+ /* we're recursively locked */
+ rwlock->Nested--;
+ return APR_SUCCESS;
+ }
+ /* OK so we need to release the sem if we have it :) */
+ readers = atomic_add(&rwlock->ReadCount, BIG_NUM) + BIG_NUM;
+ if (readers > 0) {
+ rv = release_sem_etc(rwlock->Read, readers, B_DO_NOT_RESCHEDULE);
+ }
+ if (rv == APR_SUCCESS) {
+ rwlock->writer = -1;
+ if (atomic_add(&rwlock->LockCount, -1) > 1) {
+ rv = release_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE);
+ }
+ }
+ } else {
+ /* We weren't the Writer, so just release the ReadCount... */
+ if (atomic_add(&rwlock->ReadCount, -1) < 0) {
+ /* we have a writer waiting for the lock, so release it */
+ rv = release_sem_etc(rwlock->Write, 1, B_DO_NOT_RESCHEDULE);
+ }
+ }
+
+ return rv;
}
APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock)
{
- return APR_ENOTIMPL;
+ apr_status_t stat;
+ if ((stat = _thread_rw_cleanup(rwlock)) == APR_SUCCESS) {
+ apr_pool_cleanup_kill(rwlock->pool, rwlock, _thread_rw_cleanup);
+ return APR_SUCCESS;
+ }
+ return stat;
}
APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock)