Bugzilla bug 133659: Merged the latest NSPR fixes from the tip into the NSPRPUB_PRE_4_2_CLIENT_BRANCH
authorwtc%netscape.com
Sun, 31 Mar 2002 17:17:49 +0000
branchNSPRPUB_PRE_4_2_CLIENT_BRANCH
changeset 2318 ed90bbe8f116b06120e92b721f1dbaccf6fa7509
parent 2308 8e9aab5f272ee8526992931750c301c88ecd8dcb
child 2319 8a9cfa515d5c94339edd37571b7d603329d0c5bb
push idunknown
push userunknown
push dateunknown
bugs133659
Bugzilla bug 133659: Merged the latest NSPR fixes from the tip into the NSPRPUB_PRE_4_2_CLIENT_BRANCH. a=asa (on behalf of drivers) for checkin to the mozilla 1.0 trunk.
config/WIN32.mk
configure
configure.in
macbuild/NSPR20PPC.mcp
pr/include/md/_aix.h
pr/include/md/_linux.h
pr/include/md/_nto.h
pr/include/md/_solaris.h
pr/include/md/_unixos.h
pr/include/md/_win95.h
pr/src/md/beos/bnet.c
pr/src/md/os2/os2sock.c
pr/src/md/unix/unix.c
pr/src/md/unix/unix_errors.c
pr/src/md/windows/w95dllmain.c
pr/src/md/windows/w95sock.c
pr/src/md/windows/w95thred.c
pr/src/misc/prtime.c
pr/src/pthreads/Makefile.in
pr/src/pthreads/ptio.c
pr/src/pthreads/ptsynch.c
--- a/config/WIN32.mk
+++ b/config/WIN32.mk
@@ -111,26 +111,16 @@ ifdef PROFILE
 LDFLAGS += -PROFILE -MAP
 DLLFLAGS += -PROFILE -MAP
 endif
 endif
 
 DEFINES += -DWIN32
 
 #
-# On Win95, we use the TlsXXX() interface by default because that
-# allows us to load the NSPR DLL dynamically at run time.
-# If you want to use static thread-local storage (TLS) for better
-# performance, build the NSPR library with USE_STATIC_TLS=1.
-#
-ifeq ($(USE_STATIC_TLS),1)
-DEFINES += -D_PR_USE_STATIC_TLS
-endif
-
-#
 # NSPR uses both fibers and static thread-local storage
 # (i.e., __declspec(thread) variables) on NT.  We need the -GT
 # flag to turn off certain compiler optimizations so that fibers
 # can use static TLS safely.
 #
 # Also, we optimize for Pentium (-G5) on NT.
 #
 ifeq ($(OS_TARGET),WINNT)
--- a/configure
+++ b/configure
@@ -2666,18 +2666,27 @@ ASFLAGS='$(CFLAGS)'
 OS_ARCH=`uname -s | sed -e 's|/|_|g'`
 OS_RELEASE=`uname -r`
 OS_TEST=`uname -m`
 
 if test "$OS_ARCH" = "IRIX64"; then
     OS_ARCH=IRIX
 fi
 
+if test "$OS_ARCH" = "AIX"; then
+    OS_RELEASE=`uname -v`.`uname -r`
+fi
+
+if test "$OS_ARCH" = "FreeBSD"; then
+    OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+fi
+
 if test "$OS_ARCH" = "Linux"; then
     OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+    OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'`
 fi
 
 if test "$OS_ARCH" = "POSIX_for_OpenVMS_AXP"; then
     OS_ARCH=OpenVMS
 fi
 
 #######################################################################
 # Master "Core Components" macros for getting the OS target           #
@@ -2830,27 +2839,27 @@ EOF
 
     cat >> confdefs.h <<\EOF
 #define SYSV 1
 EOF
 
     DSO_LDOPTS='-brtl -bM:SRE -bnoentry -bexpall'
     ac_safe=`echo "sys/atomic_op.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for sys/atomic_op.h""... $ac_c" 1>&6
-echo "configure:2839: checking for sys/atomic_op.h" >&5
+echo "configure:2848: checking for sys/atomic_op.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2844 "configure"
+#line 2853 "configure"
 #include "confdefs.h"
 #include <sys/atomic_op.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2858: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
   eval "ac_cv_header_$ac_safe=yes"
 else
   echo "$ac_err" >&5
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
@@ -3000,36 +3009,36 @@ EOF
     PR_MD_ARCH_DIR=beos
     RESOLVE_LINK_SYMBOLS=1
     case "${target_cpu}" in
     i?86)
         _OPTIMIZE_FLAGS=-O2
         _DEBUG_FLAGS='-gdwarf-2 -O0'
         MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@'
         echo $ac_n "checking for gethostbyaddr in -lbind""... $ac_c" 1>&6
-echo "configure:3009: checking for gethostbyaddr in -lbind" >&5
+echo "configure:3018: checking for gethostbyaddr in -lbind" >&5
 ac_lib_var=`echo bind'_'gethostbyaddr | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-lbind  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3017 "configure"
+#line 3026 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char gethostbyaddr();
 
 int main() {
 gethostbyaddr()
 ; return 0; }
 EOF
