summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>2002-03-31 17:17:49 +0000
committerwtc%netscape.com <devnull@localhost>2002-03-31 17:17:49 +0000
commit650f51cdd250c39d6472d3ab1daa786ca0bcdd44 (patch)
tree668de609a017edb442b06767379153092178f088
parentf399ac09db7197de05ef13979f7431d39eb10566 (diff)
downloadnspr-hg-650f51cdd250c39d6472d3ab1daa786ca0bcdd44.tar.gz
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.
-rw-r--r--config/WIN32.mk10
-rwxr-xr-xconfigure70
-rw-r--r--configure.in13
-rw-r--r--macbuild/NSPR20PPC.mcpbin163973 -> 0 bytes
-rw-r--r--pr/include/md/_aix.h2
-rw-r--r--pr/include/md/_linux.h2
-rw-r--r--pr/include/md/_nto.h2
-rw-r--r--pr/include/md/_solaris.h2
-rw-r--r--pr/include/md/_unixos.h3
-rw-r--r--pr/include/md/_win95.h60
-rw-r--r--pr/src/md/beos/bnet.c11
-rw-r--r--pr/src/md/os2/os2sock.c18
-rw-r--r--pr/src/md/unix/unix.c20
-rw-r--r--pr/src/md/unix/unix_errors.c7
-rw-r--r--pr/src/md/windows/w95dllmain.c19
-rw-r--r--pr/src/md/windows/w95sock.c11
-rw-r--r--pr/src/md/windows/w95thred.c24
-rw-r--r--pr/src/misc/prtime.c46
-rw-r--r--pr/src/pthreads/Makefile.in5
-rw-r--r--pr/src/pthreads/ptio.c248
-rw-r--r--pr/src/pthreads/ptsynch.c7
21 files changed, 450 insertions, 130 deletions
diff --git a/config/WIN32.mk b/config/WIN32.mk
index f002c074..2d914e6f 100644
--- a/config/WIN32.mk
+++ b/config/WIN32.mk
@@ -116,16 +116,6 @@ 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
diff --git a/configure b/configure
index cabff754..d2fb9bc2 100755
--- a/configure
+++ b/configure
@@ -2671,8 +2671,17 @@ 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
@@ -2835,17 +2844,17 @@ 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*
@@ -3005,7 +3014,7 @@ EOF
_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
@@ -3013,7 +3022,7 @@ 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
@@ -3024,7 +3033,7 @@ 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
@@ -3787,13 +3796,6 @@ EOF
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
@@ -4150,17 +4152,17 @@ 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*
@@ -4675,12 +4677,12 @@ 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. */
@@ -4703,7 +4705,7 @@ dlopen();
; 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
@@ -4722,7 +4724,7 @@ 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
@@ -4730,7 +4732,7 @@ 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
@@ -4741,7 +4743,7 @@ 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
@@ -4769,13 +4771,13 @@ 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
@@ -4793,7 +4795,7 @@ 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
@@ -4817,12 +4819,12 @@ 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. */
@@ -4845,7 +4847,7 @@ $ac_func();
; 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
@@ -4883,7 +4885,7 @@ 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; }
@@ -4905,7 +4907,7 @@ echo "
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; }
@@ -4927,7 +4929,7 @@ echo "
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; }
@@ -4949,7 +4951,7 @@ echo "
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; }
@@ -5099,7 +5101,7 @@ 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
@@ -5122,7 +5124,7 @@ echo "configure:5103: checking whether ${CC-cc} accepts -pthread" >&5
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
diff --git a/configure.in b/configure.in
index adb7e0d9..007d355d 100644
--- a/configure.in
+++ b/configure.in
@@ -509,8 +509,17 @@ 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
@@ -1238,10 +1247,6 @@ case "$target" in
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
diff --git a/macbuild/NSPR20PPC.mcp b/macbuild/NSPR20PPC.mcp
deleted file mode 100644
index ee949c26..00000000
--- a/macbuild/NSPR20PPC.mcp
+++ /dev/null
Binary files differ
diff --git a/pr/include/md/_aix.h b/pr/include/md/_aix.h
index d8d79eeb..01afa6eb 100644
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -243,4 +243,6 @@ struct _MDCPU {
#define _MD_POLL poll
#endif
+extern void _MD_aix_map_sendfile_error(int err);
+
#endif /* nspr_aix_defs_h___ */
diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h
index 86ea248c..3f4b6735 100644
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -470,4 +470,6 @@ extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds,
/* For writev() */
#include <sys/uio.h>
+extern void _MD_linux_map_sendfile_error(int err);
+
#endif /* nspr_linux_defs_h___ */
diff --git a/pr/include/md/_nto.h b/pr/include/md/_nto.h
index de6b8033..cd6213bf 100644
--- a/pr/include/md/_nto.h
+++ b/pr/include/md/_nto.h
@@ -212,4 +212,6 @@ struct _MDCPU {
*/
#define _MD_SELECT select
+#define SA_RESTART 0
+
#endif /* nspr_nto_defs_h___ */
diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h
index a6412b69..42415a5b 100644
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -784,5 +784,7 @@ PR_END_EXTERN_C
#endif /* _PR_GLOBAL_THREADS_ONLY */
+extern void _MD_solaris_map_sendfile_error(int err);
+
#endif /* nspr_solaris_defs_h___ */
diff --git a/pr/include/md/_unixos.h b/pr/include/md/_unixos.h
index 345c48d5..25ae239c 100644
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -145,6 +145,9 @@ 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 {
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h
index 86b39d5d..a94abbd6 100644
--- a/pr/include/md/_win95.h
+++ b/pr/include/md/_win95.h
@@ -409,31 +409,55 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
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;
-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)
+#define _MD_GET_ATTACHED_THREAD() \
+ (_pr_use_static_tls ? _pr_currentThread \
+ : (PRThread *) TlsGetValue(_pr_currentThreadIndex))
-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))
+#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;
extern DWORD _pr_lastThreadIndex;
-#define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastThreadIndex))
-#define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastThreadIndex, 0)
+#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;
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_CURRENT_CPU() \
+ (_pr_use_static_tls ? _pr_currentCPU \
+ : (struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
+
+#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
diff --git a/pr/src/md/beos/bnet.c b/pr/src/md/beos/bnet.c
index 25e2ac52..ba5b666b 100644
--- a/pr/src/md/beos/bnet.c
+++ b/pr/src/md/beos/bnet.c
@@ -80,6 +80,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
struct timeval tv;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRInt32 syserror;
fd_set rd_wr;
@@ -132,8 +133,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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 {
@@ -178,8 +181,12 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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();
}
diff --git a/pr/src/md/os2/os2sock.c b/pr/src/md/os2/os2sock.c
index c41ca7ca..ecdb31ff 100644
--- a/pr/src/md/os2/os2sock.c
+++ b/pr/src/md/os2/os2sock.c
@@ -113,6 +113,7 @@ 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;
@@ -176,8 +177,10 @@ socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
* 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 {
@@ -191,9 +194,12 @@ socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
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);
@@ -224,12 +230,16 @@ socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
* 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();
}
diff --git a/pr/src/md/unix/unix.c b/pr/src/md/unix/unix.c
index 69153f27..2f6ea6f8 100644
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -514,6 +514,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
struct timeval tv;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRInt32 syserror;
fd_set rd_wr;
@@ -558,8 +559,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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 {
@@ -596,8 +599,12 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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();
}
@@ -625,6 +632,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
int msecs;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRInt32 syserror;
struct pollfd pfd;
@@ -682,8 +690,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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);
@@ -719,7 +729,11 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* 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();
}
diff --git a/pr/src/md/unix/unix_errors.c b/pr/src/md/unix/unix_errors.c
index 1ce52e68..15b423cb 100644
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -847,3 +847,10 @@ 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 */
diff --git a/pr/src/md/windows/w95dllmain.c b/pr/src/md/windows/w95dllmain.c
index f6e8d59c..f5c1bca9 100644
--- a/pr/src/md/windows/w95dllmain.c
+++ b/pr/src/md/windows/w95dllmain.c
@@ -36,12 +36,20 @@
* 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,
@@ -51,6 +59,15 @@ 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;
diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c
index eaa870e3..58944703 100644
--- a/pr/src/md/windows/w95sock.c
+++ b/pr/src/md/windows/w95sock.c
@@ -474,6 +474,7 @@ static PRInt32 socket_io_wait(
struct timeval tv;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime elapsed, remaining;
+ PRBool wait_for_remaining;
fd_set rd_wr, ex;
int err, len;
@@ -560,8 +561,10 @@ static PRInt32 socket_io_wait(
* 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 {
@@ -631,8 +634,12 @@ static PRInt32 socket_io_wait(
*/
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;
diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c
index f8a70043..918db7b4 100644
--- a/pr/src/md/windows/w95thred.c
+++ b/pr/src/md/windows/w95thred.c
@@ -38,15 +38,13 @@
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 } };
@@ -55,11 +53,11 @@ _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)
@@ -68,11 +66,11 @@ void _PR_MD_CLEANUP_BEFORE_EXIT(void)
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
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index 0aa6e46c..a107d1d4 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -774,7 +774,7 @@ PR_IMPLEMENT(PRTimeParameters)
PR_USPacificTimeParameters(const PRExplodedTime *gmt)
{
PRTimeParameters retVal;
- PRExplodedTime std;
+ PRExplodedTime st;
/*
* Based on geographic location and GMT, figure out offset of
@@ -789,32 +789,32 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
* 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;
@@ -825,7 +825,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
}
} 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 {
@@ -833,14 +833,14 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
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;
@@ -851,7 +851,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
}
} 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 {
diff --git a/pr/src/pthreads/Makefile.in b/pr/src/pthreads/Makefile.in
index a43fd6ac..8eb237d4 100644
--- a/pr/src/pthreads/Makefile.in
+++ b/pr/src/pthreads/Makefile.in
@@ -63,6 +63,11 @@ INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/incl
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)
diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c
index 5bb7e321..c4a7a53a 100644
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -173,11 +173,21 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL;
#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)
@@ -338,6 +348,15 @@ struct pt_Continuation
*/
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 */
@@ -406,6 +425,7 @@ static void pt_poll_now_with_select(pt_Continuation *op)
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);
@@ -485,9 +505,12 @@ static void pt_poll_now_with_select(pt_Continuation *op)
} 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);
@@ -514,9 +537,12 @@ static void pt_poll_now_with_select(pt_Continuation *op)
} 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) {
@@ -542,6 +568,7 @@ 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);
@@ -618,9 +645,13 @@ static void pt_poll_now(pt_Continuation *op)
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)
@@ -654,7 +685,12 @@ static void pt_poll_now(pt_Continuation *op)
} 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);
@@ -1029,7 +1065,8 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
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;
}
@@ -1059,6 +1096,33 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
}
#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)
@@ -1614,6 +1678,14 @@ static PRFileDesc* pt_Accept(
{
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;
@@ -2107,7 +2179,7 @@ static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
}
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) {
@@ -2146,14 +2218,16 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
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' */
@@ -2228,7 +2302,7 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
}
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) {
@@ -2358,7 +2432,7 @@ static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd,
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) {
@@ -2425,6 +2499,140 @@ static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
#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
@@ -2465,6 +2673,8 @@ static PRInt32 pt_SendFile(
#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
@@ -2728,6 +2938,12 @@ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *dat
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:
diff --git a/pr/src/pthreads/ptsynch.c b/pr/src/pthreads/ptsynch.c
index bc714e6d..17334af3 100644
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -71,6 +71,13 @@ void _PR_InitLocks(void)
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);
}