Bug 964437, upgrade Aurora 28 to NSPR 4.10.3 RTM, r=wtc, a=lsblakk
authorKai Engert <kaie@kuix.de>
Wed, 29 Jan 2014 11:58:42 +0100
changeset 176080 0386e163f0f72b27acc5c16e7187260fe919b869
parent 176079 7d1173c4b173af649904f4abfc818b51f0c421d8
child 176081 99276938de235d35299198aba9a373bb8bb70d30
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswtc, lsblakk
bugs964437
milestone28.0a2
Bug 964437, upgrade Aurora 28 to NSPR 4.10.3 RTM, r=wtc, a=lsblakk
nsprpub/TAG-INFO
nsprpub/config/prdepend.h
nsprpub/pr/include/prinit.h
nsprpub/pr/include/prio.h
nsprpub/pr/src/md/unix/unix.c
nsprpub/pr/src/md/windows/ntmisc.c
nsprpub/pr/src/nspr.def
nsprpub/pr/src/pthreads/ptio.c
nsprpub/pr/src/pthreads/ptthread.c
nsprpub/pr/src/threads/combined/prulock.c
nsprpub/pr/src/threads/prrwlock.c
nsprpub/pr/tests/Makefile.in
nsprpub/pr/tests/rwlockrank.c
nsprpub/pr/tests/rwlocktest.c
--- a/nsprpub/TAG-INFO
+++ b/nsprpub/TAG-INFO
@@ -1,1 +1,1 @@
-NSPR_4_10_3_BETA1
+NSPR_4_10_3_RTM
--- a/nsprpub/config/prdepend.h
+++ b/nsprpub/config/prdepend.h
@@ -5,8 +5,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/nsprpub/pr/include/prinit.h
+++ b/nsprpub/pr/include/prinit.h
@@ -26,21 +26,21 @@ PR_BEGIN_EXTERN_C
 /*
 ** NSPR's version is used to determine the likelihood that the version you
 ** used to build your component is anywhere close to being compatible with
 ** what is in the underlying library.
 **
 ** The format of the version string is
 **     "<major version>.<minor version>[.<patch level>] [<Beta>]"
 */
-#define PR_VERSION  "4.10.3 Beta"
+#define PR_VERSION  "4.10.3"
 #define PR_VMAJOR   4
 #define PR_VMINOR   10
 #define PR_VPATCH   3
-#define PR_BETA     PR_TRUE
+#define PR_BETA     PR_FALSE
 
 /*
 ** PRVersionCheck
 **
 ** The basic signature of the function that is called to provide version
 ** checking. The result will be a boolean that indicates the likelihood
 ** that the underling library will perform as the caller expects.
 **
--- a/nsprpub/pr/include/prio.h
+++ b/nsprpub/pr/include/prio.h
@@ -1851,17 +1851,21 @@ NSPR_API(void *) PR_MemMap(
     PRUint32 len);
 
 NSPR_API(PRStatus) PR_MemUnmap(void *addr, PRUint32 len);
 
 NSPR_API(PRStatus) PR_CloseFileMap(PRFileMap *fmap);
 
 /*
  * Synchronously flush the given memory-mapped address range of the given open
- * file to disk.
+ * file to disk. The function does not return until all modified data have
+ * been written to disk.
+ *
+ * On some platforms, the function will call PR_Sync(fd) internally if it is
+ * necessary for flushing modified data to disk synchronously.
  */
 NSPR_API(PRStatus) PR_SyncMemMap(
     PRFileDesc *fd,
     void *addr,
     PRUint32 len);
 
 /*
  ******************************************************************
--- a/nsprpub/pr/src/md/unix/unix.c
+++ b/nsprpub/pr/src/md/unix/unix.c
@@ -3609,24 +3609,19 @@ void * _MD_MemMap(
     }
     return addr;
 }
 
 PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
 {
     if (munmap(addr, len) == 0) {
         return PR_SUCCESS;
-    } else {
-    if (errno == EINVAL) {
-            PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
-    } else {
-        PR_SetError(PR_UNKNOWN_ERROR, errno);
     }
-        return PR_FAILURE;
-    }
+    _PR_MD_MAP_DEFAULT_ERROR(errno);
+    return PR_FAILURE;
 }
 
 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
 {
     if ( PR_TRUE == fmap->md.isAnonFM ) {
         PRStatus rc = PR_Close( fmap->fd );
         if ( PR_FAILURE == rc ) {
             PR_LOG( _pr_io_lm, PR_LOG_DEBUG,
@@ -3638,26 +3633,23 @@ PRStatus _MD_CloseFileMap(PRFileMap *fma
     return PR_SUCCESS;
 }
 
 PRStatus _MD_SyncMemMap(
     PRFileDesc *fd,
     void *addr,
     PRUint32 len)
 {
+    /* msync(..., MS_SYNC) alone is sufficient to flush modified data to disk
+     * synchronously. It is not necessary to call fsync. */
     if (msync(addr, len, MS_SYNC) == 0) {
         return PR_SUCCESS;
-    } else {
-        if (errno == EINVAL) {
-            PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
-        } else {
-            PR_SetError(PR_UNKNOWN_ERROR, errno);
-        }
-        return PR_FAILURE;
     }