-if { (eval echo configure:3028: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3037: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -3782,23 +3791,16 @@ EOF
             LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
             LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
         else
             LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
             LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
         fi
     fi # GNU_CC
 
-    if test -n "$USE_STATIC_TLS"; then
-        cat >> confdefs.h <<\EOF
-#define _PR_USE_STATIC_TLS 1
-EOF
-
-    fi
-
     if test "$OS_TARGET" = "WINNT"; then
         cat >> confdefs.h <<\EOF
 #define WINNT 1
 EOF
 
     else
         cat >> confdefs.h <<\EOF
 #define WIN95 1
@@ -4145,27 +4147,27 @@ EOF
 EOF
 
     cat >> confdefs.h <<\EOF
 #define _REENTRANT 1
 EOF
 
     ac_safe=`echo "machine/builtins.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for machine/builtins.h""... $ac_c" 1>&6
-echo "configure:4154: checking for machine/builtins.h" >&5
+echo "configure:4156: checking for machine/builtins.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4159 "configure"
+#line 4161 "configure"
 #include "confdefs.h"
 #include <machine/builtins.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4164: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
   eval "ac_cv_header_$ac_safe=yes"
 else
   echo "$ac_err" >&5
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
@@ -4670,22 +4672,22 @@ EOF
 
     ;;
    
 esac
 
 if test -z "$SKIP_LIBRARY_CHECKS"; then
 
 echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "configure:4679: checking for dlopen" >&5
+echo "configure:4681: checking for dlopen" >&5
 if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4684 "configure"
+#line 4686 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char dlopen(); below.  */
 #include <assert.h>
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char dlopen();
@@ -4698,17 +4700,17 @@ int main() {
 #if defined (__stub_dlopen) || defined (__stub___dlopen)
 choke me
 #else
 dlopen();
 #endif
 
 ; return 0; }
 EOF
-if { (eval echo configure:4707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_dlopen=yes"
 else
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_func_dlopen=no"
 fi
@@ -4717,36 +4719,36 @@ fi
 
 if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
   echo "$ac_t""yes" 1>&6
   :
 else
   echo "$ac_t""no" 1>&6
 
     echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:4726: checking for dlopen in -ldl" >&5
+echo "configure:4728: checking for dlopen in -ldl" >&5
 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-ldl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4734 "configure"
+#line 4736 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char dlopen();
 
 int main() {
 dlopen()
 ; return 0; }
 EOF
-if { (eval echo configure:4745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -4764,23 +4766,23 @@ fi
 
 fi
 
 
 
 
 if test $ac_cv_prog_gcc = yes; then
     echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:4773: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:4775: checking whether ${CC-cc} needs -traditional" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
     ac_pattern="Autoconf.*'x'"
   cat > conftest.$ac_ext <<EOF
-#line 4779 "configure"
+#line 4781 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   egrep "$ac_pattern" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_prog_gcc_traditional=yes
@@ -4788,17 +4790,17 @@ else
   rm -rf conftest*
   ac_cv_prog_gcc_traditional=no
 fi
 rm -f conftest*
 
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat > conftest.$ac_ext <<EOF
-#line 4797 "configure"
+#line 4799 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   egrep "$ac_pattern" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_prog_gcc_traditional=yes
@@ -4812,22 +4814,22 @@ echo "$ac_t""$ac_cv_prog_gcc_traditional
   if test $ac_cv_prog_gcc_traditional = yes; then
     CC="$CC -traditional"
   fi
 fi
 
 for ac_func in lchown strerror
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4821: checking for $ac_func" >&5
+echo "configure:4823: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4826 "configure"
+#line 4828 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
 #include <assert.h>
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char $ac_func();
@@ -4840,17 +4842,17 @@ int main() {
 #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
 choke me
 #else
 $ac_func();
 #endif
 
 ; return 0; }
 EOF
-if { (eval echo configure:4849: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
   echo "configure: failed program was:" >&5
   cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=no"
 fi
@@ -4878,17 +4880,17 @@ if test "${enable_strip+set}" = set; the
    ENABLE_STRIP=1 
 fi
 
 
 
 
 
 echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6
-echo "configure:4887: checking for pthread_create in -lpthreads" >&5
+echo "configure:4889: checking for pthread_create in -lpthreads" >&5
 echo "
     #include <pthread.h> 
     void *foo(void *v) { int a = 1;  } 
     int main() { 
         pthread_t t;
         if (!pthread_create(&t, 0, &foo, 0)) {
             pthread_join(t, 0);
         }
@@ -4900,17 +4902,17 @@ echo "
     rm -f dummy.c dummy${ac_exeext} ;
     if test "$_res" = "0"; then
         echo "$ac_t""yes" 1>&6
         _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads"
     else
         echo "$ac_t""no" 1>&6
         
 echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
-echo "configure:4909: checking for pthread_create in -lpthread" >&5
+echo "configure:4911: checking for pthread_create in -lpthread" >&5
 echo "
     #include <pthread.h> 
     void *foo(void *v) { int a = 1;  } 
     int main() { 
         pthread_t t;
         if (!pthread_create(&t, 0, &foo, 0)) {
             pthread_join(t, 0);
         }
@@ -4922,17 +4924,17 @@ echo "
     rm -f dummy.c dummy${ac_exeext} ;
     if test "$_res" = "0"; then
         echo "$ac_t""yes" 1>&6
         _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread"
     else
         echo "$ac_t""no" 1>&6
         
 echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
-echo "configure:4931: checking for pthread_create in -lc_r" >&5
+echo "configure:4933: checking for pthread_create in -lc_r" >&5
 echo "
     #include <pthread.h> 
     void *foo(void *v) { int a = 1;  } 
     int main() { 
         pthread_t t;
         if (!pthread_create(&t, 0, &foo, 0)) {
             pthread_join(t, 0);
         }
@@ -4944,17 +4946,17 @@ echo "
     rm -f dummy.c dummy${ac_exeext} ;
     if test "$_res" = "0"; then
         echo "$ac_t""yes" 1>&6
         _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r"
     else
         echo "$ac_t""no" 1>&6
         
 echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6
-echo "configure:4953: checking for pthread_create in -lc" >&5
+echo "configure:4955: checking for pthread_create in -lc" >&5
 echo "
     #include <pthread.h> 
     void *foo(void *v) { int a = 1;  } 
     int main() { 
         pthread_t t;
         if (!pthread_create(&t, 0, &foo, 0)) {
             pthread_join(t, 0);
         }
@@ -5094,17 +5096,17 @@ EOF
     fi
 fi
 
 
 if test -n "$USE_PTHREADS"; then
       rm -f conftest*
    ac_cv_have_dash_pthread=no
    echo $ac_n "checking whether ${CC-cc} accepts -pthread""... $ac_c" 1>&6
-echo "configure:5103: checking whether ${CC-cc} accepts -pthread" >&5
+echo "configure:5105: checking whether ${CC-cc} accepts -pthread" >&5
    echo 'int main() { return 0; }' | cat > conftest.c
    ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1
    if test $? -eq 0; then
 	if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
 	    ac_cv_have_dash_pthread=yes
 		case "$target_os" in
 	    freebsd*)
 # Freebsd doesn't use -pthread for compiles, it uses them for linking
@@ -5117,17 +5119,17 @@ echo "configure:5103: checking whether $
 	fi
     fi
     rm -f conftest*
     echo "$ac_t""$ac_cv_have_dash_pthread" 1>&6
 
 			    ac_cv_have_dash_pthreads=no
     if test "$ac_cv_have_dash_pthread" = "no"; then
 	    echo $ac_n "checking whether ${CC-cc} accepts -pthreads""... $ac_c" 1>&6
-echo "configure:5126: checking whether ${CC-cc} accepts -pthreads" >&5
+echo "configure:5128: checking whether ${CC-cc} accepts -pthreads" >&5
     	echo 'int main() { return 0; }' | cat > conftest.c
 	    ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1
     	if test $? -eq 0; then
 	    	if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
 			    ac_cv_have_dash_pthreads=yes
 			    CFLAGS="$CFLAGS -pthreads"
 			    CXXFLAGS="$CXXFLAGS -pthreads"
 		    fi
--- a/configure.in
+++ b/configure.in
@@ -504,18 +504,27 @@ ASFLAGS='$(CFLAGS)'
 OS_ARCH=`uname -s | sed -e 's|/|_|g'`
 OS_RELEASE=`uname -r`
 OS_TEST=`uname -m`
 
 if test "$OS_ARCH" = "IRIX64"; then
     OS_ARCH=IRIX
 fi
 
+if test "$OS_ARCH" = "AIX"; then
+    OS_RELEASE=`uname -v`.`uname -r`
+fi
+
+if test "$OS_ARCH" = "FreeBSD"; then
+    OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+fi
+
 if test "$OS_ARCH" = "Linux"; then
     OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+    OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'`
 fi
 
 if test "$OS_ARCH" = "POSIX_for_OpenVMS_AXP"; then
     OS_ARCH=OpenVMS
 fi
 
 #######################################################################
 # Master "Core Components" macros for getting the OS target           #
@@ -1233,20 +1242,16 @@ case "$target" in
             LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
             LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
         else
             LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
             LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
         fi
     fi # GNU_CC
 
-    if test -n "$USE_STATIC_TLS"; then
-        AC_DEFINE(_PR_USE_STATIC_TLS)
-    fi
-
     if test "$OS_TARGET" = "WINNT"; then
         AC_DEFINE(WINNT)
     else
         AC_DEFINE(WIN95)
         AC_DEFINE(_PR_GLOBAL_THREADS_ONLY)
     fi
 
     if test "$CPU_ARCH" = "x86"; then
deleted file mode 100644
index ee949c268029e695628bdcacd0efa9b0ad21bd9d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -238,9 +238,11 @@ struct _MDCPU {
 #define _MD_CLEAN_THREAD(_thread)
 #endif /* PTHREADS_USER */
 
 #ifdef AIX_RENAME_SELECT
 #define _MD_SELECT	select
 #define _MD_POLL	poll
 #endif
 
+extern void _MD_aix_map_sendfile_error(int err);
+
 #endif /* nspr_aix_defs_h___ */
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -465,9 +465,11 @@ extern PRIntervalTime _PR_UNIX_TicksPerS
 extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds,
 	int timeout);
 #define _MD_POLL __syscall_poll
 #endif
 
 /* For writev() */
 #include <sys/uio.h>
 
+extern void _MD_linux_map_sendfile_error(int err);
+
 #endif /* nspr_linux_defs_h___ */
--- a/pr/include/md/_nto.h
+++ b/pr/include/md/_nto.h
@@ -207,9 +207,11 @@ struct _MDCPU {
 #define _MD_CLEAN_THREAD(_thread)
 
 /*
 ** We wrapped the select() call.  _MD_SELECT refers to the built-in,
 ** unwrapped version.
 */
 #define _MD_SELECT		select
 
+#define SA_RESTART 0
+
 #endif /* nspr_nto_defs_h___ */
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -779,10 +779,12 @@ PR_BEGIN_EXTERN_C
 ** Missing function prototypes
 */
 extern int gethostname (char *name, int namelen);
 
 PR_END_EXTERN_C
 
 #endif /* _PR_GLOBAL_THREADS_ONLY */
 
+extern void _MD_solaris_map_sendfile_error(int err);
+
 #endif /* nspr_solaris_defs_h___ */
 
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -140,16 +140,19 @@ extern void _PR_Unblock_IO_Wait(struct P
 
 extern fd_set _pr_md_read_set, _pr_md_write_set, _pr_md_exception_set;
 extern PRInt16 _pr_md_read_cnt[], _pr_md_write_cnt[], _pr_md_exception_cnt[];
 extern PRInt32 _pr_md_ioq_max_osfd;
 extern PRUint32 _pr_md_ioq_timeout;
 
 struct _MDFileDesc {
     int osfd;
+#if defined(LINUX) && defined(_PR_PTHREADS)
+    int tcp_nodelay;  /* used by pt_LinuxSendFile */
+#endif
 };
 
 struct _MDDir {
 	DIR *d;
 };
 
 struct _PRCPU;
 extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu);
--- a/pr/include/md/_win95.h
+++ b/pr/include/md/_win95.h
@@ -404,41 +404,65 @@ extern PRStatus _PR_KillWindowsProcess(s
 #define _MD_INTERVAL_PER_SEC              _PR_MD_INTERVAL_PER_SEC
 #define _MD_INTERVAL_PER_MILLISEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000)
 #define _MD_INTERVAL_PER_MICROSEC()       (_PR_MD_INTERVAL_PER_SEC() / 1000000)
 
 /* --- Native-Thread Specific Definitions ------------------------------- */
 
 extern struct PRThread * _MD_CURRENT_THREAD(void);
 
-#ifdef _PR_USE_STATIC_TLS
+extern BOOL _pr_use_static_tls;
+
 extern __declspec(thread) struct PRThread *_pr_currentThread;
-#define _MD_GET_ATTACHED_THREAD() _pr_currentThread
-#define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
+extern DWORD _pr_currentThreadIndex;
+
+#define _MD_GET_ATTACHED_THREAD() \
+    (_pr_use_static_tls ? _pr_currentThread \
+    : (PRThread *) TlsGetValue(_pr_currentThreadIndex))
+
+#define _MD_SET_CURRENT_THREAD(_thread) \
+    PR_BEGIN_MACRO \
+        if (_pr_use_static_tls) { \
+            _pr_currentThread = (_thread); \
+        } else { \
+            TlsSetValue(_pr_currentThreadIndex, (_thread)); \
+        } \
+    PR_END_MACRO
 
 extern __declspec(thread) struct PRThread *_pr_thread_last_run;
-#define _MD_LAST_THREAD() _pr_thread_last_run
-#define _MD_SET_LAST_THREAD(_thread) (_pr_thread_last_run = 0)
+extern DWORD _pr_lastThreadIndex;
+
+#define _MD_LAST_THREAD() \
+    (_pr_use_static_tls ? _pr_thread_last_run \
+    : (PRThread *) TlsGetValue(_pr_lastThreadIndex))
+
+#define _MD_SET_LAST_THREAD(_thread) \
+    PR_BEGIN_MACRO \
+        if (_pr_use_static_tls) { \
+            _pr_thread_last_run = 0; \
+        } else { \
+            TlsSetValue(_pr_lastThreadIndex, 0); \
+        } \
+    PR_END_MACRO
 
 extern __declspec(thread) struct _PRCPU *_pr_currentCPU;
-#define _MD_CURRENT_CPU() _pr_currentCPU
-#define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = 0)
-#else /* _PR_USE_STATIC_TLS */
-extern DWORD _pr_currentThreadIndex;
-#define _MD_GET_ATTACHED_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex))
-#define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentThreadIndex, (_thread))
+extern DWORD _pr_currentCPUIndex;
+
+#define _MD_CURRENT_CPU() \
+    (_pr_use_static_tls ? _pr_currentCPU \
+    : (struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
 
-extern DWORD _pr_lastThreadIndex;
-#define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastThreadIndex))
-#define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastThreadIndex, 0)
-
-extern DWORD _pr_currentCPUIndex;
-#define _MD_CURRENT_CPU() ((struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
-#define _MD_SET_CURRENT_CPU(_cpu) TlsSetValue(_pr_currentCPUIndex, 0)
-#endif /* _PR_USE_STATIC_TLS */
+#define _MD_SET_CURRENT_CPU(_cpu) \
+    PR_BEGIN_MACRO \
+        if (_pr_use_static_tls) { \
+            _pr_currentCPU = 0; \
+        } else { \
+            TlsSetValue(_pr_currentCPUIndex, 0); \
+        } \
+    PR_END_MACRO
 
 /* --- Scheduler stuff --- */
 #define LOCK_SCHEDULER()                 0
 #define UNLOCK_SCHEDULER()               0
 #define _PR_LockSched()                	 0
 #define _PR_UnlockSched()                0
 
 /* --- Initialization stuff --- */
--- a/pr/src/md/beos/bnet.c
+++ b/pr/src/md/beos/bnet.c
@@ -75,16 +75,17 @@ static PRMonitor *_pr_Xfe_mon = NULL;
 
 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
                               PRIntervalTime timeout)
 {
     PRInt32 rv = -1;
     struct timeval tv;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime epoch, now, elapsed, remaining;
+    PRBool wait_for_remaining;
     PRInt32 syserror;
     fd_set rd_wr;
 
     switch (timeout) {
     case PR_INTERVAL_NO_WAIT:
         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
         break;
     case PR_INTERVAL_NO_TIMEOUT:
@@ -127,18 +128,20 @@ static PRInt32 socket_io_wait(PRInt32 os
         FD_ZERO(&rd_wr);
         do {
             /*
              * We block in _MD_SELECT for at most
              * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
              * so that there is an upper limit on the delay
              * before the interrupt bit is checked.
              */
+            wait_for_remaining = PR_TRUE;
             tv.tv_sec = PR_IntervalToSeconds(remaining);
             if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+                wait_for_remaining = PR_FALSE;
                 tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
                 tv.tv_usec = 0;
             } else {
                 tv.tv_usec = PR_IntervalToMicroseconds(
                                  remaining -
                                  PR_SecondsToInterval(tv.tv_sec));
             }
             FD_SET(osfd, &rd_wr);
@@ -173,18 +176,22 @@ static PRInt32 socket_io_wait(PRInt32 os
              */
             if (rv == 0 || (rv == -1 && syserror == EINTR)) {
                 /*
                  * If _MD_SELECT timed out, we know how much time
                  * we spent in blocking, so we can avoid a
                  * PR_IntervalNow() call.
                  */
                 if (rv == 0) {
-                    now += PR_SecondsToInterval(tv.tv_sec)
-                           + PR_MicrosecondsToInterval(tv.tv_usec);
+                    if (wait_for_remaining) {
+                        now += remaining;
+                    } else {
+                        now += PR_SecondsToInterval(tv.tv_sec)
+                               + PR_MicrosecondsToInterval(tv.tv_usec);
+                    }
                 } else {
                     now = PR_IntervalNow();
                 }
                 elapsed = (PRIntervalTime) (now - epoch);
                 if (elapsed >= timeout) {
                     PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
                     rv = -1;
                     break;
--- a/pr/src/md/os2/os2sock.c
+++ b/pr/src/md/os2/os2sock.c
@@ -108,16 +108,17 @@ PRInt32
 }
 
 static PRInt32
 socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
 {
     PRInt32 rv = -1;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime epoch, now, elapsed, remaining;
+    PRBool wait_for_remaining;
     PRInt32 syserror;
 #ifdef BSD_SELECT
     struct timeval tv;
     fd_set rd_wr;
 #else
     int socks[1];
     long lTimeout;
 #endif
@@ -171,34 +172,39 @@ socket_io_wait( PRInt32 osfd, PRInt32 fd
             do {
                 /*
                  * We block in _MD_SELECT for at most
                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
                  * so that there is an upper limit on the delay
                  * before the interrupt bit is checked.
                  */
 #ifdef BSD_SELECT
+                wait_for_remaining = PR_TRUE;
                 tv.tv_sec = PR_IntervalToSeconds(remaining);
                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+                    wait_for_remaining = PR_FALSE;
                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
                     tv.tv_usec = 0;
                 } else {
                     tv.tv_usec = PR_IntervalToMicroseconds(
                         remaining -
                         PR_SecondsToInterval(tv.tv_sec));
                 }
                 FD_SET(osfd, &rd_wr);
                 if (fd_type == READ_FD)
                     rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
                 else
                     rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
 #else
+                wait_for_remaining = PR_TRUE;
                 lTimeout = PR_IntervalToMilliseconds(remaining);
-                if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000)
+                if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+                    wait_for_remaining = PR_FALSE;
                     lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+                }
                 socks[0] = osfd;
                 if (fd_type == READ_FD)
                     rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
                 else
                     rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
 #endif
                 /*
                  * we don't consider EINTR a real error
@@ -219,22 +225,26 @@ socket_io_wait( PRInt32 osfd, PRInt32 fd
                  */
                 if (rv == 0 || (rv == -1 && syserror == SOCEINTR)) {
                     /*
                      * If _MD_SELECT timed out, we know how much time
                      * we spent in blocking, so we can avoid a
                      * PR_IntervalNow() call.
                      */
                     if (rv == 0) {
+                        if (wait_for_remaining) {
+                            now += remaining;
+                        } else {
 #ifdef BSD_SELECT
-                        now += PR_SecondsToInterval(tv.tv_sec)
-                            + PR_MicrosecondsToInterval(tv.tv_usec);
+                            now += PR_SecondsToInterval(tv.tv_sec)
+                                + PR_MicrosecondsToInterval(tv.tv_usec);
 #else
-                        now += PR_MillisecondsToInterval(lTimeout);
+                            now += PR_MillisecondsToInterval(lTimeout);
 #endif
+                        }
                     } else {
                         now = PR_IntervalNow();
                     }
                     elapsed = (PRIntervalTime) (now - epoch);
                     if (elapsed >= timeout) {
                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
                         rv = -1;
                         break;
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -509,16 +509,17 @@ PRInt64 _MD_socketavailable64(PRFileDesc
 
 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
     PRIntervalTime timeout)
 {
     PRInt32 rv = -1;
     struct timeval tv;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime epoch, now, elapsed, remaining;
+    PRBool wait_for_remaining;
     PRInt32 syserror;
     fd_set rd_wr;
 
     switch (timeout) {
         case PR_INTERVAL_NO_WAIT:
             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
             break;
         case PR_INTERVAL_NO_TIMEOUT:
@@ -553,18 +554,20 @@ static PRInt32 socket_io_wait(PRInt32 os
             FD_ZERO(&rd_wr);
             do {
                 /*
                  * We block in _MD_SELECT for at most
                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
                  * so that there is an upper limit on the delay
                  * before the interrupt bit is checked.
                  */
+                wait_for_remaining = PR_TRUE;
                 tv.tv_sec = PR_IntervalToSeconds(remaining);
                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+                    wait_for_remaining = PR_FALSE;
                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
                     tv.tv_usec = 0;
                 } else {
                     tv.tv_usec = PR_IntervalToMicroseconds(
                         remaining -
                         PR_SecondsToInterval(tv.tv_sec));
                 }
                 FD_SET(osfd, &rd_wr);
@@ -591,18 +594,22 @@ static PRInt32 socket_io_wait(PRInt32 os
                  */
                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
                     /*
                      * If _MD_SELECT timed out, we know how much time
                      * we spent in blocking, so we can avoid a
                      * PR_IntervalNow() call.
                      */
                     if (rv == 0) {
-                        now += PR_SecondsToInterval(tv.tv_sec)
-                            + PR_MicrosecondsToInterval(tv.tv_usec);
+                        if (wait_for_remaining) {
+                            now += remaining;
+                        } else {
+                            now += PR_SecondsToInterval(tv.tv_sec)
+                                + PR_MicrosecondsToInterval(tv.tv_usec);
+                        }
                     } else {
                         now = PR_IntervalNow();
                     }
                     elapsed = (PRIntervalTime) (now - epoch);
                     if (elapsed >= timeout) {
                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
                         rv = -1;
                         break;
@@ -620,16 +627,17 @@ static PRInt32 socket_io_wait(PRInt32 os
 
 static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
     PRIntervalTime timeout)
 {
     PRInt32 rv = -1;
     int msecs;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime epoch, now, elapsed, remaining;
+    PRBool wait_for_remaining;
     PRInt32 syserror;
     struct pollfd pfd;
 
     switch (timeout) {
         case PR_INTERVAL_NO_WAIT:
             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
             break;
         case PR_INTERVAL_NO_TIMEOUT:
@@ -677,18 +685,20 @@ static PRInt32 socket_io_wait(PRInt32 os
             }
             do {
                 /*
                  * We block in _MD_POLL for at most
                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
                  * so that there is an upper limit on the delay
                  * before the interrupt bit is checked.
                  */
+                wait_for_remaining = PR_TRUE;
                 msecs = PR_IntervalToMilliseconds(remaining);
                 if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+                    wait_for_remaining = PR_FALSE;
                     msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
                 }
                 rv = _MD_POLL(&pfd, 1, msecs);
                 /*
                  * we don't consider EINTR a real error
                  */
                 if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
                     _PR_MD_MAP_POLL_ERROR(syserror);
@@ -714,17 +724,21 @@ static PRInt32 socket_io_wait(PRInt32 os
                  */
                 if (rv == 0 || (rv == -1 && syserror == EINTR)) {
                     /*
                      * If _MD_POLL timed out, we know how much time
                      * we spent in blocking, so we can avoid a
                      * PR_IntervalNow() call.
                      */
                     if (rv == 0) {
-                        now += PR_MillisecondsToInterval(msecs);
+                        if (wait_for_remaining) {
+                            now += remaining;
+                        } else {
+                            now += PR_MillisecondsToInterval(msecs);
+                        }
                     } else {
                         now = PR_IntervalNow();
                     }
                     elapsed = (PRIntervalTime) (now - epoch);
                     if (elapsed >= timeout) {
                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
                         rv = -1;
                         break;
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -842,8 +842,15 @@ void _MD_hpux_map_sendfile_error(int err
 #endif /* HPUX11 */
 
 #ifdef SOLARIS
 void _MD_solaris_map_sendfile_error(int err)
 {
     _MD_unix_map_default_error(err) ;
 }
 #endif /* SOLARIS */
+
+#ifdef LINUX
+void _MD_linux_map_sendfile_error(int err)
+{
+    _MD_unix_map_default_error(err) ;
+}
+#endif /* LINUX */
--- a/pr/src/md/windows/w95dllmain.c
+++ b/pr/src/md/windows/w95dllmain.c
@@ -31,31 +31,48 @@
  * may use your version of this file under either the MPL or the
  * GPL.
  */
 
 /*
  * The DLL entry point (DllMain) for NSPR.
  *
  * This is used to detach threads that were automatically attached by
- * nspr.
+ * nspr and to find out whether the NSPR DLL is statically or
+ * dynamically loaded.  When dynamically loaded, we cannot use static
+ * thread-local storage.  However, static TLS is faster than the
+ * TlsXXX() functions.  So we want to use static TLS whenever we can.
+ * A global variable _pr_use_static_tls is set in DllMain() during
+ * process attachment to indicate whether it is safe to use static
+ * TLS or not.
  */
 
 #include <windows.h>
 #include <primpl.h>
 
+extern BOOL _pr_use_static_tls;  /* defined in w95thred.c */
+
 BOOL WINAPI DllMain(
     HINSTANCE hinstDLL,
     DWORD fdwReason,
     LPVOID lpvReserved)
 {
 PRThread *me;
 
     switch (fdwReason) {
         case DLL_PROCESS_ATTACH:
+            /*
+             * If lpvReserved is NULL, we are dynamically loaded
+             * and therefore can't use static thread-local storage.
+             */
+            if (lpvReserved == NULL) {
+                _pr_use_static_tls = FALSE;
+            } else {
+                _pr_use_static_tls = TRUE;
+            }
             break;
         case DLL_THREAD_ATTACH:
             break;
         case DLL_THREAD_DETACH:
             if (_pr_initialized) {
                 me = _MD_GET_ATTACHED_THREAD();
                 if ((me != NULL) && (me->flags & _PR_ATTACHED))
                     _PRI_DetachThread();
--- a/pr/src/md/windows/w95sock.c
+++ b/pr/src/md/windows/w95sock.c
@@ -469,16 +469,17 @@ static PRInt32 socket_io_wait(
     PRInt32 osfd, 
     PRInt32 fd_type,
     PRIntervalTime timeout)
 {
     PRInt32 rv = -1;
     struct timeval tv;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRIntervalTime elapsed, remaining;
+    PRBool wait_for_remaining;
     fd_set rd_wr, ex;
     int err, len;
 
     switch (timeout) {
         case PR_INTERVAL_NO_WAIT:
             PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
             break;
         case PR_INTERVAL_NO_TIMEOUT:
@@ -555,18 +556,20 @@ static PRInt32 socket_io_wait(
             FD_ZERO(&ex);
             do {
                 /*
                  * We block in _MD_SELECT for at most
                  * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
                  * so that there is an upper limit on the delay
                  * before the interrupt bit is checked.
                  */
+                wait_for_remaining = PR_TRUE;
                 tv.tv_sec = PR_IntervalToSeconds(remaining);
                 if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+                    wait_for_remaining = PR_FALSE;
                     tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
                     tv.tv_usec = 0;
                 } else {
                     tv.tv_usec = PR_IntervalToMicroseconds(
                         remaining -
                         PR_SecondsToInterval(tv.tv_sec));
                 }
                 FD_SET(osfd, &rd_wr);
@@ -626,18 +629,22 @@ static PRInt32 socket_io_wait(
                     break;
                 }
                 /*
                  * We loop again if _MD_SELECT timed out and the
                  * timeout deadline has not passed yet.
                  */
                 if (rv == 0 )
                 {
-                    elapsed = PR_SecondsToInterval(tv.tv_sec) 
-                                + PR_MicrosecondsToInterval(tv.tv_usec);
+                    if (wait_for_remaining) {
+                        elapsed = remaining;
+                    } else {
+                        elapsed = PR_SecondsToInterval(tv.tv_sec) 
+                                    + PR_MicrosecondsToInterval(tv.tv_usec);
+                    }
                     if (elapsed >= remaining) {
                         PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
                         rv = -1;
                         break;
                     } else {
                         remaining = remaining - elapsed;
                     }
                 }
--- a/pr/src/md/windows/w95thred.c
+++ b/pr/src/md/windows/w95thred.c
@@ -33,51 +33,49 @@
  */
 
 #include "primpl.h"
 #include <process.h>  /* for _beginthreadex() */
 
 extern void _PR_Win32InitTimeZone(void);  /* defined in ntmisc.c */
 
 /* --- globals ------------------------------------------------ */
-#ifdef _PR_USE_STATIC_TLS
+BOOL _pr_use_static_tls = TRUE;
 __declspec(thread) struct PRThread  *_pr_thread_last_run;
 __declspec(thread) struct PRThread  *_pr_currentThread;
 __declspec(thread) struct _PRCPU    *_pr_currentCPU;
-#else
 DWORD _pr_currentThreadIndex;
 DWORD _pr_lastThreadIndex;
 DWORD _pr_currentCPUIndex;
-#endif
 int                           _pr_intsOff = 0; 
 _PRInterruptTable             _pr_interruptTable[] = { { 0 } };
 
 void
 _PR_MD_EARLY_INIT()
 {
     _PR_Win32InitTimeZone();
 
-#ifndef _PR_USE_STATIC_TLS
-    _pr_currentThreadIndex = TlsAlloc();
-    _pr_lastThreadIndex = TlsAlloc();
-    _pr_currentCPUIndex = TlsAlloc();
-#endif
+    if (!_pr_use_static_tls) {
+        _pr_currentThreadIndex = TlsAlloc();
+        _pr_lastThreadIndex = TlsAlloc();
+        _pr_currentCPUIndex = TlsAlloc();
+    }
 }
 
 void _PR_MD_CLEANUP_BEFORE_EXIT(void)
 {
     _PR_NT_FreeSids();
 
     WSACleanup();
 
-#ifndef _PR_USE_STATIC_TLS
-    TlsFree(_pr_currentThreadIndex);
-    TlsFree(_pr_lastThreadIndex);
-    TlsFree(_pr_currentCPUIndex);
-#endif
+    if (!_pr_use_static_tls) {
+        TlsFree(_pr_currentThreadIndex);
+        TlsFree(_pr_lastThreadIndex);
+        TlsFree(_pr_currentCPUIndex);
+    }
 }
 
 PRStatus
 _PR_MD_INIT_THREAD(PRThread *thread)
 {
     if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
         /*
         ** Warning:
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -769,94 +769,94 @@ PR_LocalTimeParameters(const PRExplodedT
  *
  *------------------------------------------------------------------------
  */
 
 PR_IMPLEMENT(PRTimeParameters)
 PR_USPacificTimeParameters(const PRExplodedTime *gmt)
 {
     PRTimeParameters retVal;
-    PRExplodedTime std;
+    PRExplodedTime st;
 
     /*
      * Based on geographic location and GMT, figure out offset of
      * standard time from GMT.  In this example implementation, we
      * assume the local time zone is US Pacific Time.
      */
 
     retVal.tp_gmt_offset = -8L * 3600L;
 
     /*
      * Make a copy of GMT.  Note that the tm_params field of this copy
      * is ignored.
      */
 
-    std.tm_usec = gmt->tm_usec;
-    std.tm_sec = gmt->tm_sec;
-    std.tm_min = gmt->tm_min;
-    std.tm_hour = gmt->tm_hour;
-    std.tm_mday = gmt->tm_mday;
-    std.tm_month = gmt->tm_month;
-    std.tm_year = gmt->tm_year;
-    std.tm_wday = gmt->tm_wday;
-    std.tm_yday = gmt->tm_yday;
+    st.tm_usec = gmt->tm_usec;
+    st.tm_sec = gmt->tm_sec;
+    st.tm_min = gmt->tm_min;
+    st.tm_hour = gmt->tm_hour;
+    st.tm_mday = gmt->tm_mday;
+    st.tm_month = gmt->tm_month;
+    st.tm_year = gmt->tm_year;
+    st.tm_wday = gmt->tm_wday;
+    st.tm_yday = gmt->tm_yday;
 
     /* Apply the offset to GMT to obtain the local standard time */
-    ApplySecOffset(&std, retVal.tp_gmt_offset);
+    ApplySecOffset(&st, retVal.tp_gmt_offset);
 
     /*
      * Apply the rules on standard time or GMT to obtain daylight saving
      * time offset.  In this implementation, we use the US DST rule.
      */
-    if (std.tm_month < 3) {
+    if (st.tm_month < 3) {
         retVal.tp_dst_offset = 0L;
-    } else if (std.tm_month == 3) {
-        if (std.tm_wday == 0) {
+    } else if (st.tm_month == 3) {
+        if (st.tm_wday == 0) {
             /* A Sunday */
-            if (std.tm_mday <= 7) {
+            if (st.tm_mday <= 7) {
                 /* First Sunday */
                 /* 01:59:59 PST -> 03:00:00 PDT */
-                if (std.tm_hour < 2) {
+                if (st.tm_hour < 2) {
                     retVal.tp_dst_offset = 0L;
                 } else {
                     retVal.tp_dst_offset = 3600L;
                 }
             } else {
                 /* Not first Sunday */
                 retVal.tp_dst_offset = 3600L;
             }
         } else {
             /* Not a Sunday.  See if before first Sunday or after */
-            if (std.tm_wday + 1 <= std.tm_mday) {
+            if (st.tm_wday + 1 <= st.tm_mday) {
                 /* After first Sunday */
                 retVal.tp_dst_offset = 3600L;
             } else {
                 /* Before first Sunday */
                 retVal.tp_dst_offset = 0L;
             } 
         }
-    } else if (std.tm_month < 9) {
+    } else if (st.tm_month < 9) {
         retVal.tp_dst_offset = 3600L;
-    } else if (std.tm_month == 9) {
-        if (std.tm_wday == 0) {
-            if (31 - std.tm_mday < 7) {
+    } else if (st.tm_month == 9) {
+        if (st.tm_wday == 0) {
+            if (31 - st.tm_mday < 7) {
                 /* Last Sunday */
                 /* 01:59:59 PDT -> 01:00:00 PST */
-                if (std.tm_hour < 1) {
+                if (st.tm_hour < 1) {
                     retVal.tp_dst_offset = 3600L;
                 } else {
                     retVal.tp_dst_offset = 0L;
                 }
             } else {
                 /* Not last Sunday */
                 retVal.tp_dst_offset = 3600L;
             }
         } else {
             /* See if before or after last Sunday */
-            if (7 - std.tm_wday <= 31 - std.tm_mday) {
+            if (7 - st.tm_wday <= 31 - st.tm_mday) {
                 /* before last Sunday */
                 retVal.tp_dst_offset = 3600L;
             } else {
                 retVal.tp_dst_offset = 0L;
             }
         }
     } else {
         retVal.tp_dst_offset = 0L;
--- a/pr/src/pthreads/Makefile.in
+++ b/pr/src/pthreads/Makefile.in
@@ -58,13 +58,18 @@ CSRCS = \
 	$(NULL)
 
 TARGETS	= $(OBJS)
 
 INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
 
 DEFINES	+= -D_NSPR_BUILD_
 
+ifeq ($(OS_ARCH),Linux)
+# for pthread_mutexattr_settype
+DEFINES += -D_XOPEN_SOURCE=500
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 export:: $(TARGETS)
 
 
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -168,21 +168,31 @@ struct sf_parms {
  */
 static ssize_t (*pt_aix_sendfile_fptr)() = NULL;
 
 #define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)
 
 #endif /* HAVE_SEND_FILE */
 #endif /* AIX */
 
+#ifdef LINUX
+#include <sys/sendfile.h>
+#endif
+
 #include "primpl.h"
 
 /* On Alpha Linux, these are already defined in sys/socket.h */
 #if !(defined(LINUX) && defined(__alpha))
 #include <netinet/tcp.h>  /* TCP_NODELAY, TCP_MAXSEG */
+#ifdef LINUX
+/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */
+#ifndef TCP_CORK
+#define TCP_CORK 3
+#endif
+#endif
 #endif
 
 #if defined(SOLARIS)
 #define _PRSockOptVal_t char *
 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \
     || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS) \
     || defined(NTO) || defined(OPENBSD) || defined(DARWIN) \
     || defined(UNIXWARE)
@@ -333,16 +343,25 @@ struct pt_Continuation
 #endif  /* HPUX11 */
     
 #ifdef SOLARIS
     /*
      * For sendfilev()
      */
     int nbytes_to_send;                     /* size of header and file */
 #endif  /* SOLARIS */
+
+#ifdef LINUX
+    /*
+     * For sendfile()
+     */
+    int in_fd;                              /* descriptor of file to send */
+    off_t offset;
+    size_t count;
+#endif  /* LINUX */
  
     PRIntervalTime timeout;                 /* client (relative) timeout */
 
     PRInt16 event;                           /* flags for poll()'s events */
 
     /*
     ** The representation and notification of the results of the operation.
     ** These function can either return an int return code or a pointer to
@@ -401,16 +420,17 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFile
  * workaround this problem.
  */
 static void pt_poll_now_with_select(pt_Continuation *op)
 {
     PRInt32 msecs;
 	fd_set rd, wr, *rdp, *wrp;
 	struct timeval tv;
 	PRIntervalTime epoch, now, elapsed, remaining;
+	PRBool wait_for_remaining;
     PRThread *self = PR_GetCurrentThread();
     
 	PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
 	PR_ASSERT(op->arg1.osfd < FD_SETSIZE);
 
     switch (op->timeout) {
         case PR_INTERVAL_NO_TIMEOUT:
 			tv.tv_sec = PT_DEFAULT_SELECT_SEC;
@@ -480,19 +500,22 @@ static void pt_poll_now_with_select(pt_C
 					rdp = NULL;
 				if (op->event & POLLOUT) {
 					FD_ZERO(&wr);
 					FD_SET(op->arg1.osfd, &wr);
 					wrp = &wr;
 				} else
 					wrp = NULL;
 
+    			wait_for_remaining = PR_TRUE;
     			msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
-				if (msecs > PT_DEFAULT_POLL_MSEC)
+				if (msecs > PT_DEFAULT_POLL_MSEC) {
+					wait_for_remaining = PR_FALSE;
 					msecs = PT_DEFAULT_POLL_MSEC;
+				}
 				tv.tv_sec = msecs/PR_MSEC_PER_SEC;
 				tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
 				rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
 
 				if (self->state & PT_THREAD_ABORTED)
 				{
 					self->state &= ~PT_THREAD_ABORTED;
 					op->result.code = -1;
@@ -509,19 +532,22 @@ static void pt_poll_now_with_select(pt_C
 					if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
 						revents |= POLLOUT;
 						
 					if (op->function(op, revents))
 						op->status = pt_continuation_done;
 
 				} else if ((rv == 0) ||
 						((errno == EINTR) || (errno == EAGAIN))) {
-					if (rv == 0)	/* select timed out */
-						now += PR_MillisecondsToInterval(msecs);
-					else
+					if (rv == 0) {	/* select timed out */
+						if (wait_for_remaining)
+							now += remaining;
+						else
+							now += PR_MillisecondsToInterval(msecs);
+					} else
 						now = PR_IntervalNow();
 					elapsed = (PRIntervalTime) (now - epoch);
 					if (elapsed >= op->timeout) {
 						op->result.code = -1;
 						op->syserrno = ETIMEDOUT;
 						op->status = pt_continuation_done;
 					} else
 						remaining = op->timeout - elapsed;
@@ -537,16 +563,17 @@ static void pt_poll_now_with_select(pt_C
 }  /* pt_poll_now_with_select */
 
 #endif	/* _PR_POLL_WITH_SELECT */
 
 static void pt_poll_now(pt_Continuation *op)
 {
     PRInt32 msecs;
 	PRIntervalTime epoch, now, elapsed, remaining;
+	PRBool wait_for_remaining;
     PRThread *self = PR_GetCurrentThread();
     
 	PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
 #if defined (_PR_POLL_WITH_SELECT)
 	/*
  	 * If the fd is small enough call the select-based poll operation
 	 */
 	if (op->arg1.osfd < FD_SETSIZE) {
@@ -613,19 +640,23 @@ static void pt_poll_now(pt_Continuation 
 			{
 				PRIntn rv;
 				struct pollfd tmp_pfd;
 
 				tmp_pfd.revents = 0;
 				tmp_pfd.fd = op->arg1.osfd;
 				tmp_pfd.events = op->event;
 
+    			wait_for_remaining = PR_TRUE;
     			msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
 				if (msecs > PT_DEFAULT_POLL_MSEC)
+				{
+					wait_for_remaining = PR_FALSE;
 					msecs = PT_DEFAULT_POLL_MSEC;
+				}
 				rv = poll(&tmp_pfd, 1, msecs);
 				
 				if (self->state & PT_THREAD_ABORTED)
 				{
 					self->state &= ~PT_THREAD_ABORTED;
 					op->result.code = -1;
 					op->syserrno = EINTR;
 					op->status = pt_continuation_done;
@@ -649,17 +680,22 @@ static void pt_poll_now(pt_Continuation 
 						if (op->function(op, revents))
 						{
 							op->status = pt_continuation_done;
 						}
 					}
 				} else if ((rv == 0) ||
 						((errno == EINTR) || (errno == EAGAIN))) {
 					if (rv == 0)	/* poll timed out */
-						now += PR_MillisecondsToInterval(msecs);
+					{
+						if (wait_for_remaining)
+							now += remaining;
+						else
+							now += PR_MillisecondsToInterval(msecs);
+					}
 					else
 						now = PR_IntervalNow();
 					elapsed = (PRIntervalTime) (now - epoch);
 					if (elapsed >= op->timeout) {
 						op->result.code = -1;
 						op->syserrno = ETIMEDOUT;
 						op->status = pt_continuation_done;
 					} else
@@ -1024,17 +1060,18 @@ static PRBool pt_solaris_sendfile_cont(p
     ssize_t count;
 
     count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred);
     PR_ASSERT((count == -1) || (count == xferred));
     PR_ASSERT(xferred <= op->nbytes_to_send);
     op->syserrno = errno;
 
     if (count == -1) {
-        if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+        if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN
+                && op->syserrno != EINTR) {
             op->result.code = -1;
             return PR_TRUE;
         }
         count = xferred;
     }
     
     op->result.code += count;
     if (count < op->nbytes_to_send) {
@@ -1054,16 +1091,43 @@ static PRBool pt_solaris_sendfile_cont(p
 
         return PR_FALSE;
     }
 
     return PR_TRUE;
 }
 #endif  /* SOLARIS */
 
+#ifdef LINUX 
+static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+    ssize_t rv;
+    off_t oldoffset;
+
+    oldoffset = op->offset;
+    rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count);
+    op->syserrno = errno;
+
+    if (rv == -1) {
+        if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+            op->result.code = -1;
+            return PR_TRUE;
+        }
+        rv = 0;
+    }
+    PR_ASSERT(rv == op->offset - oldoffset);
+    op->result.code += rv;
+    if (rv < op->count) {
+        op->count -= rv;
+        return PR_FALSE;
+    }
+    return PR_TRUE;
+}
+#endif  /* LINUX */
+
 void _PR_InitIO(void)
 {
 #if defined(DEBUG)
     memset(&pt_debug, 0, sizeof(PTDebug));
     pt_debug.timeStarted = PR_Now();
 #endif
 
     _pr_flock_lock = PR_NewLock();
@@ -1609,16 +1673,24 @@ static PRFileDesc* pt_Accept(
         addr->raw.family = PR_AF_INET6;
 #endif
     newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE);
     if (newfd == NULL) close(osfd);  /* $$$ whoops! this doesn't work $$$ */
     else
     {
         PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
         PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
+#ifdef LINUX
+        /*
+         * On Linux, experiments showed that the accepted sockets
+         * inherit the TCP_NODELAY socket option of the listening
+         * socket.
+         */
+        newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;
+#endif
     }
     return newfd;
 
 failed:
     pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);
     return NULL;
 }  /* pt_Accept */
 
@@ -2102,17 +2174,17 @@ static PRInt32 pt_AIXSendFile(PRFileDesc
         op.timeout = timeout;
         op.function = pt_aix_sendfile_cont;
         op.event = POLLOUT | POLLPRI;
         count = pt_Continue(&op);
         syserrno = op.syserrno;
     }
 
     if (count == -1) {
-        _MD_aix_map_sendfile_error(syserrno);
+        pt_MapError(_MD_aix_map_sendfile_error, syserrno);
         return -1;
     }
     if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
         PR_Close(sd);
     }
 	PR_ASSERT(count == (sfd->hlen + sfd->tlen +
 						((sfd->file_nbytes ==  0) ?
 						sf_struct.file_size - sfd->file_offset :
@@ -2141,24 +2213,26 @@ static PRInt32 pt_HPUXSendFile(PRFileDes
 {
     struct stat statbuf;
     size_t nbytes_to_send, file_nbytes_to_send;
     struct iovec hdtrl[2];  /* optional header and trailer buffers */
     int send_flags;
     PRInt32 count;
     int syserrno;
 
-    /* Get file size */
-    if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
-        _PR_MD_MAP_FSTAT_ERROR(errno);
-        return -1;
+    if (sfd->file_nbytes == 0) {
+        /* Get file size */
+        if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+            _PR_MD_MAP_FSTAT_ERROR(errno);
+            return -1;
+        } 		
+        file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+    } else {
+        file_nbytes_to_send = sfd->file_nbytes;
     }
-	file_nbytes_to_send = (sfd->file_nbytes ==  0) ?
-						statbuf.st_size - sfd->file_offset :
-						sfd->file_nbytes;
     nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;
 
     hdtrl[0].iov_base = (void *) sfd->header;  /* cast away the 'const' */
     hdtrl[0].iov_len = sfd->hlen;
     hdtrl[1].iov_base = (void *) sfd->trailer;
     hdtrl[1].iov_len = sfd->tlen;
     /*
      * SF_DISCONNECT seems to close the socket even if sendfile()
@@ -2223,17 +2297,17 @@ static PRInt32 pt_HPUXSendFile(PRFileDes
         op.timeout = timeout;
         op.function = pt_hpux_sendfile_cont;
         op.event = POLLOUT | POLLPRI;
         count = pt_Continue(&op);
         syserrno = op.syserrno;
     }
 
     if (count == -1) {
-        _MD_hpux_map_sendfile_error(syserrno);
+        pt_MapError(_MD_hpux_map_sendfile_error, syserrno);
         return -1;
     }
     if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
         PR_Close(sd);
     }
     PR_ASSERT(count == nbytes_to_send);
     return count;
 }
@@ -2353,17 +2427,17 @@ static PRInt32 pt_SolarisSendFile(PRFile
         op.function = pt_solaris_sendfile_cont;
         op.event = POLLOUT | POLLPRI;
         count = pt_Continue(&op);
         syserrno = op.syserrno;
     }
 
 done:
     if (count == -1) {
-        _MD_solaris_map_sendfile_error(syserrno);
+        pt_MapError(_MD_solaris_map_sendfile_error, syserrno);
         return -1;
     }
     if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
         PR_Close(sd);
     }
     PR_ASSERT(count == nbytes_to_send);
     return count;
 }
@@ -2420,16 +2494,150 @@ static PRInt32 pt_SolarisDispatchSendFil
     } else {
         return PR_EmulateSendFile(sd, sfd, flags, timeout);
     }
 }
 #endif /* !HAVE_SENDFILEV */
 
 #endif  /* SOLARIS */
 
+#ifdef LINUX
+/*
+ * pt_LinuxSendFile
+ *
+ *    Send file sfd->fd across socket sd. If specified, header and trailer
+ *    buffers are sent before and after the file, respectively.
+ *
+ *    PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *    
+ *    return number of bytes sent or -1 on error
+ *
+ *      This implementation takes advantage of the sendfile() system
+ *      call available in Linux kernel 2.2 or higher.
+ */
+
+static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+                PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+    struct stat statbuf;
+    size_t file_nbytes_to_send;	
+    PRInt32 count = 0;
+    ssize_t rv;
+    int syserrno;
+    off_t offset;
+    PRBool tcp_cork_enabled = PR_FALSE;
+    int tcp_cork;
+
+    if (sfd->file_nbytes == 0) {
+        /* Get file size */
+        if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+            _PR_MD_MAP_FSTAT_ERROR(errno);
+            return -1;
+        } 		
+        file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+    } else {
+        file_nbytes_to_send = sfd->file_nbytes;
+    }
+
+    if ((sfd->hlen != 0 || sfd->tlen != 0)
+            && sd->secret->md.tcp_nodelay == 0) {
+        tcp_cork = 1;
+        if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+                &tcp_cork, sizeof tcp_cork) == 0) {
+            tcp_cork_enabled = PR_TRUE;
+        } else {
+            syserrno = errno;
+            if (syserrno != EINVAL) {
+                _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);
+                return -1;
+            }
+            /*
+             * The most likely reason for the EINVAL error is that
+             * TCP_NODELAY is set (with a function other than
+             * PR_SetSocketOption).  This is not fatal, so we keep
+             * on going.
+             */
+            PR_LOG(_pr_io_lm, PR_LOG_WARNING,
+                ("pt_LinuxSendFile: "
+                "setsockopt(TCP_CORK) failed with EINVAL\n"));
+        }
+    }
+
+    if (sfd->hlen != 0) {
+        count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout);
+        if (count == -1) {
+            goto failed;
+        }
+    }
+
+    if (file_nbytes_to_send != 0) {
+        offset = sfd->file_offset;
+        do {
+            rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
+                &offset, file_nbytes_to_send);
+        } while (rv == -1 && (syserrno = errno) == EINTR);
+        if (rv == -1) {
+            if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) {
+                _MD_linux_map_sendfile_error(syserrno);
+                count = -1;
+                goto failed;
+            }
+            rv = 0;
+        }
+        PR_ASSERT(rv == offset - sfd->file_offset);
+        count += rv;
+
+        if (rv < file_nbytes_to_send) {
+            pt_Continuation op;
+
+            op.arg1.osfd = sd->secret->md.osfd;
+            op.in_fd = sfd->fd->secret->md.osfd;
+            op.offset = offset;
+            op.count = file_nbytes_to_send - rv;
+            op.result.code = count;
+            op.timeout = timeout;
+            op.function = pt_linux_sendfile_cont;
+            op.event = POLLOUT | POLLPRI;
+            count = pt_Continue(&op);
+            syserrno = op.syserrno;
+            if (count == -1) {
+                pt_MapError(_MD_linux_map_sendfile_error, syserrno);
+                goto failed;
+            }
+        }
+    }
+
+    if (sfd->tlen != 0) {
+        rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
+        if (rv == -1) {
+            count = -1;
+            goto failed;
+        }
+        count += rv;
+    }
+
+failed:
+    if (tcp_cork_enabled) {
+        tcp_cork = 0;
+        if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+                &tcp_cork, sizeof tcp_cork) == -1 && count != -1) {
+            _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
+            count = -1;
+        }
+    }
+    if (count != -1) {
+        if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+            PR_Close(sd);
+        }
+        PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send);
+    }
+    return count;
+}
+#endif  /* LINUX */
+
 #ifdef AIX
 extern	int _pr_aix_send_file_use_disabled;
 #endif
 
 static PRInt32 pt_SendFile(
     PRFileDesc *sd, PRSendFileData *sfd,
     PRTransmitFileFlags flags, PRIntervalTime timeout)
 {
@@ -2460,16 +2668,18 @@ static PRInt32 pt_SendFile(
     /* return(pt_AIXDispatchSendFile(sd, sfd, flags, timeout));*/
 #endif /* HAVE_SEND_FILE */
 #elif defined(SOLARIS)
 #ifdef HAVE_SENDFILEV
     	return(pt_SolarisSendFile(sd, sfd, flags, timeout));
 #else
 	return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout));
 #endif /* HAVE_SENDFILEV */
+#elif defined(LINUX)
+    	return(pt_LinuxSendFile(sd, sfd, flags, timeout));
 #else
 	return(PR_EmulateSendFile(sd, sfd, flags, timeout));
 #endif
 }
 
 static PRInt32 pt_TransmitFile(
     PRFileDesc *sd, PRFileDesc *fd, const void *headers,
     PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
@@ -2723,16 +2933,22 @@ static PRStatus pt_SetSocketOption(PRFil
             case PR_SockOpt_Keepalive:
             case PR_SockOpt_NoDelay:
             case PR_SockOpt_Broadcast:
             {
                 PRIntn value = (data->value.reuse_addr) ? 1 : 0;
                 rv = setsockopt(
                     fd->secret->md.osfd, level, name,
                     (char*)&value, sizeof(PRIntn));
+#ifdef LINUX
+                /* for pt_LinuxSendFile */
+                if (name == TCP_NODELAY && rv == 0) {
+                    fd->secret->md.tcp_nodelay = value;
+                }
+#endif
                 break;
             }
             case PR_SockOpt_McastLoopback:
             {
                 PRUint8 xbool = data->value.mcast_loopback ? 1 : 0;
                 rv = setsockopt(
                     fd->secret->md.osfd, level, name,
                     (char*)&xbool, sizeof(xbool));
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -66,16 +66,23 @@ static pthread_t pt_zero_tid;  /* a null
 /**************************************************************/
 
 void _PR_InitLocks(void)
 {
     int rv;
     rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); 
     PR_ASSERT(0 == rv);
 
+#ifdef LINUX
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+    rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
+    PR_ASSERT(0 == rv);
+#endif
+#endif
+
     rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
     PR_ASSERT(0 == rv);
 }
 
 static void pt_PostNotifies(PRLock *lock, PRBool unlock)
 {
     PRIntn index, rv;
     _PT_Notified post;