Another update from the internal CVS repository /m/src to mozilla.org.
authorwtc%netscape.com
Tue, 02 Mar 1999 00:58:34 +0000
changeset 483 880ba9a9108a8b86e0290b2fa578cddc4dea8499
parent 482 567e3b47d4940d8662457a05792d4b74058d0c2f
child 484 5e961f4c9e258a8964f8e904f7953a7bb11433b1
push idunknown
push userunknown
push dateunknown
Another update from the internal CVS repository /m/src to mozilla.org.
config/rules.mk
pr/include/MANIFEST
pr/include/nspr.h
pr/include/prerr.h
pr/include/prerror.h
pr/include/prerrorinstall.h
pr/include/prerrorplugin.h
pr/include/private/primpl.h
pr/src/Makefile
pr/src/io/prfile.c
pr/src/misc/compile-et.pl
pr/src/misc/prerr.c
pr/src/misc/prerr.et
pr/src/misc/prerrortable.c
pr/src/misc/prinit.c
pr/src/nspr.rc
pr/src/pthreads/ptthread.c
pr/src/resource.h
pr/src/threads/prrwlock.c
pr/tests/Makefile
pr/tests/errcodes.c
pr/tests/rwlocktest.c
pr/tests/socket.c
pr/tests/testfile.c
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -316,18 +316,22 @@ endif
 	$(RANLIB) $@
 
 ifeq ($(OS_ARCH), WINNT)
 $(RES): $(RESNAME)
 	@$(MAKE_OBJDIR)
 ifeq ($(OS_TARGET),OS2)
 	$(RC) -DOS2 -r $(RESNAME) $(RES)
 else
+ifeq ($(OS_TARGET),WINNT)
+	$(RC) -dWINNT -Fo$(RES) $(RESNAME)
+else
 	$(RC) -Fo$(RES) $(RESNAME)
 endif