+    _PR_MD_MAP_DEFAULT_ERROR(errno);
+    return PR_FAILURE;
 }
 
 #if defined(_PR_NEED_FAKE_POLL)
 
 /*
  * Some platforms don't have poll().  For easier porting of code
  * that calls poll(), we emulate poll() using select().
  */
--- a/nsprpub/pr/src/md/windows/ntmisc.c
+++ b/nsprpub/pr/src/md/windows/ntmisc.c
@@ -977,44 +977,45 @@ void * _MD_MemMap(
     }
     return addr;
 }
 
 PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
 {
     if (UnmapViewOfFile(addr)) {
         return PR_SUCCESS;
-    } else {
-        PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
-        return PR_FAILURE;
     }
+    _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+    return PR_FAILURE;
 }
 
 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
 {
     CloseHandle(fmap->md.hFileMap);
     PR_DELETE(fmap);
     return PR_SUCCESS;
 }
 
 PRStatus _MD_SyncMemMap(
     PRFileDesc *fd,
     void *addr,
     PRUint32 len)
 {
-    PROsfd osfd;
+    PROsfd osfd = fd->secret->md.osfd;
 
-    osfd = ( fd == (PRFileDesc*)-1 )?  -1 : fd->secret->md.osfd;
-
+    /* The FlushViewOfFile page on MSDN says:
+     *  To flush all the dirty pages plus the metadata for the file and
+     *  ensure that they are physically written to disk, call
+     *  FlushViewOfFile and then call the FlushFileBuffers function.
+     */
     if (FlushViewOfFile(addr, len) && FlushFileBuffers((HANDLE) osfd)) {
         return PR_SUCCESS;
-    } else {
-        PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
-        return PR_FAILURE;
     }
+    _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+    return PR_FAILURE;
 }
 
 /*
  ***********************************************************************
  *
  * Atomic increment and decrement operations for x86 processors
  *
  * We don't use InterlockedIncrement and InterlockedDecrement
--- a/nsprpub/pr/src/nspr.def
+++ b/nsprpub/pr/src/nspr.def
@@ -224,17 +224,16 @@ EXPORTS ;-
 		PR_Lock;
 		PR_LockFile;
 		PR_LogFlush;
 		PR_LogPrint;
 		PR_MakeDir;
 		PR_Malloc;
 		PR_MemMap;
 		PR_MemUnmap;
-		PR_SyncMemMap;
 		PR_MicrosecondsToInterval;
 		PR_MillisecondsToInterval;
 		PR_LockOrderedLock;
 		PR_MkDir;
 		PR_NetAddrToString;
 		PR_NewCondVar;
 		PR_NewLock;
 		PR_NewLogModule;
@@ -447,8 +446,12 @@ EXPORTS ;-
 ;+      global:
                 PR_GetVersion;
 ;+} NSPR_4.8;
 ;+NSPR_4.9.2 {
 ;+      global:
 		PR_GetThreadName;
 		PR_SetCurrentThreadName;
 ;+} NSPR_4.8.9;
+;+NSPR_4.10.3 {
+;+      global:
+		PR_SyncMemMap;
+;+} NSPR_4.9.2;
--- a/nsprpub/pr/src/pthreads/ptio.c
+++ b/nsprpub/pr/src/pthreads/ptio.c
@@ -3395,42 +3395,46 @@ failed:
 }  /* PR_AllocFileDesc */
 
 #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
 PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
 #if defined(_PR_INET6_PROBE)
 extern PRBool _pr_ipv6_is_present(void);
 PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
 {
-PRInt32 osfd;
-
 #if defined(DARWIN)
     /*
      * Disable IPv6 if Darwin version is less than 7.0.0 (OS X 10.3).  IPv6 on
      * lesser versions is not ready for general use (see bug 222031).
      */
     {
         struct utsname u;
         if (uname(&u) != 0 || atoi(u.release) < 7)
             return PR_FALSE;
     }
 #endif
 
+#if defined(LINUX)
+    /* If /proc/net/if_inet6 exists, the Linux kernel supports IPv6. */
+    int rv = access("/proc/net/if_inet6", F_OK);
+    return (rv == 0);
+#else
     /*
      * HP-UX only: HP-UX IPv6 Porting Guide (dated February 2001)
      * suggests that we call open("/dev/ip6", O_RDWR) to determine
      * whether IPv6 APIs and the IPv6 stack are on the system.
      * Our portable test below seems to work fine, so I am using it.
      */
-    osfd = socket(AF_INET6, SOCK_STREAM, 0);
+    PRInt32 osfd = socket(AF_INET6, SOCK_STREAM, 0);
     if (osfd != -1) {
         close(osfd);
         return PR_TRUE;
     }
     return PR_FALSE;
+#endif
 }
 #endif	/* _PR_INET6_PROBE */
 #endif
 
 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
 {
     PRIntn osfd;
     PRDescType ftype;
--- a/nsprpub/pr/src/pthreads/ptthread.c
+++ b/nsprpub/pr/src/pthreads/ptthread.c
@@ -975,20 +975,21 @@ void _PR_InitThreads(
      * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998.
      * More info - the problem is that pthreads calls the destructor
      * eagerly as the thread returns from its root, rather than lazily
      * after the thread is joined. Therefore, threads that are joining
      * and holding PRThread references are actually holding pointers to
      * nothing.
      */
     rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);
-    if (0 != rv) PR_Abort();
+    if (0 != rv)
+        PR_Assert("0 == rv", __FILE__, __LINE__);
     pt_book.keyCreated = PR_TRUE;
     rv = pthread_setspecific(pt_book.key, thred);
-    if (0 != rv) PR_Abort();
+    PR_ASSERT(0 == rv);
 }  /* _PR_InitThreads */
 
 #ifdef __GNUC__
 /*
  * GCC supports the constructor and destructor attributes as of
  * version 2.5.
  */
 static void _PR_Fini(void) __attribute__ ((destructor));
