fixup commit for branch 'PSM_2_2_DEV_20010917_BRANCH' PSM_2_2_DEV_20010917_BRANCH
authorcvs2hg
Thu, 30 Aug 2001 05:30:44 +0000
branchPSM_2_2_DEV_20010917_BRANCH
changeset 2037 5324de775c78
parent 2016 8e47a5d8f3f3
push idunknown
push userunknown
push dateunknown
fixup commit for branch 'PSM_2_2_DEV_20010917_BRANCH'
config/nspr-config.in
config/prdepend.h
pr/include/md/_pth.h
pr/include/private/primpl.h
pr/src/md/unix/unix_errors.c
pr/src/misc/prnetdb.c
pr/src/pthreads/ptsynch.c
--- a/config/nspr-config.in
+++ b/config/nspr-config.in
@@ -102,15 +102,15 @@ if test "$echo_libs" = "yes"; then
       if test -n "$lib_plc"; then
 	libdirs="$libdirs -lplc${major_version}"
       fi
       if test -n "$lib_nspr"; then
 	libdirs="$libdirs -lnspr${major_version}"
       fi
       os_ldflags="@LDFLAGS@"
       for i in $os_ldflags ; do
-	if echo $i | grep ^-L >/dev/null; then
+	if echo $i | grep \^-L >/dev/null; then
 	  libdirs="$libdirs $i"
         fi
       done
       echo $libdirs @OS_LIBS@
 fi      
 
--- a/config/prdepend.h
+++ b/config/prdepend.h
@@ -34,8 +34,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/pr/include/md/_pth.h
+++ b/pr/include/md/_pth.h
@@ -91,16 +91,62 @@
 #define _PT_PTHREAD_MUTEXATTR_DESTROY     pthread_mutexattr_destroy
 #define _PT_PTHREAD_MUTEX_INIT(m, a)      pthread_mutex_init(&(m), &(a))
 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m)    (EBUSY == pthread_mutex_trylock(&(m)))
 #define _PT_PTHREAD_CONDATTR_INIT         pthread_condattr_init
 #define _PT_PTHREAD_CONDATTR_DESTROY      pthread_condattr_destroy
 #define _PT_PTHREAD_COND_INIT(m, a)       pthread_cond_init(&(m), &(a))
 #endif
 