+endif
 	@echo $(RES) finished
 endif
 
 $(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp
 	@$(MAKE_OBJDIR)
 ifeq ($(OS_ARCH), WINNT)
 ifndef XP_OS2_EMX
 	$(CCC) -Fo$@ -c $(CCCFLAGS) $<
--- a/pr/include/MANIFEST
+++ b/pr/include/MANIFEST
@@ -8,17 +8,17 @@ prbit.h
 prclist.h
 prcmon.h
 prcountr.h
 prcvar.h
 prdtoa.h
 prenv.h
 prerr.h
 prerror.h
-prerrorplugin.h
+prerrorinstall.h
 prinet.h
 prinit.h
 prinrval.h
 prio.h
 prlink.h
 prlock.h
 prlog.h
 prlong.h
--- a/pr/include/nspr.h
+++ b/pr/include/nspr.h
@@ -22,17 +22,17 @@
 #include "pratom.h"
 #include "prbit.h"
 #include "prclist.h"
 #include "prcmon.h"
 #include "prcvar.h"
 #include "prdtoa.h"
 #include "prenv.h"
 #include "prerror.h"
-#include "prerrorplugin.h"
+#include "prerrorinstall.h"
 #include "prinet.h"
 #include "prinit.h"
 #include "prinrval.h"
 #include "prio.h"
 #include "prlink.h"
 #include "prlock.h"
 #include "prlog.h"
 #include "prlong.h"
--- a/pr/include/prerr.h
+++ b/pr/include/prerr.h
@@ -84,22 +84,22 @@
 #define PR_FILE_EXISTS_ERROR                     (-5943L)
 #define PR_MAX_DIRECTORY_ENTRIES_ERROR           (-5942L)
 #define PR_INVALID_DEVICE_STATE_ERROR            (-5941L)
 #define PR_DEVICE_IS_LOCKED_ERROR                (-5940L)
 #define PR_NO_MORE_FILES_ERROR                   (-5939L)
 #define PR_END_OF_FILE_ERROR                     (-5938L)
 #define PR_FILE_SEEK_ERROR                       (-5937L)
 #define PR_FILE_IS_BUSY_ERROR                    (-5936L)
-#define PR_RESERVED_ERROR                        (-5935L)
+#define PR_RESERVED_ERROR_5935                   (-5935L)
 #define PR_IN_PROGRESS_ERROR                     (-5934L)
 #define PR_ALREADY_INITIATED_ERROR               (-5933L)
 #define PR_GROUP_EMPTY_ERROR                     (-5932L)
 #define PR_INVALID_STATE_ERROR                   (-5931L)
 #define PR_NETWORK_DOWN_ERROR                    (-5930L)
 #define PR_SOCKET_SHUTDOWN_ERROR                 (-5929L)
 #define PR_CONNECT_ABORTED_ERROR                 (-5928L)
 #define PR_HOST_UNREACHABLE_ERROR                (-5927L)
 #define PR_MAX_ERROR                             (-5926L)
-extern void pr_init_error_table_nspr(void);
+extern void nspr_InitializePRErrorTable(void);
 #define ERROR_TABLE_BASE_nspr (-6000L)
 
 #endif /* prerr_h___ */
--- a/pr/include/prerror.h
+++ b/pr/include/prerror.h
@@ -89,86 +89,104 @@ without specific, written prior permissi
 make no representations about the suitability of this software for any
 purpose.  It is provided "as is" without express or implied warranty.
 */
 
 /*
 ** Description:	Localizable error code to string function.
 **
 **
-** NSPR provides a mechanism for converting an error code to a descriptive
-** string, in a caller-specified language.
+** NSPR provides a mechanism for converting an error code to a
+** descriptive string, in a caller-specified language.
 **
-** Error codes themselves are 32 bit (signed) integers.  Typically, the high
-** order 24 bits are an identifier of which error table the error code is
-** from, and the low order 8 bits are a sequential error number within
-** the table.  NSPR supports error tables whose first error code is not
-** a multiple of 256, such error code assignments should be avoided when
-** possible.
+** Error codes themselves are 32 bit (signed) integers.  Typically,
+** the high order 24 bits are an identifier of which error table the
+** error code is from, and the low order 8 bits are a sequential error
+** number within the table.  NSPR supports error tables whose first
+** error code is not a multiple of 256, such error code assignments
+** should be avoided when possible.
 **
 ** Error table 0 is defined to match the UNIX system call error table
 ** (sys_errlist); this allows errno values to be used directly in the
-** library.  Other error table numbers are typically formed by compacting
-** together the first four characters of the error table name.  The mapping
-** between characters in the name and numeric values in the error code are
-** defined in a system-independent fashion, so that two systems that can
-** pass integral values between them can reliably pass error codes without
-** loss of meaning; this should work even if the character sets used are not
-** the same. (However, if this is to be done, error table 0 should be avoided,
-** since the local system call error tables may differ.)
+** library.  Other error table numbers are typically formed by
+** compacting together the first four characters of the error table
+** name.  The mapping between characters in the name and numeric
+** values in the error code are defined in a system-independent
+** fashion, so that two systems that can pass integral values between
+** them can reliably pass error codes without loss of meaning; this
+** should work even if the character sets used are not the
+** same. (However, if this is to be done, error table 0 should be
+** avoided, since the local system call error tables may differ.)
 **
-** Libraries defining error codes need only provide a table mapping error
-** code numbers to names and default English descriptions, calling a routine
-** to make the table ``known'' to NSPR library.  Any error code the library
-** generates can be converted to the corresponding error message.  There is
-** also a default format for error codes accidentally returned before making
-** the table known, which is of the form "unknown code foo 32", where "foo"
-** would be the name of the table.
+** Libraries defining error codes need only provide a table mapping
+** error code numbers to names and default English descriptions,
+** calling a routine to install the table, making it ``known'' to NSPR
+** library.  Once installed, a table may not be removed.  Any error
+** code the library generates can be converted to the corresponding
+** error message.  There is also a default format for error codes
+** accidentally returned before making the table known, which is of
+** the form "unknown code foo 32", where "foo" would be the name of
+** the table.
 **
-** Normally, the error code conversion routine only supports the languages
-** "i-default" and "en", returning the error-table-provided English
-** description for both languages.  The application may provide a
-** localization plugin, allowing support for additional languages.
+** Normally, the error code conversion routine only supports the
+** languages "i-default" and "en", returning the error-table-provided
+** English description for both languages.  The application may
+** provide a localization plugin, allowing support for additional
+** languages.
 **
 **/
 
 /**********************************************************************/
 /************************* TYPES AND CONSTANTS ************************/
 /**********************************************************************/
 
 /*
  * PRLanguageCode --
  *
  *    NSPR represents a language code as a non-negative integer.
  *    Languages 0 is always "i-default" the language you get without
  *    explicit negotiation.  Language 1 is always "en", English
  *    which has been explicitly negotiated.  Additional language
  *    codes are defined by an application-provided localization plugin.
  */
-typedef PRInt32 PRLanguageCode;
+typedef PRUint32 PRLanguageCode;
 #define PR_LANGUAGE_I_DEFAULT 0 /* i-default, the default language */
 #define PR_LANGUAGE_EN 1 /* English, explicitly negotiated */
 
 /**********************************************************************/
 /****************************** FUNCTIONS *****************************/
 /**********************************************************************/
 
 /***********************************************************************
-** FUNCTION:    PR_ErrorTableToString
+** FUNCTION:    PR_ErrorToString
 ** DESCRIPTION:
 **  Returns the UTF-8 message for an error code in
 **  the requested language.  May return the message
 **  in the default language if a translation in the requested
 **  language is not available.  The returned string is
 **  valid for the duration of the process.  Never returns NULL.
 **
 ***********************************************************************/
 PR_EXTERN(const char *) PR_ErrorToString(PRErrorCode code,
     PRLanguageCode language);
 
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorToName
+** DESCRIPTION:
+**  Returns the macro name for an error code, or NULL
+**  if the error code is not known.  The returned string is
+**  valid for the duration of the process.
+**
+**  Does not work for error table 0, the system error codes.
+**
+***********************************************************************/
+PR_EXTERN(const char *) PR_ErrorToName(PRErrorCode code);
+
+
 /***********************************************************************
 ** FUNCTION:    PR_ErrorLanguages
 ** DESCRIPTION:
 **  Returns the RFC 1766 language tags for the language
 **  codes PR_ErrorToString() supports.  The returned array is valid
 **  for the duration of the process.  Never returns NULL.  The first
 **  item in the returned array is the language tag for PRLanguageCode 0,
 **  the second is for PRLanguageCode 1, and so on.  The array is terminated
new file mode 100644
--- /dev/null
+++ b/pr/include/prerrorinstall.h
@@ -0,0 +1,134 @@
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
+#ifndef prerrorinstall_h___
+#define prerrorinstall_h___
+
+#include "prerror.h"
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+/*
+ * struct PRErrorMessage --
+ *
+ *    An error message in an error table.
+ */
+struct PRErrorMessage {
+    const char * name;    /* Macro name for error */
+    const char * en_text; /* Default English text */
+};
+
+/*
+ * struct PRErrorTable --
+ *
+ *    An error table, provided by a library.
+ */
+struct PRErrorTable {
+    const struct PRErrorMessage * msgs; /* Array of error information */
+
+    const char *name; /* Name of error table source */
+    PRErrorCode base; /* Error code for first error in table */
+    int n_msgs; /* Number of codes in table */
+};
+
+/*
+ * struct PRErrorCallbackPrivate --
+ *
+ *    A private structure for the localization plugin 
+ */
+struct PRErrorCallbackPrivate;
+
+/*
+ * struct PRErrorCallbackTablePrivate --
+ *
+ *    A data structure under which the localization plugin may store information,
+ *    associated with an error table, that is private to itself.
+ */
+struct PRErrorCallbackTablePrivate;
+
+/*
+ * PRErrorCallbackLookupFn --
+ *
+ *    A function of PRErrorCallbackLookupFn type is a localization
+ *    plugin callback which converts an error code into a description
+ *    in the requested language.  The callback is provided the
+ *    appropriate error table, private data for the plugin and the table.
+ *    The callback returns the appropriate UTF-8 encoded description, or NULL
+ *    if no description can be found.
+ */
+typedef const char *
+PRErrorCallbackLookupFn(PRErrorCode code, PRLanguageCode language, 
+		   const struct PRErrorTable *table,
+		   struct PRErrorCallbackPrivate *cb_private,
+		   struct PRErrorCallbackTablePrivate *table_private);
+
+/*
+ * PRErrorCallbackNewtableFn --
+ *
+ *    A function PRErrorCallbackNewtableFn type is a localization plugin
+ *    callback which is called once with each error table registered
+ *    with NSPR.  The callback is provided with the error table and
+ *    the plugin's private structure.  The callback returns any table private
+ *    data it wishes to associate with the error table.  Does not need to be thread
+ *    safe.
+ */
+typedef struct PRErrorCallbackTablePrivate *
+PRErrorCallbackNewtableFn(const struct PRErrorTable *table,
+			struct PRErrorCallbackPrivate *cb_private);
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorInstallTable
+** DESCRIPTION:
+**  Registers an error table with NSPR.  Must be done exactly once per
+**  table.  Memory pointed to by `table' must remain valid for the life
+**  of the process.
+**
+**  NOT THREAD SAFE!
+**  
+***********************************************************************/
+PR_EXTERN(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table);
+
+
+/***********************************************************************
+** FUNCTION:    PR_ErrorInstallCallback
+** DESCRIPTION:
+**  Registers an error localization plugin with NSPR.  May be called
+**  at most one time.  `languages' contains the language codes supported
+**  by this plugin.  Languages 0 and 1 must be "i-default" and "en"
+**  respectively.  `lookup' and `newtable' contain pointers to
+**  the plugin callback functions.  `cb_private' contains any information
+**  private to the plugin functions.
+**
+**  NOT THREAD SAFE!
+**
+***********************************************************************/
+PR_EXTERN(void) PR_ErrorInstallCallback(const char * const * languages,
+			      PRErrorCallbackLookupFn *lookup, 
+			      PRErrorCallbackNewtableFn *newtable,
+			      struct PRErrorCallbackPrivate *cb_private);
+
+PR_END_EXTERN_C
+
+#endif /* prerrorinstall_h___ */
deleted file mode 100644
--- a/pr/include/prerrorplugin.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL.  You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- * 
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- * 
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation.  Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
- * Reserved.
- */
-
-#ifndef prerrorplugin_h___
-#define prerrorplugin_h___
-
-#include "prerror.h"
-
-PR_BEGIN_EXTERN_C
-
-/**********************************************************************/
-/************************* TYPES AND CONSTANTS ************************/
-/**********************************************************************/
-
-/*
- * struct PRErrorTable --
- *
- *    An error table, provided by a library.
- */
-struct PRErrorTable {
-    struct PRErrorMessage {
-	const char * const name;    /* Macro name for error */
-	const char * const en_text; /* default english text */
-    } const * msgs; /* Array of error information */
-
-    const char *name; /* Name of error table source */
-    PRErrorCode base; /* Error code for first error in table */
-    int n_msgs; /* Number of codes in table */
-};
-
-/*
- * struct PRErrorPluginRock --
- *
- *    A rock, under which the localization plugin may store information
- *    that is private to itself.
- */
-struct PRErrorPluginRock;
-
-/*
- * struct PRErrorPluginTableRock --
- *
- *    A rock, under which the localization plugin may store information,
- *    associated with an error table, that is private to itself.
- */
-struct PRErrorPluginTableRock;
-
-/*
- * PRErrorPluginLookupFn --
- *
- *    A function of PRErrorPluginLookupFn type is a localization
- *    plugin callback which converts an error code into a description
- *    in the requested language.  The callback is provided the
- *    appropriate error table, rock, and table rock.  The callback
- *    returns the appropriate UTF-8 encoded description, or NULL if no
- *    description can be found.
- */
-typedef const char *
-PRErrorPluginLookupFn(PRErrorCode code, PRLanguageCode language, 
-		   const struct PRErrorTable *table,
-		   struct PRErrorPluginRock *rock,
-		   struct PRErrorPluginTableRock *table_rock);
-
-/*
- * PRErrorPluginNewtableFn --
- *
- *    A function PRErrorPluginNewtableFn type is a localization plugin
- *    callback which is called once with each error table registered
- *    with NSPR.  The callback is provided with the error table and
- *    the plugin rock.  The callback returns any table rock it wishes
- *    to associate with the error table.  Does not need to be thread
- *    safe.
- */
-typedef struct PRErrorPluginTableRock *
-PRErrorPluginNewtableFn(const struct PRErrorTable *table,
-			struct PRErrorPluginRock *rock);
-
-/**********************************************************************/
-/****************************** FUNCTIONS *****************************/
-/**********************************************************************/
-
-/***********************************************************************
-** FUNCTION:    PR_ErrorInstallTable
-** DESCRIPTION:
-**  Registers an error table with NSPR.  Must be done exactly once per
-**  table.
-**  NOT THREAD SAFE!
-**  
-***********************************************************************/
-PR_EXTERN(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table);
-
-
-/***********************************************************************
-** FUNCTION:    PR_ErrorInstallPlugin
-** DESCRIPTION:
-**  Registers an error localization plugin with NSPR.  May be called
-**  at most one time.  `languages' contains the language codes supported
-**  by this plugin.  Languages 0 and 1 must be "i-default" and "en"
-**  respectively.  `lookup' and `newtable' contain pointers to
-**  the plugin callback functions.  `rock' contains any information
-**  private to the plugin functions.
-**  NOT THREAD SAFE!
-***********************************************************************/
-PR_EXTERN(void) PR_ErrorInstallPlugin(const char * const * languages,
-			      PRErrorPluginLookupFn *lookup, 
-			      PRErrorPluginNewtableFn *newtable,
-			      struct PRErrorPluginRock *rock);
-
-PR_END_EXTERN_C
-
-#endif /* prerrorplugin_h___ */
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -1477,16 +1477,17 @@ extern void _PR_InitIO(void);
 extern void _PR_InitLog(void);
 extern void _PR_InitNet(void);
 extern void _PR_InitClock(void);
 extern void _PR_InitLinker(void);
 extern void _PR_InitAtomic(void);
 extern void _PR_InitCPUs(void);
 extern void _PR_InitDtoa(void);
 extern void _PR_InitMW(void);
+extern void _PR_InitRWLocks(void);
 extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me);
 extern void _PR_CleanupThread(PRThread *thread);
 extern void _PR_CleanupTPD(void);
 extern void _PR_Cleanup(void);
 extern void _PR_LogCleanup(void);
 extern void _PR_InitLayerCache(void);
 
 extern PRBool _pr_initialized;
--- a/pr/src/Makefile
+++ b/pr/src/Makefile
@@ -366,17 +366,17 @@ endif
 	@if test ! -z "$(SH_NOW)"; then \
 	    $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
 	else \
 	    true; \
 	fi
 	@$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
 
 
-$(OBJDIR)/prvrsion.$(OBJ_SUFFIX): $(TINC)
+$(OBJDIR)/prvrsion.$(OBJ_SUFFIX): prvrsion.c $(TINC)
 ifeq ($(OS_ARCH), WINNT)
 ifdef XP_OS2_EMX
 	$(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) prvrsion.c
 else
 	$(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) prvrsion.c
 endif
 else
 	$(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) prvrsion.c
--- a/pr/src/io/prfile.c
+++ b/pr/src/io/prfile.c
@@ -458,47 +458,65 @@ PR_IMPLEMENT(PRInt32) PR_Stat(const char
 	return rv;
 }
 
 #endif /* !defined(WIN16)  */
 #endif /* ! NO_NSPR_10_SUPPORT */
 
 PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
 {
-    PRStatus rv = PR_SUCCESS;
+    PRStatus status = PR_SUCCESS;
+
+#ifdef WINNT
+    if (!fd->secret->md.io_model_committed) {
+        PRInt32 rv;
+        rv = _md_Associate((HANDLE)fd->secret->md.osfd);
+        PR_ASSERT(0 != rv);
+        fd->secret->md.io_model_committed = PR_TRUE;
+    }
+#endif
 
     PR_Lock(_pr_flock_lock);
     if (fd->secret->lockCount == 0) {
-        rv = _PR_MD_LOCKFILE(fd->secret->md.osfd);
-        if (rv == PR_SUCCESS)
+        status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
+        if (status == PR_SUCCESS)
             fd->secret->lockCount = 1;
     } else {
         fd->secret->lockCount++;
     }
     PR_Unlock(_pr_flock_lock);
  
-    return rv;
+    return status;
 }
 
 PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
 {
-    PRStatus rv = PR_SUCCESS;
+    PRStatus status = PR_SUCCESS;
+
+#ifdef WINNT
+    if (!fd->secret->md.io_model_committed) {
+        PRInt32 rv;
+        rv = _md_Associate((HANDLE)fd->secret->md.osfd);
+        PR_ASSERT(0 != rv);
+        fd->secret->md.io_model_committed = PR_TRUE;
+    }
+#endif
 
     PR_Lock(_pr_flock_lock);
     if (fd->secret->lockCount == 0) {
-        rv = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
-        PR_ASSERT(rv == PR_SUCCESS || fd->secret->lockCount == 0);
-        if (rv == PR_SUCCESS)
+        status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
+        PR_ASSERT(status == PR_SUCCESS || fd->secret->lockCount == 0);
+        if (status == PR_SUCCESS)
             fd->secret->lockCount = 1;
     } else {
         fd->secret->lockCount++;
     }
     PR_Unlock(_pr_flock_lock);
 
-    return rv;
+    return status;
 }
 
 PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
 {
     PRStatus rv = PR_SUCCESS;
 
     PR_Lock(_pr_flock_lock);
     if (fd->secret->lockCount == 1) {
--- a/pr/src/misc/compile-et.pl
+++ b/pr/src/misc/compile-et.pl
@@ -95,21 +95,21 @@ while ($_ = <INPUT>) {
     elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*"(.*)"[ \t]*$/) {
 	&code($2, $3);
     }
     elsif ($skipone && /^[ \t]*"(.*)"[ \t]*$/) {
 	&code($macro, $1);
     }
 }
 
-print H "extern void pr_init_error_table_", $table_name, "(void);\n";
+print H "extern void ", $table_name, "_InitializePRErrorTable","(void);\n";
 printf H "#define ERROR_TABLE_BASE_%s (%dL)\n", $table_name, $table_base;
 
 print C "\t{0, 0}\n";
 print C "};\n\n";
 printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n",
     $base, $table_base, $table_item_count;
 print C "\n";
-print C "void pr_init_error_table_", $table_name, "() {\n";
+print C "void ", $table_name, "_InitializePRErrorTable", "() {\n";
 print C "    PR_ErrorInstallTable(&et);\n";
 print C "}\n";
 
 0;
--- a/pr/src/misc/prerr.c
+++ b/pr/src/misc/prerr.c
@@ -1,14 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
 /*
  *
  * prerr.c
  * This file is automatically generated; please do not edit it.
  */
-#include "prerrorplugin.h"
+#include "prerrorinstall.h"
 static const struct PRErrorMessage text[] = {
 	{"PR_OUT_OF_MEMORY_ERROR",    "Memory allocation attempt failed"},
 	{"PR_BAD_DESCRIPTOR_ERROR",    "Invalid file descriptor"},
 	{"PR_WOULD_BLOCK_ERROR",    "The operation would have blocked"},
 	{"PR_ACCESS_FAULT_ERROR",    "Invalid memory address argument"},
 	{"PR_INVALID_METHOD_ERROR",    "Invalid function for file type"},
 	{"PR_ILLEGAL_ACCESS_ERROR",    "Invalid memory address argument"},
 	{"PR_UNKNOWN_ERROR",    "Some unknown error has occurred"},
@@ -65,26 +83,26 @@ static const struct PRErrorMessage text[
 	{"PR_FILE_EXISTS_ERROR",    "Cannot create or rename a filename that already exists"},
 	{"PR_MAX_DIRECTORY_ENTRIES_ERROR",    "Directory is full.  No additional filenames may be added"},
 	{"PR_INVALID_DEVICE_STATE_ERROR",    "The required device was in an invalid state"},
 	{"PR_DEVICE_IS_LOCKED_ERROR",    "The device is locked"},
 	{"PR_NO_MORE_FILES_ERROR",    "No more entries in the directory"},
 	{"PR_END_OF_FILE_ERROR",    "Encountered end of file"},
 	{"PR_FILE_SEEK_ERROR",    "Seek error"},
 	{"PR_FILE_IS_BUSY_ERROR",    "The file is busy"},
-	{"PR_RESERVED_ERROR",    "Reserved Error Code"},
+	{"PR_RESERVED_ERROR_5935",    "Reserved Error Code -5935"},
 	{"PR_IN_PROGRESS_ERROR",    "Operation is still in progress (probably a non-blocking connect)"},
 	{"PR_ALREADY_INITIATED_ERROR",    "Operation has already been initiated (probably a non-blocking connect)"},
 	{"PR_GROUP_EMPTY_ERROR",    "The wait group is empty"},
 	{"PR_INVALID_STATE_ERROR",    "Object state improper for request"},
 	{"PR_NETWORK_DOWN_ERROR",    "Network is down"},
 	{"PR_SOCKET_SHUTDOWN_ERROR",    "Socket shutdown"},
 	{"PR_CONNECT_ABORTED_ERROR",    "Connection aborted"},
 	{"PR_HOST_UNREACHABLE_ERROR",    "Host is unreachable"},
 	{"PR_MAX_ERROR",    "Placeholder for the end of the list"},
 	{0, 0}
 };
 
 static const struct PRErrorTable et = { text, "prerr", -6000L, 75 };
 
-void pr_init_error_table_nspr() {
+void nspr_InitializePRErrorTable() {
     PR_ErrorInstallTable(&et);
 }
--- a/pr/src/misc/prerr.et
+++ b/pr/src/misc/prerr.et
@@ -94,17 +94,17 @@ ec PR_MAX_DIRECTORY_ENTRIES_ERROR,
 "Directory is full.  No additional filenames may be added"
 ec PR_INVALID_DEVICE_STATE_ERROR,
 "The required device was in an invalid state"
 ec PR_DEVICE_IS_LOCKED_ERROR, "The device is locked"
 ec PR_NO_MORE_FILES_ERROR,      "No more entries in the directory"
 ec PR_END_OF_FILE_ERROR,        "Encountered end of file"
 ec PR_FILE_SEEK_ERROR,  "Seek error"
 ec PR_FILE_IS_BUSY_ERROR,       "The file is busy"
-ec PR_RESERVED_ERROR,       "Reserved Error Code"
+ec PR_RESERVED_ERROR_5935,       "Reserved Error Code -5935"
 ec PR_IN_PROGRESS_ERROR,
 "Operation is still in progress (probably a non-blocking connect)"
 ec PR_ALREADY_INITIATED_ERROR,
 "Operation has already been initiated (probably a non-blocking connect)"
 ec PR_GROUP_EMPTY_ERROR,        "The wait group is empty"
 ec PR_INVALID_STATE_ERROR,      "Object state improper for request"
 ec PR_NETWORK_DOWN_ERROR,       "Network is down"
 ec PR_SOCKET_SHUTDOWN_ERROR,    "Socket shutdown"
--- a/pr/src/misc/prerrortable.c
+++ b/pr/src/misc/prerrortable.c
@@ -36,42 +36,42 @@ provided "as is" without express or impl
 #include <string.h>
 #ifdef SUNOS4
 #include "md/sunos4.h"  /* for strerror */
 #endif
 #include <assert.h>
 #include <errno.h>
 #include "prmem.h"
 #include "prerror.h"
-#include "prerrorplugin.h"
+#include "prerrorinstall.h"
 
 #define	ERRCODE_RANGE	8	/* # of bits to shift table number */
 #define	BITS_PER_CHAR	6	/* # bits to shift per character in name */
 
 #ifdef NEED_SYS_ERRLIST
 extern char const * const sys_errlist[];
 extern const int sys_nerr;
 #endif
 
 /* List of error tables */
 struct PRErrorTableList {
     struct PRErrorTableList *next;
     const struct PRErrorTable *table;
-    struct PRErrorPluginTableRock *table_rock;
+    struct PRErrorCallbackTablePrivate *table_private;
 };
 static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL;
 
 /* Supported languages */
 static const char * default_languages[] = { "i-default", "en", 0 };
-static const char * const * plugin_languages = default_languages;
+static const char * const * callback_languages = default_languages;
 
-/* Plugin info */
-static struct PRErrorPluginRock *plugin_rock = 0;
-static PRErrorPluginLookupFn *plugin_lookup = 0;
-static PRErrorPluginNewtableFn *plugin_newtable = 0;
+/* Callback info */
+static struct PRErrorCallbackPrivate *callback_private = 0;
+static PRErrorCallbackLookupFn *callback_lookup = 0;
+static PRErrorCallbackNewtableFn *callback_newtable = 0;
 
 
 static const char char_set[] =
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
 
 static const char *
 error_table_name (PRErrorCode num)
 {
@@ -91,18 +91,16 @@ error_table_name (PRErrorCode num)
 	ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
 	if (ch != 0)
 	    *p++ = char_set[ch-1];
     }
     *p = '\0';
     return(buf);
 }
 
-
-
 PR_IMPLEMENT(const char *)
 PR_ErrorToString(PRErrorCode code, PRLanguageCode language)
 {
     /* static buffer only used if code is using inconsistent error message
      * numbers, so just ignore the possible thread contention
      */
     static char buffer[25];
 
@@ -112,19 +110,19 @@ PR_ErrorToString(PRErrorCode code, PRLan
     struct PRErrorTableList *et;
     int started = 0;
     char *cp;
 
     for (et = Table_List; et; et = et->next) {
 	if (et->table->base <= code &&
 	    et->table->base + et->table->n_msgs > code) {
 	    /* This is the right table */
-	    if (plugin_lookup) {
-		msg = plugin_lookup(code, language, et->table,
-		    plugin_rock, et->table_rock);
+	    if (callback_lookup) {
+		msg = callback_lookup(code, language, et->table,
+		    callback_private, et->table_private);
 		if (msg) return msg;
 	    }
     
 	    return(et->table->msgs[code - et->table->base].en_text);
 	}
     }
 
     if (code >= 0 && code < 256) {
@@ -149,56 +147,72 @@ PR_ErrorToString(PRErrorCode code, PRLan
 	*cp++ = (char)('0' + offset / 10);
 	offset %= 10;
     }
     *cp++ = (char)('0' + offset);
     *cp = '\0';
     return(buffer);
 }
 
+PR_IMPLEMENT(const char *)
+PR_ErrorToName(PRErrorCode code)
+{
+    struct PRErrorTableList *et;
+
+    for (et = Table_List; et; et = et->next) {
+	if (et->table->base <= code &&
+	    et->table->base + et->table->n_msgs > code) {
+	    /* This is the right table */
+	    return(et->table->msgs[code - et->table->base].name);
+	}
+    }
+
+    return 0;
+}
+
 PR_IMPLEMENT(const char * const *)
 PR_ErrorLanguages(void)
 {
-    return plugin_languages;
+    return callback_languages;
 }
 
 PR_IMPLEMENT(PRErrorCode)
 PR_ErrorInstallTable(const struct PRErrorTable *table)
 {
     struct PRErrorTableList * new_et;
 
     new_et = (struct PRErrorTableList *)
 					PR_Malloc(sizeof(struct PRErrorTableList));
     if (!new_et)
 	return errno;	/* oops */
     new_et->table = table;
-    if (plugin_newtable) {
-	new_et->table_rock = plugin_newtable(table, plugin_rock);
+    if (callback_newtable) {
+	new_et->table_private = callback_newtable(table, callback_private);
     } else {
-	new_et->table_rock = 0;
+	new_et->table_private = 0;
     }
     new_et->next = Table_List;
     Table_List = new_et;
     return 0;
 }
 
 PR_IMPLEMENT(void)
-PR_ErrorInstallPlugin(const char * const * languages,
-		       PRErrorPluginLookupFn *lookup, 
-		       PRErrorPluginNewtableFn *newtable,
-		       struct PRErrorPluginRock *rock)
+PR_ErrorInstallCallback(const char * const * languages,
+		       PRErrorCallbackLookupFn *lookup, 
+		       PRErrorCallbackNewtableFn *newtable,
+		       struct PRErrorCallbackPrivate *cb_private)
 {
     struct PRErrorTableList *et;
 
     assert(strcmp(languages[0], "i-default") == 0);
     assert(strcmp(languages[1], "en") == 0);
     
-    plugin_languages = languages;
-    plugin_lookup = lookup;
-    plugin_newtable = newtable;
-    plugin_rock = rock;
+    callback_languages = languages;
+    callback_lookup = lookup;
+    callback_newtable = newtable;
+    callback_private = cb_private;
 
-    if (plugin_newtable) {
+    if (callback_newtable) {
 	for (et = Table_List; et; et = et->next) {
-	    et->table_rock = plugin_newtable(et->table, plugin_rock);
+	    et->table_private = callback_newtable(et->table, callback_private);
 	}
     }
 }
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -12,16 +12,17 @@
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 #include "primpl.h"
+#include <ctype.h>
 #include <string.h>
 
 PRLogModuleInfo *_pr_clock_lm;
 PRLogModuleInfo *_pr_cmon_lm;
 PRLogModuleInfo *_pr_io_lm;
 PRLogModuleInfo *_pr_cvar_lm;
 PRLogModuleInfo *_pr_mon_lm;
 PRLogModuleInfo *_pr_linker_lm;
@@ -68,21 +69,55 @@ PRLock *_pr_sleeplock;  /* used in PR_Sl
 static void _PR_InitCallOnce(void);
 
 PRBool _pr_initialized = PR_FALSE;
 
 
 PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
 {
     /*
-    ** This is the secret handshake algorithm. Right now it requires
-    ** an exact match. Later it should get more clever.
+    ** This is the secret handshake algorithm.
+    **
+    ** This release (3.1) is backward compatible with
+    ** all the previous releases ("2.1 19980529", "3.0",
+    ** "3.0.x").  It is not compatible with future
+    ** releases or patches.  So this release has a
+    ** simple version compatibility check algorithm.
     */
-    if (!_pr_initialized) _PR_ImplicitInitialization();
-    return ((0 == strcmp(importedVersion, PR_VERSION)) ? PR_TRUE : PR_FALSE);
+    int vmajor = 0, vminor = 0, vpatch = 0;
+    const char *ptr = importedVersion;
+
+    while (isdigit(*ptr)) {
+        vmajor = 10 * vmajor + *ptr - '0';
+        ptr++;
+    }
+    if (*ptr == '.') {
+        ptr++;
+        while (isdigit(*ptr)) {
+            vminor = 10 * vminor + *ptr - '0';
+            ptr++;
+        }
+        if (*ptr == '.') {
+            ptr++;
+            while (isdigit(*ptr)) {
+                vpatch = 10 * vpatch + *ptr - '0';
+                ptr++;
+            }
+        }
+    }
+
+    if (vmajor > PR_VMAJOR) {
+        return PR_FALSE;
+    } else if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
+        return PR_FALSE;
+    } else if (vminor == PR_VMINOR && vpatch > PR_VPATCH) {
+        return PR_FALSE;
+    } else {
+        return PR_TRUE;
+    }
 }  /* PR_VersionCheck */
 
 
 PR_IMPLEMENT(PRBool) PR_Initialized(void)
 {
     return _pr_initialized;
 }
 
@@ -144,18 +179,19 @@ static void _PR_InitStuff(void)
     _PR_InitNet();
 #ifdef PR_LOGGING
     _PR_InitLog();
 #endif
     _PR_InitLinker();
     _PR_InitCallOnce();
     _PR_InitDtoa();
     _PR_InitMW();
+    _PR_InitRWLocks();
 
-    pr_init_error_table_nspr();
+    nspr_InitializePRErrorTable();
 
     _PR_MD_FINAL_INIT();
 }
 
 void _PR_ImplicitInitialization()
 {
 	_PR_InitStuff();
 
@@ -604,17 +640,16 @@ PR_IMPLEMENT(PRFileDesc *) PR_GetInherit
             ptr++;
         }
         if (*ptr == '\0') {
             PR_SetError(PR_UNKNOWN_ERROR, 0);
             return NULL;
         }
         ptr++;
     }
-    return NULL;
 }
 
 PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
     const char *path,
     char *const *argv,
     char *const *envp,
     const PRProcessAttr *attr)
 {
--- a/pr/src/nspr.rc
+++ b/pr/src/nspr.rc
@@ -11,45 +11,121 @@
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef WIN16
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 #pragma code_page(1252)
+#endif //_WIN32
 
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
+ FILEVERSION 3,2,0,0
  PRODUCTVERSION 3,1,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
 #else
  FILEFLAGS 0x0L
 #endif
  FILEOS 0x40004L
  FILETYPE 0x1L
  FILESUBTYPE 0x0L
 
+// end win16
+#endif
+
 BEGIN
     BLOCK "StringFileInfo"
     BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Netscape Communications Corporation\0"
             VALUE "FileDescription", "Netscape Portable Run Time\0"
-            VALUE "FileVersion", "1, 0, 0, 1\0"
-            VALUE "InternalName", "libnspr21\0"
+            VALUE "FileVersion", "3, 1, 0, 0\0"
+#ifdef WINNT
+            VALUE "InternalName", "libnspr3\0"
+            VALUE "OriginalFilename", "libnspr3.dll\0"
+#else
+            VALUE "InternalName", "nspr3\0"
+            VALUE "OriginalFilename", "nspr3.dll\0"
+#endif
             VALUE "LegalCopyright", "Copyright  1996\0"
-            VALUE "OriginalFilename", "libnspr21.dll\0"
             VALUE "ProductName", "Netscape Communication Corporation NSPR20\0"
             VALUE "ProductVersion", "3, 1, 0, 0\0"
         END
     END
     BLOCK "VarFileInfo"
     BEGIN
         VALUE "Translation", 0x409, 1200
     END
 END
 
+#endif    // !_MAC
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -304,20 +304,45 @@ static PRThread* _PR_CreateThread(
     {
         pthread_t id;
 
         thred->arg = arg;
         thred->startFunc = start;
         thred->priority = priority;
         if (PR_UNJOINABLE_THREAD == state)
             thred->state |= PT_THREAD_DETACHED;
+
+        if (PR_LOCAL_THREAD == scope)
+        	scope = PR_GLOBAL_THREAD;
+			
+        if (PR_GLOBAL_BOUND_THREAD == scope) {
+			/*
+			 * should a Posix feature test be used here?
+			 */
+#ifdef PTHREAD_SCOPE_SYSTEM
+    		rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+			if (rv) {
+				/*
+				 * system scope not supported
+				 */
+        		scope = PR_GLOBAL_THREAD;
+				/*
+				 * reset scope
+				 */
+    			rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
+    			PR_ASSERT(0 == rv);
+			}
+#endif
+		}
         if (PR_GLOBAL_THREAD == scope)
             thred->state |= PT_THREAD_GLOBAL;
-        if (PR_GLOBAL_BOUND_THREAD == scope)
+        else if (PR_GLOBAL_BOUND_THREAD == scope)
             thred->state |= (PT_THREAD_GLOBAL | PT_THREAD_BOUND);
+		else	/* force it global */
+            thred->state |= PT_THREAD_GLOBAL;
         if (PR_SYSTEM_THREAD == type)
             thred->state |= PT_THREAD_SYSTEM;
 
         thred->suspend =(isGCAble) ? PT_THREAD_SETGCABLE : 0;
 
         thred->stack = PR_NEWZAP(PRThreadStack);
         if (thred->stack == NULL) {
             PRIntn oserr = errno;
@@ -336,43 +361,47 @@ static PRThread* _PR_CreateThread(
 
         /* make the thread counted to the rest of the runtime */
         PR_Lock(pt_book.ml);
         if (PR_SYSTEM_THREAD == type)
             pt_book.system += 1;
         else pt_book.user += 1;
         PR_Unlock(pt_book.ml);
 
-        if (thred->state & PT_THREAD_BOUND) {
-			/*
-			 * should a Posix feature test be used here?
-			 */
-#ifdef PTHREAD_SCOPE_SYSTEM
-    		rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
-#endif
-		}
         /*
          * We pass a pointer to a local copy (instead of thred->id)
          * to pthread_create() because who knows what wacky things
          * pthread_create() may be doing to its argument.
          */
         rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
 
 #if !defined(_PR_DCETHREADS)
         if (EPERM == rv)
         {
+#if defined(IRIX)
+        	if (PR_GLOBAL_BOUND_THREAD == scope) {
+				/*
+				 * SCOPE_SYSTEM requires appropriate privilege
+				 * reset to process scope and try again
+				 */
+    			rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
+    			PR_ASSERT(0 == rv);
+            	thred->state &= ~PT_THREAD_BOUND;
+			}
+#else
             /* Remember that we don't have thread scheduling privilege. */
             pt_schedpriv = EPERM;
             PR_LOG(_pr_thread_lm, PR_LOG_MIN,
                 ("_PR_CreateThread: no thread scheduling privilege"));
             /* Try creating the thread again without setting priority. */
 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
             rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
             PR_ASSERT(0 == rv);
 #endif
+#endif	/* IRIX */
             rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
         }
 #endif
 
         if (0 != rv)
         {
 #if defined(_PR_DCETHREADS)
             PRIntn oserr = errno;
--- a/pr/src/resource.h
+++ b/pr/src/resource.h
@@ -11,11 +11,23 @@
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
-#if 0
-There are no resources for NSPR.
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by nspr.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
 #endif
+#endif
--- a/pr/src/threads/prrwlock.c
+++ b/pr/src/threads/prrwlock.c
@@ -11,47 +11,78 @@
  * NPL.
  * 
  * The Initial Developer of this code under the NPL is Netscape
  * Communications Corporation.  Portions created by Netscape are
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
-#include "nspr.h"
+#include "primpl.h"
 
 #include <string.h>
 
+#if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+
+#include <pthread.h>
+#define HAVE_UNIX98_RWLOCK
+#define RWLOCK_T pthread_rwlock_t
+#define RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
+#define RWLOCK_DESTROY(lock) pthread_rwlock_destroy(lock)
+#define RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
+#define RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
+#define RWLOCK_UNLOCK(lock) pthread_rwlock_unlock(lock)
+
+#elif defined(SOLARIS) && (defined(_PR_PTHREADS) \
+        || defined(_PR_GLOBAL_THREADS_ONLY))
+
+#include <synch.h>
+#define HAVE_UI_RWLOCK
+#define RWLOCK_T rwlock_t
+#define RWLOCK_INIT(lock) rwlock_init(lock, USYNC_THREAD, NULL)
+#define RWLOCK_DESTROY(lock) rwlock_destroy(lock)
+#define RWLOCK_RDLOCK(lock) rw_rdlock(lock)
+#define RWLOCK_WRLOCK(lock) rw_wrlock(lock)
+#define RWLOCK_UNLOCK(lock) rw_unlock(lock)
+
+#endif
+
 /*
  * Reader-writer lock
  */
 struct PRRWLock {
-    PRLock			*rw_lock;
 	char			*rw_name;			/* lock name					*/
 	PRUint32		rw_rank;			/* rank of the lock				*/
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	RWLOCK_T		rw_lock;
+#else
+    PRLock			*rw_lock;
 	PRInt32			rw_lock_cnt;		/* ==  0, if unlocked			*/
 										/* == -1, if write-locked		*/
 										/* > 0	, # of read locks		*/
 	PRUint32		rw_reader_cnt;		/* number of waiting readers	*/
 	PRUint32		rw_writer_cnt;		/* number of waiting writers	*/
 	PRCondVar   	*rw_reader_waitq;	/* cvar for readers 			*/
 	PRCondVar   	*rw_writer_waitq;	/* cvar for writers				*/
+#ifdef DEBUG
     PRThread 		*rw_owner;			/* lock owner for write-lock	*/
+#endif
+#endif
 };
 
 #ifdef DEBUG
 #define _PR_RWLOCK_RANK_ORDER_DEBUG	/* enable deadlock detection using
 									   rank-order for locks
 									*/
 #endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 
-static PRUintn	pr_thread_rwlock_initialized;
-static PRUintn	pr_thread_rwlock;				/* TPD key for lock stack */
+static PRUintn	pr_thread_rwlock_key;			/* TPD key for lock stack */
 static PRUintn	pr_thread_rwlock_alloc_failed;
 
 #define	_PR_RWLOCK_RANK_ORDER_LIMIT	10
 
 typedef struct thread_rwlock_stack {
 	PRInt32		trs_index;									/* top of stack */
 	PRRWLock	*trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT];	/* stack of lock
 														 	   pointers */
@@ -74,170 +105,226 @@ static void _PR_RELEASE_LOCK_STACK(void 
  *		Create a reader-writer lock, with the given lock rank and lock name
  *	
  */
 
 PR_IMPLEMENT(PRRWLock *)
 PR_NewRWLock(PRUint32 lock_rank, const char *lock_name)
 {
     PRRWLock *rwlock;
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	int err;
+#endif
+
+    if (!_pr_initialized) _PR_ImplicitInitialization();
 
     rwlock = PR_NEWZAP(PRRWLock);
     if (rwlock == NULL)
 		return NULL;
-	
-	rwlock->rw_lock = PR_NewLock();
-    if (rwlock->rw_lock == NULL) {
-		PR_DELETE(rwlock);
-		return(NULL);
-	}
-	rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);
-    if (rwlock->rw_reader_waitq == NULL) {
-		PR_DestroyLock(rwlock->rw_lock);
-		PR_DELETE(rwlock);
-		return(NULL);
-	}
-	rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock);
-    if (rwlock->rw_writer_waitq == NULL) {
-		PR_DestroyCondVar(rwlock->rw_reader_waitq);	
-		PR_DestroyLock(rwlock->rw_lock);
-		PR_DELETE(rwlock);
-		return(NULL);
-	}
+
+	rwlock->rw_rank = lock_rank;
 	if (lock_name != NULL) {
 		rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1);
     	if (rwlock->rw_name == NULL) {
-			PR_DestroyCondVar(rwlock->rw_reader_waitq);	
-			PR_DestroyCondVar(rwlock->rw_writer_waitq);	
-			PR_DestroyLock(rwlock->rw_lock);
 			PR_DELETE(rwlock);
 			return(NULL);
 		}
 		strcpy(rwlock->rw_name, lock_name);
 	} else {
 		rwlock->rw_name = NULL;
 	}
-	rwlock->rw_rank = lock_rank;
+	
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	err = RWLOCK_INIT(&rwlock->rw_lock);
+	if (err != 0) {
+		PR_SetError(PR_UNKNOWN_ERROR, err);
+		PR_Free(rwlock->rw_name);
+		PR_DELETE(rwlock);
+		return NULL;
+	}
+	return rwlock;
+#else
+	rwlock->rw_lock = PR_NewLock();
+    if (rwlock->rw_lock == NULL) {
+		goto failed;
+	}
+	rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);
+    if (rwlock->rw_reader_waitq == NULL) {
+		goto failed;
+	}
+	rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock);
+    if (rwlock->rw_writer_waitq == NULL) {
+		goto failed;
+	}
 	rwlock->rw_reader_cnt = 0;
 	rwlock->rw_writer_cnt = 0;
 	rwlock->rw_lock_cnt = 0;
+	return rwlock;
 
-    return rwlock;
+failed:
+	if (rwlock->rw_reader_waitq != NULL) {
+		PR_DestroyCondVar(rwlock->rw_reader_waitq);	
+	}
+	if (rwlock->rw_lock != NULL) {
+		PR_DestroyLock(rwlock->rw_lock);
+	}
+	PR_Free(rwlock->rw_name);
+	PR_DELETE(rwlock);
+	return NULL;
+#endif
 }
 
 /*
 ** Destroy the given RWLock "lock".
 */
 PR_IMPLEMENT(void)
 PR_DestroyRWLock(PRRWLock *rwlock)
 {
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	int err;
+	err = RWLOCK_DESTROY(&rwlock->rw_lock);
+	PR_ASSERT(err == 0);
+#else
 	PR_ASSERT(rwlock->rw_reader_cnt == 0);
 	PR_DestroyCondVar(rwlock->rw_reader_waitq);	
 	PR_DestroyCondVar(rwlock->rw_writer_waitq);	
 	PR_DestroyLock(rwlock->rw_lock);
+#endif
 	if (rwlock->rw_name != NULL)
 		PR_Free(rwlock->rw_name);
     PR_DELETE(rwlock);
 }
 
 /*
 ** Read-lock the RWLock.
 */
 PR_IMPLEMENT(void)
 PR_RWLock_Rlock(PRRWLock *rwlock)
 {
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 PRThread *me = PR_GetCurrentThread();
+#endif
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
-
 	/*
 	 * assert that rank ordering is not violated; the rank of 'rwlock' should
 	 * be equal to or greater than the highest rank of all the locks held by
 	 * the thread.
 	 */
 	PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || 
 					(rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK(me)));
 #endif
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	err = RWLOCK_RDLOCK(&rwlock->rw_lock);
+	PR_ASSERT(err == 0);
+#else
 	PR_Lock(rwlock->rw_lock);
 	/*
 	 * wait if write-locked or if a writer is waiting; preference for writers
 	 */
 	while ((rwlock->rw_lock_cnt < 0) ||
 			(rwlock->rw_writer_cnt > 0)) {
 		rwlock->rw_reader_cnt++;
 		PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
 		rwlock->rw_reader_cnt--;
 	}
 	/*
 	 * Increment read-lock count
 	 */
 	rwlock->rw_lock_cnt++;
 
 	PR_Unlock(rwlock->rw_lock);
+#endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
 	_PR_SET_THREAD_RWLOCK_RANK(me,rwlock);
 #endif
 }
 
 /*
 ** Write-lock the RWLock.
 */
 PR_IMPLEMENT(void)
 PR_RWLock_Wlock(PRRWLock *rwlock)
 {
 PRInt32 lock_acquired = 0;
+#if defined(DEBUG) || defined(_PR_RWLOCK_RANK_ORDER_DEBUG)
 PRThread *me = PR_GetCurrentThread();
+#endif
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * assert that rank ordering is not violated; the rank of 'rwlock' should
 	 * be equal to or greater than the highest rank of all the locks held by
 	 * the thread.
 	 */
 	PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || 
 					(rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK(me)));
 #endif
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	err = RWLOCK_WRLOCK(&rwlock->rw_lock);
+	PR_ASSERT(err == 0);
+#else
 	PR_Lock(rwlock->rw_lock);
 	/*
 	 * wait if read locked
 	 */
 	while (rwlock->rw_lock_cnt != 0) {
 		rwlock->rw_writer_cnt++;
 		PR_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
 		rwlock->rw_writer_cnt--;
 	}
 	/*
 	 * apply write lock
 	 */
 	rwlock->rw_lock_cnt--;
 	PR_ASSERT(rwlock->rw_lock_cnt == -1);
 	PR_ASSERT(me != NULL);
+#ifdef DEBUG
     rwlock->rw_owner = me;
+#endif
 	PR_Unlock(rwlock->rw_lock);
+#endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
 	_PR_SET_THREAD_RWLOCK_RANK(me,rwlock);
 #endif
 }
 
 /*
 ** Unlock the RW lock.
 */
 PR_IMPLEMENT(void)
 PR_RWLock_Unlock(PRRWLock *rwlock)
 {
+#if defined(DEBUG) || defined(_PR_RWLOCK_RANK_ORDER_DEBUG)
 PRThread *me = PR_GetCurrentThread();
+#endif
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
 
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+	err = RWLOCK_UNLOCK(&rwlock->rw_lock);
+	PR_ASSERT(err == 0);
+#else
 	PR_Lock(rwlock->rw_lock);
 	/*
 	 * lock must be read or write-locked
 	 */
 	PR_ASSERT(rwlock->rw_lock_cnt != 0);
 	if (rwlock->rw_lock_cnt > 0) {
 
 		/*
@@ -247,85 +334,85 @@ PRThread *me = PR_GetCurrentThread();
 		if (rwlock->rw_lock_cnt == 0) {
 			/*
 			 * lock is not read-locked anymore; wakeup a waiting writer
 			 */
 			if (rwlock->rw_writer_cnt > 0)
 				PR_NotifyCondVar(rwlock->rw_writer_waitq);
 		}
 	} else {
-		PRThread *me = PR_GetCurrentThread();
-
 		PR_ASSERT(rwlock->rw_lock_cnt == -1);
 
 		rwlock->rw_lock_cnt = 0;
+#ifdef DEBUG
     	PR_ASSERT(rwlock->rw_owner == me);
     	rwlock->rw_owner = NULL;
+#endif
 		/*
 		 * wakeup a writer, if present; preference for writers
 		 */
 		if (rwlock->rw_writer_cnt > 0)
 			PR_NotifyCondVar(rwlock->rw_writer_waitq);
 		/*
 		 * else, wakeup all readers, if any
 		 */
 		else if (rwlock->rw_reader_cnt > 0)
 			PR_NotifyAllCondVar(rwlock->rw_reader_waitq);
 	}
 	PR_Unlock(rwlock->rw_lock);
+#endif
 
 #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
 	/*
 	 * update thread's lock rank
 	 */
 	_PR_UNSET_THREAD_RWLOCK_RANK(me, rwlock);
 #endif
 	return;
 }
 
-#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+#ifndef _PR_RWLOCK_RANK_ORDER_DEBUG
+
+void _PR_InitRWLocks(void) { }
+
+#else
+
+void _PR_InitRWLocks(void)
+{
+	/*
+	 * allocated thread-private-data index for rwlock list
+	 */
+	if (PR_NewThreadPrivateIndex(&pr_thread_rwlock_key,
+			_PR_RELEASE_LOCK_STACK) == PR_FAILURE) {
+		pr_thread_rwlock_alloc_failed = 1;
+		return;
+	}
+}
 
 /*
  * _PR_SET_THREAD_RWLOCK_RANK
  *		Set a thread's lock rank, which is the highest of the ranks of all
  *		the locks held by the thread. Pointers to the locks are added to a
  *		per-thread list, which is anchored off a thread-private data key.
  */
 
 static void
 _PR_SET_THREAD_RWLOCK_RANK(PRThread *me, PRRWLock *rwlock)
 {
 thread_rwlock_stack *lock_stack;
 PRStatus rv;
 
 	/*
-	 * allocated thread-private-data for rwlock list, if not already allocated
-	 */
-	if (!pr_thread_rwlock_initialized) {
-		/*
-		 * allocate tpd, only if not failed already
-		 */
-		if (!pr_thread_rwlock_alloc_failed) {
-			if (PR_NewThreadPrivateIndex(&pr_thread_rwlock,
-										_PR_RELEASE_LOCK_STACK)
-												== PR_FAILURE) {
-				pr_thread_rwlock_alloc_failed = 1;
-				return;
-			}
-		} else
-			return;
-	}
-	/*
 	 * allocate a lock stack
 	 */
-	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock)) == NULL) {
+	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL) {
 		lock_stack = (thread_rwlock_stack *)
 						PR_CALLOC(1 * sizeof(thread_rwlock_stack));
 		if (lock_stack) {
-			rv = PR_SetThreadPrivate(pr_thread_rwlock, lock_stack);
+			rv = PR_SetThreadPrivate(pr_thread_rwlock_key, lock_stack);
 			if (rv == PR_FAILURE) {
 				PR_DELETE(lock_stack);
 				pr_thread_rwlock_alloc_failed = 1;
 				return;
 			}
 		} else {
 			pr_thread_rwlock_alloc_failed = 1;
 			return;
@@ -333,17 +420,16 @@ PRStatus rv;
 	}
 	/*
 	 * add rwlock to lock stack, if limit is not exceeded
 	 */
 	if (lock_stack) {
 		if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT)
 			lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;	
 	}
-	pr_thread_rwlock_initialized = 1;
 }
 
 static void
 _PR_RELEASE_LOCK_STACK(void *lock_stack)
 {
 	PR_ASSERT(lock_stack);
 	PR_DELETE(lock_stack);
 }
@@ -355,43 +441,36 @@ static void
  *		stack is not allocated, return PR_RWLOCK_RANK_NONE.
  */
 	
 static PRUint32
 _PR_GET_THREAD_RWLOCK_RANK(PRThread *me)
 {
 	thread_rwlock_stack *lock_stack;
 
-	if (pr_thread_rwlock_initialized) {
-		if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock)) == NULL)
-			return (PR_RWLOCK_RANK_NONE);
-		else
-			return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
-
-	} else
-			return (PR_RWLOCK_RANK_NONE);
+	if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL)
+		return (PR_RWLOCK_RANK_NONE);
+	else
+		return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
 }
 
 /*
  * _PR_UNSET_THREAD_RWLOCK_RANK
  *
  *		remove the rwlock from the lock stack. Since locks may not be
  *		unlocked in a FIFO order, the entire lock stack is searched.
  */
 	
 static void
 _PR_UNSET_THREAD_RWLOCK_RANK(PRThread *me, PRRWLock *rwlock)
 {
 	thread_rwlock_stack *lock_stack;
 	int new_index = 0, index, done = 0;
 
-	if (!pr_thread_rwlock_initialized)
-		return;
-
-	lock_stack = PR_GetThreadPrivate(pr_thread_rwlock);
+	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)  {
 			/*
 			 * reset the slot for rwlock
--- a/pr/tests/Makefile
+++ b/pr/tests/Makefile
@@ -46,16 +46,17 @@ CSRCS =             \
 	cleanup.c		\
 	cltsrv.c		\
 	concur.c	    \
 	cvar.c			\
 	cvar2.c			\
 	dceemu.c		\
 	dlltest.c		\
 	dtoa.c			\
+	errcodes.c		\
 	exit.c  		\
 	fileio.c		\
 	foreign.c	    \
 	forktest.c	    \
 	fsync.c	        \
 	getproto.c		\
 	i2l.c		    \
 	initclk.c		\
@@ -133,16 +134,17 @@ CSRCS =             \
 	testfile.c    	\
 	threads.c 	  	\
 	thruput.c 	  	\
 	timemac.c		\
 	timetest.c		\
 	tmoacc.c        \
 	tmocon.c        \
 	tpd.c			\
+	vercheck.c		\
 	version.c	    \
 	udpsrv.c	    \
 	writev.c        \
 	xnotify.c       \
 	$(NULL)
 
 ifeq ($(OS_TARGET),OS2)
 CSRCS +=            \
@@ -467,16 +469,20 @@ install:: export
 clean::
 	rm -f $(TARGETS)
 
 ifeq ($(USE_PTHREADS), 1)
 $(OBJDIR)/foreign: $(OBJDIR)/foreign.o
 	$(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
 $(OBJDIR)/provider: $(OBJDIR)/provider.o
 	$(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/socket: $(OBJDIR)/socket.o
+	$(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/testfile: $(OBJDIR)/testfile.o
+	$(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
 endif
 
 #
 # Run the test programs with no arguments
 #
 # Test output goes to the file pointed to by the environment variable
 # NSPR_TEST_LOGFILE, if set, else to /dev/null
 #
new file mode 100644
--- /dev/null
+++ b/pr/tests/errcodes.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL.  You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ * 
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ * 
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation.  Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
+ * Reserved.
+ */
+
+/***********************************************************************
+**
+** Name: errcodes.c
+**
+** Description: print nspr error codes
+**
+*/
+#include "prerror.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+static int _debug_on = 0;
+
+struct errinfo {
+	PRErrorCode errcode;
+	char 		*errname;
+};
+
+struct errinfo errcodes[] = {
+{PR_OUT_OF_MEMORY_ERROR,			"PR_OUT_OF_MEMORY_ERROR"},
+{PR_BAD_DESCRIPTOR_ERROR,			"PR_BAD_DESCRIPTOR_ERROR"},
+{PR_WOULD_BLOCK_ERROR,				"PR_WOULD_BLOCK_ERROR"},
+{PR_ACCESS_FAULT_ERROR,				"PR_ACCESS_FAULT_ERROR"},
+{PR_INVALID_METHOD_ERROR,			"PR_INVALID_METHOD_ERROR"},
+{PR_ILLEGAL_ACCESS_ERROR,			"PR_ILLEGAL_ACCESS_ERROR"},
+{PR_UNKNOWN_ERROR,					"PR_UNKNOWN_ERROR"},
+{PR_PENDING_INTERRUPT_ERROR,		"PR_PENDING_INTERRUPT_ERROR"},
+{PR_NOT_IMPLEMENTED_ERROR,			"PR_NOT_IMPLEMENTED_ERROR"},
+{PR_IO_ERROR,						"PR_IO_ERROR"},
+{PR_IO_TIMEOUT_ERROR,				"PR_IO_TIMEOUT_ERROR"},
+{PR_IO_PENDING_ERROR,				"PR_IO_PENDING_ERROR"},
+{PR_DIRECTORY_OPEN_ERROR,			"PR_DIRECTORY_OPEN_ERROR"},
+{PR_INVALID_ARGUMENT_ERROR,			"PR_INVALID_ARGUMENT_ERROR"},
+{PR_ADDRESS_NOT_AVAILABLE_ERROR,	"PR_ADDRESS_NOT_AVAILABLE_ERROR"},
+{PR_ADDRESS_NOT_SUPPORTED_ERROR,	"PR_ADDRESS_NOT_SUPPORTED_ERROR"},
+{PR_IS_CONNECTED_ERROR,				"PR_IS_CONNECTED_ERROR"},
+{PR_BAD_ADDRESS_ERROR,				"PR_BAD_ADDRESS_ERROR"},
+{PR_ADDRESS_IN_USE_ERROR,			"PR_ADDRESS_IN_USE_ERROR"},
+{PR_CONNECT_REFUSED_ERROR,			"PR_CONNECT_REFUSED_ERROR"},
+{PR_NETWORK_UNREACHABLE_ERROR,		"PR_NETWORK_UNREACHABLE_ERROR"},
+{PR_CONNECT_TIMEOUT_ERROR,			"PR_CONNECT_TIMEOUT_ERROR"},
+{PR_NOT_CONNECTED_ERROR,			"PR_NOT_CONNECTED_ERROR"},
+{PR_LOAD_LIBRARY_ERROR,				"PR_LOAD_LIBRARY_ERROR"},
+{PR_UNLOAD_LIBRARY_ERROR,			"PR_UNLOAD_LIBRARY_ERROR"},
+{PR_FIND_SYMBOL_ERROR,				"PR_FIND_SYMBOL_ERROR"},
+{PR_INSUFFICIENT_RESOURCES_ERROR,	"PR_INSUFFICIENT_RESOURCES_ERROR"},
+{PR_DIRECTORY_LOOKUP_ERROR,			"PR_DIRECTORY_LOOKUP_ERROR"},
+{PR_TPD_RANGE_ERROR,				"PR_TPD_RANGE_ERROR"},
+{PR_PROC_DESC_TABLE_FULL_ERROR,		"PR_PROC_DESC_TABLE_FULL_ERROR"},
+{PR_SYS_DESC_TABLE_FULL_ERROR,		"PR_SYS_DESC_TABLE_FULL_ERROR"},
+{PR_NOT_SOCKET_ERROR,				"PR_NOT_SOCKET_ERROR"},
+{PR_NOT_TCP_SOCKET_ERROR,			"PR_NOT_TCP_SOCKET_ERROR"},
+{PR_SOCKET_ADDRESS_IS_BOUND_ERROR,	"PR_SOCKET_ADDRESS_IS_BOUND_ERROR"},
+{PR_NO_ACCESS_RIGHTS_ERROR,			"PR_NO_ACCESS_RIGHTS_ERROR"},
+{PR_OPERATION_NOT_SUPPORTED_ERROR,	"PR_OPERATION_NOT_SUPPORTED_ERROR"},
+{PR_PROTOCOL_NOT_SUPPORTED_ERROR,	"PR_PROTOCOL_NOT_SUPPORTED_ERROR"},
+{PR_REMOTE_FILE_ERROR,				"PR_REMOTE_FILE_ERROR"},
+{PR_BUFFER_OVERFLOW_ERROR,			"PR_BUFFER_OVERFLOW_ERROR"},
+{PR_CONNECT_RESET_ERROR,			"PR_CONNECT_RESET_ERROR"},
+{PR_RANGE_ERROR,					"PR_RANGE_ERROR"},
+{PR_DEADLOCK_ERROR,					"PR_DEADLOCK_ERROR"},
+{PR_FILE_IS_LOCKED_ERROR,			"PR_FILE_IS_LOCKED_ERROR"},
+{PR_FILE_TOO_BIG_ERROR,				"PR_FILE_TOO_BIG_ERROR"},
+{PR_NO_DEVICE_SPACE_ERROR,			"PR_NO_DEVICE_SPACE_ERROR"},
+{PR_PIPE_ERROR,						"PR_PIPE_ERROR"},
+{PR_NO_SEEK_DEVICE_ERROR,			"PR_NO_SEEK_DEVICE_ERROR"},
+{PR_IS_DIRECTORY_ERROR,				"PR_IS_DIRECTORY_ERROR"},
+{PR_LOOP_ERROR,						"PR_LOOP_ERROR"},
+{PR_NAME_TOO_LONG_ERROR,			"PR_NAME_TOO_LONG_ERROR"},
+{PR_FILE_NOT_FOUND_ERROR,			"PR_FILE_NOT_FOUND_ERROR"},
+{PR_NOT_DIRECTORY_ERROR,			"PR_NOT_DIRECTORY_ERROR"},
+{PR_READ_ONLY_FILESYSTEM_ERROR,		"PR_READ_ONLY_FILESYSTEM_ERROR"},
+{PR_DIRECTORY_NOT_EMPTY_ERROR,		"PR_DIRECTORY_NOT_EMPTY_ERROR"},
+{PR_FILESYSTEM_MOUNTED_ERROR,		"PR_FILESYSTEM_MOUNTED_ERROR"},
+{PR_NOT_SAME_DEVICE_ERROR,			"PR_NOT_SAME_DEVICE_ERROR"},
+{PR_DIRECTORY_CORRUPTED_ERROR,		"PR_DIRECTORY_CORRUPTED_ERROR"},
+{PR_FILE_EXISTS_ERROR,				"PR_FILE_EXISTS_ERROR"},
+{PR_MAX_DIRECTORY_ENTRIES_ERROR,	"PR_MAX_DIRECTORY_ENTRIES_ERROR"},
+{PR_INVALID_DEVICE_STATE_ERROR,		"PR_INVALID_DEVICE_STATE_ERROR"},
+{PR_DEVICE_IS_LOCKED_ERROR,			"PR_DEVICE_IS_LOCKED_ERROR"},
+{PR_NO_MORE_FILES_ERROR,			"PR_NO_MORE_FILES_ERROR"},
+{PR_END_OF_FILE_ERROR,				"PR_END_OF_FILE_ERROR"},
+{PR_FILE_SEEK_ERROR,				"PR_FILE_SEEK_ERROR"},
+{PR_FILE_IS_BUSY_ERROR,				"PR_FILE_IS_BUSY_ERROR"},
+{PR_IN_PROGRESS_ERROR,				"PR_IN_PROGRESS_ERROR"},
+{PR_ALREADY_INITIATED_ERROR,		"PR_ALREADY_INITIATED_ERROR"},
+{PR_GROUP_EMPTY_ERROR,				"PR_GROUP_EMPTY_ERROR"},
+{PR_INVALID_STATE_ERROR,			"PR_INVALID_STATE_ERROR"},
+{PR_NETWORK_DOWN_ERROR,				"PR_NETWORK_DOWN_ERROR"},
+{PR_SOCKET_SHUTDOWN_ERROR,			"PR_SOCKET_SHUTDOWN_ERROR"},
+{PR_CONNECT_ABORTED_ERROR,			"PR_CONNECT_ABORTED_ERROR"},
+{PR_HOST_UNREACHABLE_ERROR,			"PR_HOST_UNREACHABLE_ERROR"}
+};
+
+int
+main(int argc, char **argv)
+{
+
+	int count, errnum;
+
+    /*
+     * -d           debug mode
+     */
+
+    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);
+
+	count = sizeof(errcodes)/sizeof(errcodes[0]);
+	printf("\nNumber of error codes = %d\n\n",count);
+	for (errnum = 0; errnum < count; errnum++) {
+		printf("%-40s = %d\n",errcodes[errnum].errname,
+						errcodes[errnum].errcode);
+	}
+
+	return 0;
+}
--- a/pr/tests/rwlocktest.c
+++ b/pr/tests/rwlocktest.c
@@ -31,54 +31,53 @@ static int _debug_on;
 static void rwtest(void *args);
 static PRInt32 *array_A,*array_B,*array_C;
 static void update_array(void);
 static void check_array(void);
 
 typedef struct thread_args {
 	PRRWLock	*rwlock;
 	PRInt32		loop_cnt;
-	void		*data;
 } thread_args;
 
 PRFileDesc  *output;
 PRFileDesc  *errhandle;
 
 #define	DEFAULT_THREAD_CNT	4
-#define	DEFAULT_DATA_CNT	100
+#define	DEFAULT_LOOP_CNT	100
 #define	TEST_ARRAY_SIZE		100
 
 PRIntn main(PRIntn argc, char **argv)
 {
     PRInt32 cnt;
 	PRStatus rc;
 	PRInt32 i;
 
 	PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
-	PRInt32 data_cnt = DEFAULT_DATA_CNT;
+	PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
 	PRThread **threads;
 	thread_args *params;
 	PRRWLock	*rwlock1;
 
 	PLOptStatus os;
-	PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
+	PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
 
 	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;
         case 't':  /* thread count */
             thread_cnt = atoi(opt->value);
             break;
-        case 'c':  /* data count */
-            data_cnt = atoi(opt->value);
+        case 'c':  /* loop count */
+            loop_cnt = atoi(opt->value);
             break;
          default:
             break;
         }
     }
 	PL_DestroyOptState(opt);
 
 	PR_SetConcurrency(4);
@@ -94,38 +93,34 @@ PRIntn main(PRIntn argc, char **argv)
 	}
 
 	threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
 	params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
 
 	/*
 	 * allocate and initialize data arrays
 	 */
-	array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE
-									* TEST_ARRAY_SIZE);
-	array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE
-									* TEST_ARRAY_SIZE);
-	array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE
-									* TEST_ARRAY_SIZE);
+	array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
+	array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
+	array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
 	cnt = 0;
 	for (i=0; i < TEST_ARRAY_SIZE;i++) {
 		array_A[i] = cnt++;
 		array_B[i] = cnt++;
 		array_C[i] = array_A[i] + array_B[i];
 	}
 
 	if (_debug_on)
-		PR_fprintf(output,"%s: thread_cnt = %d data_cnt = %d\n", argv[0],
-							thread_cnt, data_cnt);
+		PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
+							thread_cnt, loop_cnt);
 	for(cnt = 0; cnt < thread_cnt; cnt++) {
 		PRThreadScope scope;
 
 		params[cnt].rwlock = rwlock1;
-		params[cnt].data = NULL;
-		params[cnt].loop_cnt = data_cnt;
+		params[cnt].loop_cnt = loop_cnt;
 
 		/*
 		 * create LOCAL and GLOBAL threads alternately
 		 */
 		if (cnt & 1)
 			scope = PR_LOCAL_THREAD;
 		else
 			scope = PR_GLOBAL_THREAD;
@@ -157,16 +152,17 @@ PRIntn main(PRIntn argc, char **argv)
 
 	PR_DELETE(array_A);	
 	PR_DELETE(array_B);	
 	PR_DELETE(array_C);	
 
 	PR_DestroyRWLock(rwlock1);
 
 	
+	printf("PASS\n");
 	return 0;
 }
 
 static void rwtest(void *args)
 {
     PRInt32 index;
 	thread_args *arg = (thread_args *) args;
 
--- a/pr/tests/socket.c
+++ b/pr/tests/socket.c
@@ -29,16 +29,23 @@
 #include "plgetopt.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #ifdef XP_UNIX
 #include <sys/mman.h>
 #endif
+#if defined(_PR_PTHREADS)
+#include <pthread.h>
+#endif
+
+#ifdef WINNT
+#include <process.h>
+#endif
 
 static int _debug_on = 0;
 
 #ifdef XP_MAC
 #include "prlog.h"
 #include "prsem.h"
 int fprintf(FILE *stream, const char *fmt, ...)
 {
@@ -239,16 +246,72 @@ Serve_Client(void *arg)
 
 exit:
     PR_Close(sockfd);
     if (in_buf) {
         PR_DELETE(in_buf);
     }
 }
 
+PRThread* create_new_thread(PRThreadType type,
+							void (*start)(void *arg),
+							void *arg,
+							PRThreadPriority priority,
+							PRThreadScope scope,
+							PRThreadState state,
+							PRUint32 stackSize, PRInt32 index)
+{
+PRInt32 native_thread = 0;
+
+	PR_ASSERT(state == PR_UNJOINABLE_THREAD);
+#if defined(_PR_PTHREADS) || defined(WINNT)
+	switch(index %  4) {
+		case 0:
+			scope = (PR_LOCAL_THREAD);
+			break;
+		case 1:
+			scope = (PR_GLOBAL_THREAD);
+			break;
+		case 2:
+			scope = (PR_GLOBAL_BOUND_THREAD);
+			break;
+		case 3:
+			native_thread = 1;
+			break;
+		default:
+			PR_ASSERT(!"Invalid scope");
+			break;
+	}
+	if (native_thread) {
+#ifdef _PR_PTHREADS
+		pthread_t tid;
+		if (!pthread_create(&tid, NULL, start, arg))
+			return((PRThread *) tid);
+		else
+			return (NULL);
+#else
+		HANDLE thandle;
+		
+		thandle = (HANDLE) _beginthreadex(
+						NULL,
+						stackSize,
+						(unsigned (__stdcall *)(void *))start,
+						arg,
+						0,
+						NULL);		
+		return((PRThread *) thandle);
+#endif
+	} else {
+		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+	}
+#else
+	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+#endif
+}
+
 /*
  * TCP Server
  *    Server Thread
  *    Bind an address to a socket and listen for incoming connections
  *    Start a Serve_Client thread for each incoming connection.
  */
 static void PR_CALLBACK
 TCP_Server(void *arg)
@@ -325,22 +388,22 @@ TCP_Server(void *arg)
         }
 
         /*
          * Start a Serve_Client thread for each incoming connection
          */
         scp->sockfd = newsockfd;
         scp->datalen = sp->datalen;
 
-        t = PR_CreateThread(PR_USER_THREAD,
+        t = create_new_thread(PR_USER_THREAD,
             Serve_Client, (void *)scp, 
             PR_PRIORITY_NORMAL,
             PR_LOCAL_THREAD,
             PR_UNJOINABLE_THREAD,
-            0);
+            0, i);
         if (t == NULL) {
             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
             failed_already=1;
             goto exit;
         }
         DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
     }
 
@@ -724,17 +787,16 @@ UDP_Client(void *arg)
  *
  */
 
 static PRInt32
 TCP_Socket_Client_Server_Test(void)
 {
     int i;
     PRThread *t;
-    PRThreadScope scope;
     PRSemaphore *server_sem;
     Server_Param *sparamp;
     Client_Param *cparamp;
     PRMonitor *mon2;
     PRInt32    datalen;
 
 
     datalen = tcp_mesg_size;
@@ -796,29 +858,22 @@ TCP_Socket_Client_Server_Test(void)
         return -1;
     }
     cparamp->server_addr = tcp_server_addr;
     cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     cparamp->exit_mon = mon2;
     cparamp->exit_counter = &thread_count;
     cparamp->datalen = datalen;
     for (i = 0; i < num_tcp_clients; i++) {
-        /*
-         * Every other thread is a LOCAL/GLOBAL thread
-         */
-        if (i & 1)
-            scope = PR_LOCAL_THREAD;
-        else
-            scope = PR_GLOBAL_THREAD;
-        t = PR_CreateThread(PR_USER_THREAD,
+        t = create_new_thread(PR_USER_THREAD,
             TCP_Client, (void *) cparamp,
             PR_PRIORITY_NORMAL,
-            scope,
+            PR_LOCAL_THREAD,
             PR_UNJOINABLE_THREAD,
-            0);
+            0, i);
         if (t == NULL) {
             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
             failed_already=1;
             return -1;
         }
         DPRINTF(("Created TCP client = 0x%lx\n", t));
         thread_count++;
     }
@@ -1129,17 +1184,16 @@ static void
 TransmitFile_Server(void *arg)
 {
     PRThread **t = NULL;  /* an array of PRThread pointers */
     Server_Param *sp = (Server_Param *) arg;
     Serve_Client_Param *scp;
     PRFileDesc *sockfd = NULL, *newsockfd;
     PRNetAddr netaddr;
     PRInt32 i;
-    PRThreadScope scope;
 
     t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *));
     if (t == NULL) {
         fprintf(stderr, "prsocket_test: run out of memory\n");
         failed_already=1;
         goto exit;
     }
     /*
@@ -1213,27 +1267,20 @@ TransmitFile_Server(void *arg)
         }
 
         /*
          * Start a Serve_Client thread for each incoming connection
          */
         scp->sockfd = newsockfd;
         scp->datalen = sp->datalen;
 
-        /*
-         * create LOCAL and GLOBAL threads alternately
-         */
-        if (i & 1)
-            scope = PR_LOCAL_THREAD;
-        else
-            scope = PR_GLOBAL_THREAD;
         t[i] = PR_CreateThread(PR_USER_THREAD,
             Serve_TransmitFile_Client, (void *)scp, 
             PR_PRIORITY_NORMAL,
-            scope,
+            PR_LOCAL_THREAD,
             PR_JOINABLE_THREAD,
             0);
         if (t[i] == NULL) {
             fprintf(stderr,
                 "prsocket_test: PR_CreateThread failed\n");
             failed_already=1;
             goto exit;
         }
@@ -1272,17 +1319,16 @@ exit:
  * Socket_Misc_Test    - test miscellaneous functions 
  *    
  */
 static PRInt32
 Socket_Misc_Test(void)
 {
     PRIntn i, rv = 0, bytes, count, len;
     PRThread *t;
-    PRThreadScope scope;
     PRSemaphore *server_sem;
     Server_Param *sparamp;
     Client_Param *cparamp;
     PRMonitor *mon2;
     PRInt32    datalen;
 
     /*
  * We deliberately pick a buffer size that is not a nice multiple
@@ -1479,29 +1525,22 @@ Socket_Misc_Test(void)
         goto done;
     }
     cparamp->server_addr = tcp_server_addr;
     cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     cparamp->exit_mon = mon2;
     cparamp->exit_counter = &thread_count;
     cparamp->datalen = datalen;
     for (i = 0; i < num_transmitfile_clients; i++) {
-        /*
-         * Every other thread is a LOCAL/GLOBAL thread
-         */
-        if (i & 1)
-            scope = PR_GLOBAL_THREAD;
-        else
-            scope = PR_LOCAL_THREAD;
-        t = PR_CreateThread(PR_USER_THREAD,
+        t = create_new_thread(PR_USER_THREAD,
             TransmitFile_Client, (void *) cparamp,
             PR_PRIORITY_NORMAL,
-            scope,
+            PR_LOCAL_THREAD,
             PR_UNJOINABLE_THREAD,
-            0);
+            0, i);
         if (t == NULL) {
             fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
             rv = -1;
             failed_already=1;
             goto done;
         }
         DPRINTF(("Created TransmitFile client = 0x%lx\n", t));
         thread_count++;
--- a/pr/tests/testfile.c
+++ b/pr/tests/testfile.c
@@ -19,16 +19,20 @@
 #include "nspr.h"
 #include "prpriv.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #ifdef WIN32
 #include <windows.h>
+#include <process.h>
+#endif
+#if defined(_PR_PTHREADS)
+#include <pthread.h>
 #endif
 
 #if defined(XP_OS2)
 #define INCL_DOSFILEMGR
 #include <os2.h>
 #ifdef XP_OS2_EMX
 #include <getopt.h>
 #endif /* XP_OS2_EMX */
@@ -56,17 +60,18 @@ PRInt32 count;
 int thread_count;
 
 #ifdef WIN16
 #define	BUF_DATA_SIZE	256 * 120
 #else
 #define	BUF_DATA_SIZE	256 * 1024
 #endif
 
-#define NUM_RDWR_THREADS 10
+#define NUM_RDWR_THREADS	10
+#define NUM_DIRTEST_THREADS	4
 #define CHUNK_SIZE 512
 
 typedef struct buffer {
 	char	data[BUF_DATA_SIZE];
 } buffer;
 
 typedef struct File_Rdwr_Param {
 	char	*pathname;
@@ -85,16 +90,78 @@ char *FILE_NAME = "pr_testfile";
 char *HIDDEN_FILE_NAME = "hidden_pr_testfile";
 #else
 char *TEST_DIR = "/tmp/testfile_dir";
 char *FILE_NAME = "pr_testfile";
 char *HIDDEN_FILE_NAME = ".hidden_pr_testfile";
 #endif
 buffer *in_buf, *out_buf;
 char pathname[256], renamename[256];
+#define TMPDIR_LEN	64
+char testdir[TMPDIR_LEN];
+static PRInt32 PR_CALLBACK DirTest(void *argunused);
+PRInt32 dirtest_failed = 0;
+
+PRThread* create_new_thread(PRThreadType type,
+							void (*start)(void *arg),
+							void *arg,
+							PRThreadPriority priority,
+							PRThreadScope scope,
+							PRThreadState state,
+							PRUint32 stackSize, PRInt32 index)
+{
+PRInt32 native_thread = 0;
+
+	PR_ASSERT(state == PR_UNJOINABLE_THREAD);
+#if defined(_PR_PTHREADS) || defined(WINNT)
+	switch(index %  4) {
+		case 0:
+			scope = (PR_LOCAL_THREAD);
+			break;
+		case 1:
+			scope = (PR_GLOBAL_THREAD);
+			break;
+		case 2:
+			scope = (PR_GLOBAL_BOUND_THREAD);
+			break;
+		case 3:
+			native_thread = 1;
+			break;
+		default:
+			PR_ASSERT(!"Invalid scope");
+			break;
+	}
+	if (native_thread) {
+#ifdef _PR_PTHREADS
+		pthread_t tid;
+		printf("creating pthread\n");
+		if (!pthread_create(&tid, NULL, start, arg))
+			return((PRThread *) tid);
+		else
+			return (NULL);
+#else
+		HANDLE thandle;
+		
+		printf("creating Windows thread\n");
+		thandle = (HANDLE) _beginthreadex(
+						NULL,
+						stackSize,
+						(unsigned (__stdcall *)(void *))start,
+						arg,
+						0,
+						NULL);		
+		return((PRThread *) thandle);
+#endif
+	} else {
+		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+	}
+#else
+	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+#endif
+}
 
 static void PR_CALLBACK File_Write(void *arg)
 {
 PRFileDesc *fd_file;
 File_Rdwr_Param *fp = (File_Rdwr_Param *) arg;
 char *name, *buf;
 int offset, len;
 
@@ -159,227 +226,249 @@ int offset, len;
 
 	PR_EnterMonitor(mon);
 	--thread_count;
 	PR_Notify(mon);
 	PR_ExitMonitor(mon);
 }
 
 
-static void Misc_File_Tests(char *pathname)
+static PRInt32 Misc_File_Tests(char *pathname)
 {
 PRFileDesc *fd_file;
-int len;
+int len, rv = 0;
 PRFileInfo file_info, file_info1;
 char tmpname[1024];
 
 	setbuf(stdout, NULL);
 	/*
 	 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
 	 */
 
 	fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
 
 	if (fd_file == NULL) {
 		printf("testfile failed to create/open file %s\n",pathname);
-		return;
+		return -1;
 	}
 	if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
 		printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (PR_Access(pathname, PR_ACCESS_EXISTS) != 0) {
 		printf("testfile PR_Access failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (PR_Access(pathname, PR_ACCESS_WRITE_OK) != 0) {
 		printf("testfile PR_Access failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (PR_Access(pathname, PR_ACCESS_READ_OK) != 0) {
 		printf("testfile PR_Access failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 
 
 	if (PR_GetFileInfo(pathname, &file_info) < 0) {
 		printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
-		return;
+		rv = -1;
+		goto cleanup;
 	}
 	if (file_info.type != PR_FILE_FILE) {
-		printf(
-		"testfile PR_GetFileInfo returned incorrect type for file %s\n",
+	printf(
+	"testfile: Error - PR_GetFileInfo returned incorrect type for file %s\n",
 		pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (file_info.size != 0) {
 		printf(
 		"testfile PR_GetFileInfo returned incorrect size (%d should be 0) for file %s\n",
 		file_info.size, pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	file_info1 = file_info;
 
 	len = PR_Available(fd_file);
 	if (len < 0) {
 		printf("testfile PR_Available failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	} else if (len != 0) {
 		printf(
 		"testfile PR_Available failed: expected/returned = %d/%d bytes\n",
 			0, len);
+		rv = -1;
 		goto cleanup;
 	}
 	len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
 	if (len < 0) {
 		printf("testfile failed to write to file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
 		printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
 		goto cleanup;
 	}
 	if (file_info.size != CHUNK_SIZE) {
 		printf(
 		"testfile PR_GetFileInfo returned incorrect size (%d should be %d) for file %s\n",
 		file_info.size, CHUNK_SIZE, pathname);
+		rv = -1;
 		goto cleanup;
 	}
 	if (LL_NE(file_info.creationTime , file_info1.creationTime)) {
 		printf(
 		"testfile PR_GetFileInfo returned incorrect creation time: %s\n",
 		pathname);
+		printf("ft = %lld, ft1 = %lld\n",file_info.creationTime,
+									file_info1.creationTime);
+		rv = -1;
 		goto cleanup;
 	}
 	if (LL_CMP(file_info.modifyTime, > , file_info1.modifyTime)) {
 		printf(
 		"testfile PR_GetFileInfo returned incorrect modify time: %s\n",
 		pathname);
+		rv = -1;
 		goto cleanup;
 	}
 
 	len = PR_Available(fd_file);
 	if (len < 0) {
 		printf("testfile PR_Available failed on file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	} else if (len != 0) {
 		printf(
 		"testfile PR_Available failed: expected/returned = %d/%d bytes\n",
 			0, len);
+		rv = -1;
 		goto cleanup;
 	}
 	
 	PR_Seek(fd_file, 0, PR_SEEK_SET);
 	len = PR_Available(fd_file);
 	if (len < 0) {
 		printf("testfile PR_Available failed on file %s\n",pathname);
-		return;
+		rv = -1;
+		goto cleanup;
 	} else if (len != CHUNK_SIZE) {
 		printf(
 		"testfile PR_Available failed: expected/returned = %d/%d bytes\n",
 			CHUNK_SIZE, len);
+		rv = -1;
 		goto cleanup;
 	}
     PR_Close(fd_file);
 
 	strcpy(tmpname,pathname);
 	strcat(tmpname,".RENAMED");
 	if (PR_FAILURE == PR_Rename(pathname, tmpname)) {
 		printf("testfile failed to rename file %s\n",pathname);
+		rv = -1;
 		goto cleanup;
 	}
 
 	fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
 	len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
     PR_Close(fd_file);
 	if (PR_SUCCESS == PR_Rename(pathname, tmpname)) {
 		printf("testfile renamed to existing file %s\n",pathname);
 	}
 
-	if ((PR_Delete(tmpname)) < 0)
+	if ((PR_Delete(tmpname)) < 0) {
 		printf("testfile failed to unlink file %s\n",tmpname);
+		rv = -1;
+	}
 
 cleanup:
-	if ((PR_Delete(pathname)) < 0)
+	if ((PR_Delete(pathname)) < 0) {
 		printf("testfile failed to unlink file %s\n",pathname);
+		rv = -1;
+	}
+	return rv;
 }
 
 
 static PRInt32 PR_CALLBACK FileTest(void)
 {
 PRDir *fd_dir;
-int i, offset, len;
+int i, offset, len, rv = 0;
 PRThread *t;
 PRThreadScope scope;
 File_Rdwr_Param *fparamp;
 
 	/*
 	 * Create Test dir
 	 */
 	if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
 		printf("testfile failed to create dir %s\n",TEST_DIR);
 		return -1;
 	}
 	fd_dir = PR_OpenDir(TEST_DIR);
 	if (fd_dir == NULL) {
 		printf("testfile failed to open dir %s\n",TEST_DIR);
-		return -1;
+		rv =  -1;
+		goto cleanup;	
 	}
 
     PR_CloseDir(fd_dir);
 
 	strcat(pathname, TEST_DIR);
 	strcat(pathname, "/");
 	strcat(pathname, FILE_NAME);
 
 	in_buf = PR_NEW(buffer);
 	if (in_buf == NULL) {
 		printf(
 		"testfile failed to alloc buffer struct\n");
-		return -1;
+		rv =  -1;
+		goto cleanup;	
 	}
 	out_buf = PR_NEW(buffer);
 	if (out_buf == NULL) {
 		printf(
 		"testfile failed to alloc buffer struct\n");
-		return -1;
+		rv =  -1;
+		goto cleanup;	
 	}
 
 	/*
 	 * Start a bunch of writer threads
 	 */
 	offset = 0;
 	len = CHUNK_SIZE;
 	PR_EnterMonitor(mon);
 	for (i = 0; i < NUM_RDWR_THREADS; i++) {
 		fparamp = PR_NEW(File_Rdwr_Param);
 		if (fparamp == NULL) {
 			printf(
 			"testfile failed to alloc File_Rdwr_Param struct\n");
-			return -1;
+			rv =  -1;
+			goto cleanup;	
 		}
 		fparamp->pathname = pathname;
 		fparamp->buf = out_buf->data + offset;
 		fparamp->offset = offset;
 		fparamp->len = len;
 		memset(fparamp->buf, i, len);
-		/*
-		 * Create LOCAL and GLOBAL Threads, alternately
-		 */
-		if (i % 1)
-			scope = PR_GLOBAL_THREAD;
-		else
-			scope = PR_LOCAL_THREAD;
 
-		t = PR_CreateThread(PR_USER_THREAD,
+		t = create_new_thread(PR_USER_THREAD,
 			      File_Write, (void *)fparamp, 
 			      PR_PRIORITY_NORMAL,
 			      scope,
 			      PR_UNJOINABLE_THREAD,
-			      0);
+			      0, i);
 		offset += len;
 	}
 	thread_count = i;
 	/* Wait for writer threads to exit */
 	while (thread_count) {
 		PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
 	}
 	PR_ExitMonitor(mon);
@@ -391,71 +480,116 @@ File_Rdwr_Param *fparamp;
 	offset = 0;
 	len = CHUNK_SIZE;
 	PR_EnterMonitor(mon);
 	for (i = 0; i < NUM_RDWR_THREADS; i++) {
 		fparamp = PR_NEW(File_Rdwr_Param);
 		if (fparamp == NULL) {
 			printf(
 			"testfile failed to alloc File_Rdwr_Param struct\n");
-			return -1;
+			rv =  -1;
+			goto cleanup;	
 		}
 		fparamp->pathname = pathname;
 		fparamp->buf = in_buf->data + offset;
 		fparamp->offset = offset;
 		fparamp->len = len;
-		/*
-		 * Create LOCAL and GLOBAL Threads, alternately
-		 */
-		if (i % 1)
-			scope = PR_LOCAL_THREAD;
-		else
-			scope = PR_GLOBAL_THREAD;
 
-		t = PR_CreateThread(PR_USER_THREAD,
+		t = create_new_thread(PR_USER_THREAD,
 			      File_Read, (void *)fparamp, 
 			      PR_PRIORITY_NORMAL,
 			      scope,
 			      PR_UNJOINABLE_THREAD,
-			      0);
+			      0, i);
 		offset += len;
 		if ((offset + len) > BUF_DATA_SIZE)
 			break;
 	}
 	thread_count = i;
 
 	/* Wait for reader threads to exit */
 	while (thread_count) {
 		PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
 	}
 	PR_ExitMonitor(mon);
 
 	if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
 		printf("File Test failed: file data corrupted\n");
+		rv =  -1;
+		goto cleanup;	
 	}
 
 	if ((PR_Delete(pathname)) < 0) {
 		printf("testfile failed to unlink file %s\n",pathname);
-		return -1;
+		rv =  -1;
+		goto cleanup;	
 	}
 
 	/*
 	 * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
 	 */
-	Misc_File_Tests(pathname);
+	if (Misc_File_Tests(pathname) < 0) {
+		rv = -1;
+	}
 
+cleanup:
 	if ((PR_RmDir(TEST_DIR)) < 0) {
 		printf("testfile failed to rmdir %s\n", TEST_DIR);
+		rv = -1;
+	}
+	return rv;
+}
+
+struct dirtest_arg {
+	PRMonitor	*mon;
+	PRInt32		done;
+};
+
+static PRInt32 RunDirTest(void)
+{
+int i;
+PRThread *t;
+PRMonitor *mon;
+struct dirtest_arg thrarg;
+
+	mon = PR_NewMonitor();
+	if (!mon) {
+		printf("RunDirTest: Error - failed to create monitor\n");
+		dirtest_failed = 1;
 		return -1;
 	}
+	thrarg.mon = mon;
+
+	for (i = 0; i < NUM_DIRTEST_THREADS; i++) {
+
+		thrarg.done= 0;
+		t = create_new_thread(PR_USER_THREAD,
+			      DirTest, &thrarg, 
+			      PR_PRIORITY_NORMAL,
+			      PR_LOCAL_THREAD,
+			      PR_UNJOINABLE_THREAD,
+			      0, i);
+		if (!t) {
+			printf("RunDirTest: Error - failed to create thread\n");
+			dirtest_failed = 1;
+			return -1;
+		}
+		PR_EnterMonitor(mon);
+		while (!thrarg.done)
+			PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+		PR_ExitMonitor(mon);
+
+	}
+	PR_DestroyMonitor(mon);
 	return 0;
 }
 
-static PRInt32 PR_CALLBACK DirTest(void)
+static PRInt32 PR_CALLBACK DirTest(void *arg)
 {
+struct dirtest_arg *tinfo = (struct dirtest_arg *) arg;
 PRFileDesc *fd_file;
 PRDir *fd_dir;
 int i;
 int path_len;
 PRDirEntry *dirEntry;
 PRFileInfo info;
 PRInt32 num_files = 0;
 #if defined(XP_PC) && defined(WIN32)
@@ -758,27 +892,34 @@ HANDLE hfile;
     PR_CloseDir(fd_dir);
 
 	if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
 		printf(
 			"testfile failed to rmdir %s [%d, %d]\n",
 			TEST_DIR, PR_GetError(), PR_GetOSError());
 		return -1;
 	}
+	PR_EnterMonitor(tinfo->mon);
+	tinfo->done = 1;
+	PR_Notify(tinfo->mon);
+	PR_ExitMonitor(tinfo->mon);
 
 	return 0;
 }
 /************************************************************************/
 
 /*
  * Test file and directory NSPR APIs
  */
 
 int main(int argc, char **argv)
 {
+#ifdef WIN32
+	PRUint32 len;
+#endif
 #if defined(XP_UNIX) || defined(XP_OS2_EMX)
         int opt;
         extern char *optarg;
 	extern int optind;
 #endif
 #if defined(XP_UNIX) || defined(XP_OS2_EMX)
         while ((opt = getopt(argc, argv, "d")) != EOF) {
                 switch(opt) {
@@ -797,24 +938,35 @@ int main(int argc, char **argv)
 	SetupMacPrintfLog("testfile.log");
 #endif
 
 	mon = PR_NewMonitor();
 	if (mon == NULL) {
 		printf("testfile: PR_NewMonitor failed\n");
 		exit(2);
 	}
+#ifdef WIN32
+	len = GetTempPath(TMPDIR_LEN, testdir);
+	if ((len > 0) && (len < (TMPDIR_LEN - 7))) {
+		/*
+		 * enough space for \prdir
+		 */
+		strcpy((testdir + len),"\prdir");
+		TEST_DIR = testdir;
+		printf("TEST_DIR = %s\n",TEST_DIR);
+	}
+	
+#endif
 
 	if (FileTest() < 0) {
 		printf("File Test failed\n");
 		exit(2);
 	}
 	printf("File Test passed\n");
-
-	if (DirTest() < 0) {
+	if ((RunDirTest() < 0) || dirtest_failed) {
 		printf("Dir Test failed\n");
 		exit(2);
 	}
 	printf("Dir Test passed\n");
 
 	PR_DestroyMonitor(mon);
 	PR_Cleanup();
     return 0;