@@ -1043,17 +1044,18 @@ void _PR_Fini(void)
     void *thred;
     int rv;
 
     if (!_pr_initialized) {
         /* Either NSPR was never successfully initialized or 
          * PR_Cleanup has been called already. */
         if (pt_book.keyCreated)
         {
-            pthread_key_delete(pt_book.key);
+            rv = pthread_key_delete(pt_book.key);
+            PR_ASSERT(0 == rv);
             pt_book.keyCreated = PR_FALSE;
         }
         return;
     }
 
     _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
     if (NULL != thred)
     {
@@ -1062,16 +1064,17 @@ void _PR_Fini(void)
          * thread private data destructors at final cleanup.
          */
         _pt_thread_death_internal(thred, PR_FALSE);
         rv = pthread_setspecific(pt_book.key, NULL);
         PR_ASSERT(0 == rv);
     }
     rv = pthread_key_delete(pt_book.key);
     PR_ASSERT(0 == rv);
+    pt_book.keyCreated = PR_FALSE;
     /* TODO: free other resources used by NSPR */
     /* _pr_initialized = PR_FALSE; */
 }  /* _PR_Fini */
 
 PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
 {
     PRThread *me = PR_GetCurrentThread();
     int rv;
--- a/nsprpub/pr/src/threads/combined/prulock.c
+++ b/nsprpub/pr/src/threads/combined/prulock.c
@@ -192,25 +192,25 @@ PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
     PRIntn is;
     PRThread *t;
     PRCList *q;
 
     PR_ASSERT(me != suspendAllThread); 
     PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
     PR_ASSERT(lock != NULL);
 #ifdef _PR_GLOBAL_THREADS_ONLY 
-    PR_ASSERT(lock->owner != me);
     _PR_MD_LOCK(&lock->ilock);
+    PR_ASSERT(lock->owner == 0);
     lock->owner = me;
     return;
 #else  /* _PR_GLOBAL_THREADS_ONLY */
 
 	if (_native_threads_only) {
-		PR_ASSERT(lock->owner != me);
 		_PR_MD_LOCK(&lock->ilock);
+		PR_ASSERT(lock->owner == 0);
 		lock->owner = me;
 		return;
 	}
 
     if (!_PR_IS_NATIVE_THREAD(me))
     	_PR_INTSOFF(is);
 
     PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
--- a/nsprpub/pr/src/threads/prrwlock.c
+++ b/nsprpub/pr/src/threads/prrwlock.c
@@ -221,17 +221,18 @@ int err;
 
 	PR_Unlock(rwlock->rw_lock);
 #endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
-	_PR_SET_THREAD_RWLOCK_RANK(rwlock);
+	if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
+		_PR_SET_THREAD_RWLOCK_RANK(rwlock);
 #endif
 }
 
 /*
 ** Write-lock the RWLock.
 */
 PR_IMPLEMENT(void)
 PR_RWLock_Wlock(PRRWLock *rwlock)
