diff options
author | wtc%netscape.com <devnull@localhost> | 2002-03-31 17:17:49 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2002-03-31 17:17:49 +0000 |
commit | 650f51cdd250c39d6472d3ab1daa786ca0bcdd44 (patch) | |
tree | 668de609a017edb442b06767379153092178f088 | |
parent | f399ac09db7197de05ef13979f7431d39eb10566 (diff) | |
download | nspr-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.mk | 10 | ||||
-rwxr-xr-x | configure | 70 | ||||
-rw-r--r-- | configure.in | 13 | ||||
-rw-r--r-- | macbuild/NSPR20PPC.mcp | bin | 163973 -> 0 bytes | |||
-rw-r--r-- | pr/include/md/_aix.h | 2 | ||||
-rw-r--r-- | pr/include/md/_linux.h | 2 | ||||
-rw-r--r-- | pr/include/md/_nto.h | 2 | ||||
-rw-r--r-- | pr/include/md/_solaris.h | 2 | ||||
-rw-r--r-- | pr/include/md/_unixos.h | 3 | ||||
-rw-r--r-- | pr/include/md/_win95.h | 60 | ||||
-rw-r--r-- | pr/src/md/beos/bnet.c | 11 | ||||
-rw-r--r-- | pr/src/md/os2/os2sock.c | 18 | ||||
-rw-r--r-- | pr/src/md/unix/unix.c | 20 | ||||
-rw-r--r-- | pr/src/md/unix/unix_errors.c | 7 | ||||
-rw-r--r-- | pr/src/md/windows/w95dllmain.c | 19 | ||||
-rw-r--r-- | pr/src/md/windows/w95sock.c | 11 | ||||
-rw-r--r-- | pr/src/md/windows/w95thred.c | 24 | ||||
-rw-r--r-- | pr/src/misc/prtime.c | 46 | ||||
-rw-r--r-- | pr/src/pthreads/Makefile.in | 5 | ||||
-rw-r--r-- | pr/src/pthreads/ptio.c | 248 | ||||
-rw-r--r-- | pr/src/pthreads/ptsynch.c | 7 |
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 @@ -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 Binary files differdeleted file mode 100644 index ee949c26..00000000 --- a/macbuild/NSPR20PPC.mcp +++ /dev/null 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); } |