+/* The pthreads standard does not specify an invalid value for the
+ * pthread_t handle.  (0 is usually an invalid pthread identifier
+ * but there are exceptions, for example, DG/UX.)  These macros
+ * define a way to set the handle to or compare the handle with an
+ * invalid identifier.  These macros are not portable and may be
+ * more of a problem as we adapt to more pthreads implementations.
+ * They are only used in the PRMonitor functions.  Do not use them
+ * in new code.
+ *
+ * Unfortunately some of our clients depend on certain properties
+ * of our PRMonitor implementation, preventing us from replacing
+ * it by a portable implementation.
+ * - High-performance servers like the fact that PR_EnterMonitor
+ *   only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock.
+ *   (A portable implementation would use a PRLock and a PRCondVar
+ *   to implement the recursive lock in a monitor and call both
+ *   PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.)
+ *   Unfortunately this forces us to read the monitor owner field
+ *   without holding a lock.
+ * - One way to make it safe to read the monitor owner field
+ *   without holding a lock is to make that field a PRThread*
+ *   (one should be able to read a pointer with a single machine
+ *   instruction).  However, PR_GetCurrentThread calls calloc if
+ *   it is called by a thread that was not created by NSPR.  The
+ *   malloc tracing tools in the Mozilla client use PRMonitor for
+ *   locking in their malloc, calloc, and free functions.  If
+ *   PR_EnterMonitor calls any of these functions, infinite
+ *   recursion ensues.
+ */
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
+	memset(&(t), 0, sizeof(pthread_t))
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
+	(!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
+#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
+	|| defined(HPUX) || defined(LINUX) || defined(FREEBSD) \
+	|| defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
+	|| defined(VMS) || defined(NTO) || defined(RHAPSODY)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t)  (t) = 0
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t)  (t) == 0
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt)   (dt) = (st)
+#else 
+#error "pthreads is not supported for this architecture"
+#endif
+
 #if defined(_PR_DCETHREADS)
 #define _PT_PTHREAD_ATTR_INIT            pthread_attr_create
 #define _PT_PTHREAD_ATTR_DESTROY         pthread_attr_delete
 #define _PT_PTHREAD_CREATE(t, a, f, r)   pthread_create(t, a, f, r) 
 #define _PT_PTHREAD_KEY_CREATE           pthread_keycreate
 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY  pthread_attr_setsched
 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
                                      (*(s) = pthread_attr_getstacksize(*(a)), 0)
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -1445,17 +1445,17 @@ struct PRCondVar {
 };
 
 /************************************************************************/
 
 struct PRMonitor {
     const char* name;           /* monitor name for debugging */
 #if defined(_PR_PTHREADS)
     PRLock lock;                /* the lock structure */
-    PRThread *owner;            /* the owner of the lock or NULL */
+    pthread_t owner;            /* the owner of the lock or invalid */
     PRCondVar *cvar;            /* condition variable queue */
 #else  /* defined(_PR_PTHREADS) */
     PRCondVar *cvar;            /* associated lock and condition variable queue */
 #endif /* defined(_PR_PTHREADS) */
     PRUint32 entryCount;        /* # of times re-entered */
 };
 
 /************************************************************************/
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -378,19 +378,24 @@ void _MD_unix_map_mkdir_error(int err)
     _MD_unix_map_default_error(err);
 }
 
 void _MD_unix_map_rmdir_error(int err)
 {
     PRErrorCode prError;
 
     switch (err) {
+        /*
+         * On AIX 4.3, ENOTEMPTY is defined as EEXIST.
+         */
+#if ENOTEMPTY != EEXIST
         case ENOTEMPTY:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
+#endif
         case EEXIST:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
         case EINVAL:
             prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
             break;
         case ETIMEDOUT:
             prError = PR_REMOTE_FILE_ERROR;
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -79,17 +79,17 @@ PRLock *_pr_dnsLock = NULL;
 
 /*
  * Some platforms have the reentrant getprotobyname_r() and
  * getprotobynumber_r().  However, they come in two flavors.
  * Some return a pointer to struct protoent, others return
  * an int.
  */
 
-#if defined(SOLARIS) \
+#if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \
 	|| (defined(LINUX) && defined(_REENTRANT) \
         && !(defined(__GLIBC__) && __GLIBC__ >= 2))
 #define _PR_HAVE_GETPROTO_R
 #define _PR_HAVE_GETPROTO_R_POINTER
 #endif
 
 #if defined(OSF1) \
         || defined(AIX4_3) || (defined(AIX) && defined(_THREAD_SAFE)) \
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -439,16 +439,18 @@ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(v
     }
     mon = PR_NEWZAP(PRMonitor);
     if (mon != NULL)
     {
         int rv;
         rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr); 
         PR_ASSERT(0 == rv);
 
+        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
+
         mon->cvar = cvar;
         rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr); 
         PR_ASSERT(0 == rv);
         mon->entryCount = 0;
         mon->cvar->lock = &mon->lock;
         if (0 != rv)
         {
             PR_DELETE(mon);
@@ -479,119 +481,120 @@ PR_IMPLEMENT(void) PR_DestroyMonitor(PRM
 }  /* PR_DestroyMonitor */
 
 
 /* The GC uses this; it is quite arguably a bad interface.  I'm just 
  * duplicating it for now - XXXMB
  */
 PR_IMPLEMENT(PRInt32) PR_GetMonitorEntryCount(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
-    if (mon->owner == self)
+    pthread_t self = pthread_self();
+    if (pthread_equal(mon->owner, self))
         return mon->entryCount;
     return 0;
 }
 
 PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
+    pthread_t self = pthread_self();
 
     PR_ASSERT(mon != NULL);
     /*
-     * This is safe only if mon->owner (a PRThread*) can be
-     * read in one instruction.
+     * This is safe only if mon->owner (a pthread_t) can be
+     * read in one instruction.  Perhaps mon->owner should be
+     * a "PRThread *"?
      */
-    if (mon->owner != self)
+    if (!pthread_equal(mon->owner, self))
     {
         PR_Lock(&mon->lock);
         /* and now I have the lock */
         PR_ASSERT(0 == mon->entryCount);
-        PR_ASSERT(NULL == mon->owner);
-        mon->owner = self;
+        PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
+        _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
     }
     mon->entryCount += 1;
 }  /* PR_EnterMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
 {
-    PRThread *self = PR_GetCurrentThread();
+    pthread_t self = pthread_self();
 
     PR_ASSERT(mon != NULL);
     /* The lock better be that - locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* we'd better be the owner */
-    PR_ASSERT(mon->owner == self);
-    if (mon->owner != self)
+    PR_ASSERT(pthread_equal(mon->owner, self));
+    if (!pthread_equal(mon->owner, self))
         return PR_FAILURE;
 
     /* if it's locked and we have it, then the entries should be > 0 */
     PR_ASSERT(mon->entryCount > 0);
     mon->entryCount -= 1;  /* reduce by one */
     if (mon->entryCount == 0)
     {
         /* and if it transitioned to zero - unlock */
-        mon->owner = NULL;  /* make the owner unknown */
+        _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);  /* make the owner unknown */
         PR_Unlock(&mon->lock);
     }
     return PR_SUCCESS;
 }  /* PR_ExitMonitor */
 
 PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
 {
     PRStatus rv;
     PRInt16 saved_entries;
-    PRThread *saved_owner;
+    pthread_t saved_owner;
 
     PR_ASSERT(mon != NULL);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     /* tuck these away 'till later */
     saved_entries = mon->entryCount; 
     mon->entryCount = 0;
-    saved_owner = mon->owner;
-    mon->owner = NULL;
+    _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
+    _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
     
     rv = PR_WaitCondVar(mon->cvar, timeout);
 
     /* reinstate the intresting information */
     mon->entryCount = saved_entries;
-    mon->owner = saved_owner;
+    _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
 
     return rv;
 }  /* PR_Wait */
 
 PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
 {
     PR_ASSERT(NULL != mon);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
 
     return PR_SUCCESS;
 }  /* PR_Notify */
 
 PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
 {
     PR_ASSERT(mon != NULL);
     /* we'd better be locked */
     PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
     /* and the entries better be positive */
     PR_ASSERT(mon->entryCount > 0);
     /* and it better be by us */
-    PR_ASSERT(mon->owner == PR_GetCurrentThread());
+    PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
 
     pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
 
     return PR_SUCCESS;
 }  /* PR_NotifyAll */
 
 /**************************************************************/
 /**************************************************************/