@@ -277,17 +278,18 @@ int err;
 #endif
 	PR_Unlock(rwlock->rw_lock);
 #endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
-	_PR_SET_THREAD_RWLOCK_RANK(rwlock);
+	if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
+		_PR_SET_THREAD_RWLOCK_RANK(rwlock);
 #endif
 }
 
 /*
 ** Unlock the RW lock.
 */
 PR_IMPLEMENT(void)
 PR_RWLock_Unlock(PRRWLock *rwlock)
@@ -342,17 +344,18 @@ int err;
 	}
 	PR_Unlock(rwlock->rw_lock);
 #endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
-	_PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
+	if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
+		_PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
 #endif
 	return;
 }
 
 #ifndef _PR_RWLOCK_RANK_ORDER_DEBUG
 
 void _PR_InitRWLocks(void) { }
 
@@ -424,17 +427,18 @@ static void
  *		stack is not allocated, return PR_RWLOCK_RANK_NONE.
  */
 	
 static PRUint32
 _PR_GET_THREAD_RWLOCK_RANK(void)
 {
 	thread_rwlock_stack *lock_stack;
 
-	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL)
+	lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
+	if (lock_stack == NULL || lock_stack->trs_index == 0)
 		return (PR_RWLOCK_RANK_NONE);
 	else
 		return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
 }
 
 /*
  * _PR_UNSET_THREAD_RWLOCK_RANK
  *
@@ -447,30 +451,29 @@ static void
 {
 	thread_rwlock_stack *lock_stack;
 	int new_index = 0, index, done = 0;
 
 	lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
 
 	PR_ASSERT(lock_stack != NULL);
 
-	index = lock_stack->trs_index - 1;
-	while (index-- >= 0) {
-		if ((lock_stack->trs_stack[index] == rwlock) && !done)  {
+	for (index = lock_stack->trs_index - 1; index >= 0; index--) {
+		if (!done && (lock_stack->trs_stack[index] == rwlock))  {
 			/*
 			 * reset the slot for rwlock
 			 */
 			lock_stack->trs_stack[index] = NULL;
 			done = 1;
 		}
 		/*
 		 * search for the lowest-numbered empty slot, above which there are
 		 * no non-empty slots
 		 */
-		if ((lock_stack->trs_stack[index] != NULL) && !new_index)
+		if (!new_index && (lock_stack->trs_stack[index] != NULL))
 			new_index = index + 1;
 		if (done && new_index)
 			break;
 	}
 	/*
 	 * set top of stack to highest numbered empty slot
 	 */
 	lock_stack->trs_index = new_index;
--- a/nsprpub/pr/tests/Makefile.in
+++ b/nsprpub/pr/tests/Makefile.in
@@ -114,16 +114,17 @@ CSRCS =             \
 	provider.c		\
 	prpoll.c		\
 	prpollml.c		\
 	pushtop.c		\
 	ranfile.c       \
 	randseed.c      \
 	reinit.c        \
 	rmdir.c			\
+	rwlockrank.c    \
 	rwlocktest.c    \
 	sel_spd.c  		\
 	selct_er.c	    \
 	selct_nm.c	    \
 	selct_to.c	    \
 	select2.c  		\
 	selintr.c  		\
 	sem.c 	  		\
