summaryrefslogtreecommitdiffstats
path: root/lib/base/crit.cpp
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /lib/base/crit.cpp
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'lib/base/crit.cpp')
-rw-r--r--lib/base/crit.cpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/lib/base/crit.cpp b/lib/base/crit.cpp
new file mode 100644
index 00000000..06f5fba4
--- /dev/null
+++ b/lib/base/crit.cpp
@@ -0,0 +1,399 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * crit.c: Critical section abstraction. Used in threaded servers to protect
+ * areas where two threads can interfere with each other.
+ *
+ * Condvars are condition variables that are used for thread-thread
+ * synchronization.
+ *
+ * Rob McCool
+ */
+
+#include "systems.h"
+
+#include "netsite.h"
+#include "crit.h"
+#include "pool.h"
+#include "ereport.h"
+
+#include "base/dbtbase.h"
+
+#ifdef USE_NSPR
+/*
+#include "prmon.h"
+#include "private/primpl.h"
+*/
+#include "nspr.h"
+
+/* private/primpl.h is gone fromnspr21 19971028 */
+#if 0
+#ifdef XP_WIN32
+#include "private/primpl.h"
+#endif /* XP_WIN32 */
+#endif
+
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prinrval.h"
+
+/*
+ * Defined to replace PR_Monitor() with PR_Lock().
+ */
+typedef struct critical {
+ PRLock *lock;
+ PRUint32 count;
+ PRThread *owner;
+} critical_t;
+
+typedef struct condvar {
+ critical_t *lock;
+ PRCondVar *cvar;
+} condvar_t;
+
+#endif
+/* -------------------------- critical sections --------------------------- */
+
+/* Useful for ASSERTs only. Returns non-zero if the current thread is the owner.
+ */
+NSAPI_PUBLIC int crit_owner_is_me(CRITICAL id)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)id;
+
+ return (crit->owner == PR_GetCurrentThread());
+#else
+ return 1;
+#endif
+}
+
+NSAPI_PUBLIC CRITICAL crit_init(void)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)PERM_MALLOC(sizeof(critical_t)) ;
+
+ if (crit) {
+ if (!(crit->lock = PR_NewLock())) {
+ PERM_FREE(crit);
+ return NULL;
+ }
+ crit->count = 0;
+ crit->owner = 0;
+ }
+ return (void *) crit;
+#else
+ return NULL;
+#endif
+}
+
+NSAPI_PUBLIC void crit_enter(CRITICAL id)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)id;
+ PRThread *me = PR_GetCurrentThread();
+
+ if ( crit->owner == me) {
+ NS_ASSERT(crit->count > 0);
+ crit->count++;
+ }
+ else {
+ PR_Lock(crit->lock);
+ NS_ASSERT(crit->count == 0);
+ crit->count = 1;
+ crit->owner = me;
+ }
+#endif
+}
+
+NSAPI_PUBLIC void crit_exit(CRITICAL id)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)id;
+
+ if (crit->owner != PR_GetCurrentThread())
+ return;
+
+ if ( --crit->count == 0) {
+ crit->owner = 0;
+ PR_Unlock(crit->lock);
+ }
+ NS_ASSERT(crit->count >= 0);
+#endif
+}
+
+NSAPI_PUBLIC void crit_terminate(CRITICAL id)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)id;
+
+ PR_DestroyLock((PRLock*)crit->lock);
+ PERM_FREE(crit);
+#endif
+}
+
+
+/* ------------------------- condition variables -------------------------- */
+
+
+NSAPI_PUBLIC CONDVAR condvar_init(CRITICAL id)
+{
+#ifdef USE_NSPR
+ critical_t *crit = (critical_t*)id;
+
+ condvar_t *cvar = (condvar_t*)PERM_MALLOC(sizeof(condvar_t)) ;
+
+ if (crit) {
+ cvar->lock = crit;
+ if ((cvar->cvar = PR_NewCondVar((PRLock *)cvar->lock->lock)) == 0) {
+ PERM_FREE(cvar);
+ return NULL;
+ }
+ }
+ return (void *) cvar;
+#endif
+}
+
+NSAPI_PUBLIC void condvar_wait(CONDVAR _cv)
+{
+#ifdef USE_NSPR
+ condvar_t *cv = (condvar_t *)_cv;
+ /* Save away recursion count so we can restore it after the wait */
+ int saveCount = cv->lock->count;
+ PRThread *saveOwner = cv->lock->owner;
+
+ NS_ASSERT(cv->lock->owner == PR_GetCurrentThread());
+ cv->lock->count = 0;
+ cv->lock->owner = 0;
+
+ PR_WaitCondVar(cv->cvar, PR_INTERVAL_NO_TIMEOUT);
+
+ cv->lock->count = saveCount;
+ cv->lock->owner = saveOwner;
+#endif
+}
+
+
+NSAPI_PUBLIC void condvar_timed_wait(CONDVAR _cv, long secs)
+{
+#ifdef USE_NSPR
+ condvar_t *cv = (condvar_t *)_cv;
+ /* Save away recursion count so we can restore it after the wait */
+ int saveCount = cv->lock->count;
+ PRThread *saveOwner = cv->lock->owner;
+
+ NS_ASSERT(cv->lock->owner == PR_GetCurrentThread());
+ cv->lock->count = 0;
+ cv->lock->owner = 0;
+
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
+ if (secs > 0)
+ timeout = PR_SecondsToInterval(secs);
+ PR_WaitCondVar(cv->cvar, timeout);
+
+ cv->lock->count = saveCount;
+ cv->lock->owner = saveOwner;
+#endif
+}
+
+
+
+NSAPI_PUBLIC void condvar_notify(CONDVAR _cv)
+{
+#ifdef USE_NSPR
+ condvar_t *cv = (condvar_t *)_cv;
+ NS_ASSERT(cv->lock->owner == PR_GetCurrentThread());
+ PR_NotifyCondVar(cv->cvar);
+#endif
+}
+
+NSAPI_PUBLIC void condvar_notifyAll(CONDVAR _cv)
+{
+#ifdef USE_NSPR
+ condvar_t *cv = (condvar_t *)_cv;
+ NS_ASSERT(cv->lock->owner == PR_GetCurrentThread());
+ PR_NotifyAllCondVar(cv->cvar);
+#endif
+}
+
+NSAPI_PUBLIC void condvar_terminate(CONDVAR _cv)
+{
+#ifdef USE_NSPR
+ condvar_t *cv = (condvar_t *)_cv;
+ PR_DestroyCondVar(cv->cvar);
+ PERM_FREE(cv);
+#endif
+}
+
+/* ----------------------- Counting semaphores ---------------------------- */
+/* These are currently not listed in crit.h because they aren't yet used;
+ * although they do work.
+ */
+
+/*
+ * XXXMB - these should be in NSPR.
+ *
+ */
+
+#if defined(SOLARIS) && defined(HW_THREADS)
+#include <synch.h>
+typedef sema_t counting_sem_t;
+#elif defined(IRIX) && defined(HW_THREADS)
+#include <ulocks.h>
+typedef usema_t *counting_sem_t;
+#else
+typedef struct counting_sem_t {
+ CRITICAL lock;
+ CRITICAL cv_lock;
+ CONDVAR cv;
+ int count;
+ int max;
+} counting_sem_t;
+#endif
+
+NSAPI_PUBLIC COUNTING_SEMAPHORE
+cs_init(int initial_count)
+{
+ counting_sem_t *cs = (counting_sem_t *)PERM_MALLOC(sizeof(counting_sem_t));
+#if defined(SOLARIS) && defined(HW_THREADS)
+ if ( sema_init(cs, initial_count, USYNC_THREAD, NULL) < 0) {
+ ereport(LOG_FAILURE, XP_GetAdminStr(DBT_csInitFailureS_), system_errmsg());
+ PERM_FREE(cs);
+ return NULL;
+ }
+
+ return (COUNTING_SEMAPHORE)cs;
+#elif defined(IRIX) && defined(HW_THREADS)
+ usptr_t *arena;
+
+ usconfig(CONF_INITSIZE, 64*1024);
+ if ( (arena = usinit("/tmp/cs.locks")) == NULL)
+ return NULL;
+
+ if ( (cs = (counting_sem_t *)usnewsema(arena, 0)) == NULL)
+ return NULL;
+
+ return cs;
+
+#else
+
+ cs->count = initial_count;
+ cs->lock = crit_init();
+ cs->cv_lock = crit_init();
+ cs->cv = condvar_init(cs->cv_lock);
+
+ return (COUNTING_SEMAPHORE)cs;
+#endif
+}
+
+NSAPI_PUBLIC void
+cs_terminate(COUNTING_SEMAPHORE csp)
+{
+ counting_sem_t *cs = (counting_sem_t *)csp;
+
+#if defined(SOLARIS) && defined(HW_THREADS)
+ if ( sema_destroy(cs) < 0 ) {
+ ereport(LOG_FAILURE, XP_GetAdminStr(DBT_csTerminateFailureS_), system_errmsg());
+ }
+ PERM_FREE(cs);
+ return;
+#elif defined(IRIX) && defined(HW_THREADS)
+ /* usfreesema() */
+ return;
+#else
+ condvar_terminate(cs->cv);
+ crit_terminate(cs->cv_lock);
+ crit_terminate(cs->lock);
+ PERM_FREE(cs);
+
+ return;
+#endif
+}
+
+NSAPI_PUBLIC int
+cs_wait(COUNTING_SEMAPHORE csp)
+{
+ counting_sem_t *cs = (counting_sem_t *)csp;
+ int ret;
+
+#if defined(SOLARIS) && defined(HW_THREADS)
+ if ( (ret = sema_wait(cs)) < 0 ) {
+ ereport(LOG_FAILURE, XP_GetAdminStr(DBT_csWaitFailureS_), system_errmsg());
+ return -1;
+ }
+ return ret;
+#elif defined(IRIX) && defined(HW_THREADS)
+ uspsema(cs);
+ return 0;
+#else
+ crit_enter(cs->lock);
+ while ( cs->count == 0 ) {
+ crit_enter(cs->cv_lock);
+ crit_exit(cs->lock);
+ condvar_wait(cs->cv);
+ crit_exit(cs->cv_lock);
+ crit_enter(cs->lock);
+ }
+ ret = --(cs->count);
+ crit_exit(cs->lock);
+
+ return 0;
+#endif
+}
+
+NSAPI_PUBLIC int
+cs_trywait(COUNTING_SEMAPHORE csp)
+{
+ counting_sem_t *cs = (counting_sem_t *)csp;
+ int ret;
+
+#if defined(SOLARIS) && defined(HW_THREADS)
+ ret = sema_trywait(cs)?-1:0;
+ return ret;
+#elif defined(IRIX) && defined(HW_THREADS)
+ ret = uscpsema(cs);
+ return (ret == 1)?0:-1;
+#else
+ crit_enter(cs->lock);
+ if (cs->count > 0) {
+ ret = --(cs->count);
+ crit_exit(cs->lock);
+ return 0;
+ }
+ crit_exit(cs->lock);
+ return -1;
+
+#endif
+}
+
+NSAPI_PUBLIC int
+cs_release(COUNTING_SEMAPHORE csp)
+{
+ counting_sem_t *cs = (counting_sem_t *)csp;
+ int ret;
+
+#if defined(SOLARIS) && defined(HW_THREADS)
+ if ( (ret = sema_post(cs)) < 0 ) {
+ ereport(LOG_FAILURE, XP_GetAdminStr(DBT_csPostFailureS_), system_errmsg());
+ return -1;
+ }
+ return ret;
+#elif defined(IRIX) && defined(HW_THREADS)
+ usvsema(cs);
+ return 0;
+#else
+ crit_enter(cs->lock);
+ ret = ++(cs->count);
+ if (cs->count == 1) {
+ crit_enter(cs->cv_lock);
+ condvar_notify(cs->cv);
+ crit_exit(cs->cv_lock);
+ }
+ crit_exit(cs->lock);
+
+ return 0;
+#endif
+}