new file mode 100644
--- /dev/null
+++ b/nsprpub/pr/tests/rwlockrank.c
@@ -0,0 +1,120 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * RWLock rank tests
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+static int _debug_on;
+static PRRWLock *rwlock0;
+static PRRWLock *rwlock1;
+static PRRWLock *rwlock2;
+
+static void rwtest(void *args)
+{
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Unlock(rwlock1);
+
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Unlock(rwlock1);
+
+    // Test correct lock rank.
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Rlock(rwlock2);
+    PR_RWLock_Unlock(rwlock2);
+    PR_RWLock_Unlock(rwlock1);
+
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Rlock(rwlock2);
+    PR_RWLock_Unlock(rwlock1);
+    PR_RWLock_Unlock(rwlock2);
+
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Rlock(rwlock0);
+    PR_RWLock_Rlock(rwlock2);
+    PR_RWLock_Unlock(rwlock2);
+    PR_RWLock_Unlock(rwlock0);
+    PR_RWLock_Unlock(rwlock1);
+
+#if 0
+    // Test incorrect lock rank.
+    PR_RWLock_Rlock(rwlock2);
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Unlock(rwlock1);
+    PR_RWLock_Unlock(rwlock2);
+
+    PR_RWLock_Rlock(rwlock2);
+    PR_RWLock_Rlock(rwlock0);
+    PR_RWLock_Rlock(rwlock1);
+    PR_RWLock_Unlock(rwlock1);
+    PR_RWLock_Unlock(rwlock0);
+    PR_RWLock_Unlock(rwlock2);
+#endif
+}
+
+int main(int argc, char **argv)
+{
+    PRStatus rc;
+    PRThread *thread;
+    PLOptStatus os;
+    PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+
+    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+        if (PL_OPT_BAD == os) continue;
+        switch (opt->option) {
+        case 'd':  /* debug mode */
+            _debug_on = 1;
+            break;
+         default:
+            break;
+        }
+    }
+    PL_DestroyOptState(opt);
+
+    rwlock0 = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "Lock 0");
+    if (rwlock0 == NULL) {
+        fprintf(stderr, "PR_NewRWLock failed - error %d\n",
+                (int)PR_GetError());
+        return 1;
+    }
+    rwlock1 = PR_NewRWLock(1, "Lock 1");
+    if (rwlock1 == NULL) {
+        fprintf(stderr, "PR_NewRWLock failed - error %d\n",
+                (int)PR_GetError());
+        return 1;
+    }
+    rwlock2 = PR_NewRWLock(2, "Lock 2");
+    if (rwlock2 == NULL) {
+        fprintf(stderr, "PR_NewRWLock failed - error %d\n",
+                (int)PR_GetError());
+        return 1;
+    }
+
+    thread = PR_CreateThread(PR_USER_THREAD, rwtest, NULL, PR_PRIORITY_NORMAL,
+                             PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+    if (thread == NULL) {
+        fprintf(stderr, "PR_CreateThread failed - error %d\n",
+                (int)PR_GetError());
+        PR_ProcessExit(2);
+    }
+    if (_debug_on) {
+        printf("%s: created thread = %p\n", argv[0], thread);
+    }
+
+    rc = PR_JoinThread(thread);
+    PR_ASSERT(rc == PR_SUCCESS);
+
+    PR_DestroyRWLock(rwlock0);
+    rwlock0 = NULL;
+    PR_DestroyRWLock(rwlock1);
+    rwlock1 = NULL;
+    PR_DestroyRWLock(rwlock2);
+    rwlock2 = NULL;
+
+    printf("PASS\n");
+    return 0;
+}
--- a/nsprpub/pr/tests/rwlocktest.c
+++ b/nsprpub/pr/tests/rwlocktest.c
@@ -127,17 +127,17 @@ int main(int argc, char **argv)
 						  PR_JOINABLE_THREAD,
 						  0);
 		if (threads[cnt] == NULL) {
 			PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
 								PR_GetError());
 			PR_ProcessExit(2);
 		}
 		if (_debug_on)
-			PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
+			PR_fprintf(output,"%s: created thread = %p\n", argv[0],
 										threads[cnt]);
 	}
 
 	for(cnt = 0; cnt < thread_cnt; cnt++) {
     	rc = PR_JoinThread(threads[cnt]);
 		PR_ASSERT(rc == PR_SUCCESS);
 
 	}