summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>1998-09-25 20:34:39 +0000
committerwtc%netscape.com <devnull@localhost>1998-09-25 20:34:39 +0000
commita5cf3a954c0d28455f78eaffcd2067e961972933 (patch)
treecf0a94361c04135067133f9c138577166fbbb0be
parent299a8c91a9d819a6d8e38032447c052271fc41e8 (diff)
downloadnspr-hg-a5cf3a954c0d28455f78eaffcd2067e961972933.tar.gz
NSPR20 v3.0 beta landing from NSPRPUB_RELEASE_3_0_LANDING_BRANCH.
-rw-r--r--config/AIX.mk28
-rw-r--r--config/BSD_OS.mk6
-rw-r--r--config/FreeBSD.mk11
-rw-r--r--config/HP-UX.mk67
-rw-r--r--config/IRIX.mk119
-rw-r--r--config/Linux.mk28
-rw-r--r--config/Makefile46
-rw-r--r--config/NCR.mk2
-rw-r--r--config/NEC.mk4
-rw-r--r--config/NEWS-OS.mk4
-rw-r--r--config/NetBSD.mk4
-rw-r--r--config/OSF1.mk25
-rw-r--r--config/OpenBSD.mk63
-rw-r--r--config/Rhapsody.mk26
-rw-r--r--config/SCOOS.mk5
-rw-r--r--config/SINIX.mk4
-rw-r--r--config/SunOS.mk4
-rw-r--r--config/SunOS4.mk5
-rw-r--r--config/SunOS5.mk44
-rw-r--r--config/UNIX.mk7
-rw-r--r--config/UNIXWARE.mk4
-rw-r--r--config/WIN32.mk33
-rw-r--r--config/config.mk46
-rw-r--r--config/now.c57
-rw-r--r--config/nsinstall.c212
-rw-r--r--config/pathsub.c219
-rw-r--r--config/rules.mk34
-rw-r--r--lib/Makefile2
-rw-r--r--lib/ds/Makefile2
-rw-r--r--lib/ds/plevent.c4
-rw-r--r--lib/ds/plhash.c18
-rw-r--r--lib/ds/plhash.h44
-rw-r--r--lib/libc/src/Makefile40
-rw-r--r--lib/libc/src/plerror.c4
-rw-r--r--lib/libc/src/plvrsion.c65
-rw-r--r--lib/msgc/include/gcint.h2
-rw-r--r--lib/msgc/include/prgc.h6
-rw-r--r--lib/msgc/src/Makefile2
-rw-r--r--lib/msgc/src/prmsgc.c19
-rw-r--r--lib/msgc/src/unixgc.c2
-rw-r--r--lib/msgc/tests/Makefile2
-rw-r--r--lib/prstreams/Makefile83
-rw-r--r--macbuild/NSPR20PPC.mcpbin75093 -> 75653 bytes
-rw-r--r--pr/include/MANIFEST7
-rw-r--r--pr/include/md/Makefile16
-rw-r--r--pr/include/md/_aix.h52
-rw-r--r--pr/include/md/_bsdi.h38
-rw-r--r--pr/include/md/_darwin.cfg8
-rw-r--r--pr/include/md/_darwin.h69
-rw-r--r--pr/include/md/_dgux.cfg3
-rw-r--r--pr/include/md/_dgux.h2
-rw-r--r--pr/include/md/_freebsd.h38
-rw-r--r--pr/include/md/_hpux.h49
-rw-r--r--pr/include/md/_hpux32.cfg (renamed from pr/include/md/_hpux.cfg)4
-rw-r--r--pr/include/md/_hpux64.cfg122
-rw-r--r--pr/include/md/_irix.h102
-rw-r--r--pr/include/md/_irix32.cfg (renamed from pr/include/md/_irix.cfg)3
-rw-r--r--pr/include/md/_irix64.cfg127
-rw-r--r--pr/include/md/_linux.h46
-rw-r--r--pr/include/md/_macos.h13
-rw-r--r--pr/include/md/_ncr.cfg3
-rw-r--r--pr/include/md/_ncr.h39
-rw-r--r--pr/include/md/_nec.h36
-rw-r--r--pr/include/md/_netbsd.h36
-rw-r--r--pr/include/md/_nspr_pthread.h36
-rw-r--r--pr/include/md/_openbsd.cfg262
-rw-r--r--pr/include/md/_openbsd.h171
-rw-r--r--pr/include/md/_os2.h2
-rw-r--r--pr/include/md/_osf1.cfg3
-rw-r--r--pr/include/md/_osf1.h64
-rw-r--r--pr/include/md/_pth.h49
-rw-r--r--pr/include/md/_reliantunix.cfg3
-rw-r--r--pr/include/md/_reliantunix.h38
-rw-r--r--pr/include/md/_rhapsody.cfg8
-rw-r--r--pr/include/md/_rhapsody.h69
-rw-r--r--pr/include/md/_scoos.cfg3
-rw-r--r--pr/include/md/_scoos.h39
-rw-r--r--pr/include/md/_solaris.h82
-rw-r--r--pr/include/md/_sony.h36
-rw-r--r--pr/include/md/_sunos4.h38
-rw-r--r--pr/include/md/_unix_errors.h3
-rw-r--r--pr/include/md/_unixos.h168
-rw-r--r--pr/include/md/_unixware.cfg3
-rw-r--r--pr/include/md/_unixware.h38
-rw-r--r--pr/include/md/_win16.h2
-rw-r--r--pr/include/md/_win95.h11
-rw-r--r--pr/include/md/_winnt.h116
-rw-r--r--pr/include/md/prosdep.h9
-rw-r--r--pr/include/nspr.h1
-rw-r--r--pr/include/obsolete/pralarm.h1
-rw-r--r--pr/include/obsolete/protypes.h1
-rw-r--r--pr/include/pratom.h90
-rw-r--r--pr/include/prbit.h2
-rw-r--r--pr/include/prcountr.h512
-rw-r--r--pr/include/prdtoa.h6
-rw-r--r--pr/include/prerror.h8
-rw-r--r--pr/include/prinit.h22
-rw-r--r--pr/include/prio.h66
-rw-r--r--pr/include/private/Makefile2
-rw-r--r--pr/include/private/pprio.h15
-rw-r--r--pr/include/private/pprmwait.h (renamed from pr/src/io/pprmwait.h)39
-rw-r--r--pr/include/private/primpl.h236
-rw-r--r--pr/include/prlog.h12
-rw-r--r--pr/include/prmem.h103
-rw-r--r--pr/include/prmwait.h93
-rw-r--r--pr/include/prolock.h196
-rw-r--r--pr/include/prpdce.h4
-rw-r--r--pr/include/prtrace.h635
-rw-r--r--pr/include/prtypes.h20
-rwxr-xr-xpr/include/prvrsion.h108
-rw-r--r--pr/src/Makefile109
-rw-r--r--pr/src/io/Makefile6
-rw-r--r--pr/src/io/prfdcach.c287
-rw-r--r--pr/src/io/prfile.c24
-rw-r--r--pr/src/io/prio.c83
-rw-r--r--pr/src/io/priometh.c52
-rw-r--r--pr/src/io/prlayer.c1
-rw-r--r--pr/src/io/prlog.c47
-rw-r--r--pr/src/io/prmwait.c933
-rw-r--r--pr/src/io/prpolevt.c121
-rw-r--r--pr/src/io/prsocket.c178
-rw-r--r--pr/src/linking/prlink.c668
-rw-r--r--pr/src/malloc/prmalloc.c22
-rw-r--r--pr/src/malloc/prmem.c21
-rw-r--r--pr/src/md/mac/macio.c6
-rw-r--r--pr/src/md/mac/macsockclient.c115
-rw-r--r--pr/src/md/mac/macsockotpt.c2349
-rw-r--r--pr/src/md/mac/macthr.c5
-rw-r--r--pr/src/md/os2/os2poll.c345
-rw-r--r--pr/src/md/prosdep.c14
-rw-r--r--pr/src/md/unix/Makefile15
-rw-r--r--pr/src/md/unix/aix.c248
-rw-r--r--pr/src/md/unix/darwin.c27
-rw-r--r--pr/src/md/unix/hpux.c149
-rw-r--r--pr/src/md/unix/irix.c584
-rw-r--r--pr/src/md/unix/ncr.c9
-rw-r--r--pr/src/md/unix/objs.mk14
-rw-r--r--pr/src/md/unix/openbsd.c102
-rw-r--r--pr/src/md/unix/os_Irix.s89
-rw-r--r--pr/src/md/unix/os_SunOS.s83
-rw-r--r--pr/src/md/unix/os_SunOS_ultrasparc.s27
-rw-r--r--pr/src/md/unix/osf1.c57
-rw-r--r--pr/src/md/unix/pthreads_user.c12
-rw-r--r--pr/src/md/unix/rhapsody.c27
-rw-r--r--pr/src/md/unix/scoos.c8
-rw-r--r--pr/src/md/unix/solaris.c31
-rw-r--r--pr/src/md/unix/unix.c4668
-rw-r--r--pr/src/md/unix/unix_errors.c56
-rw-r--r--pr/src/md/unix/unixware.c14
-rw-r--r--pr/src/md/unix/uxpoll.c681
-rw-r--r--pr/src/md/unix/uxproces.c28
-rw-r--r--pr/src/md/unix/uxwrap.c459
-rw-r--r--pr/src/md/windows/Makefile2
-rw-r--r--pr/src/md/windows/ntdllmn.c67
-rw-r--r--pr/src/md/windows/ntio.c394
-rw-r--r--pr/src/md/windows/ntmisc.c70
-rw-r--r--pr/src/md/windows/ntthread.c87
-rw-r--r--pr/src/md/windows/w16callb.c2
-rw-r--r--pr/src/md/windows/w16mem.c1
-rw-r--r--pr/src/md/windows/w32poll.c285
-rw-r--r--pr/src/md/windows/w95dllmain.c50
-rw-r--r--pr/src/md/windows/w95sock.c592
-rw-r--r--pr/src/md/windows/w95thred.c13
-rw-r--r--pr/src/md/windows/win32_errors.c327
-rw-r--r--pr/src/memory/prseg.c137
-rw-r--r--pr/src/misc/Makefile5
-rw-r--r--pr/src/misc/pratom.c105
-rw-r--r--pr/src/misc/prcountr.c510
-rw-r--r--pr/src/misc/prdtoa.c2
-rw-r--r--pr/src/misc/prinit.c43
-rw-r--r--pr/src/misc/prolock.c91
-rw-r--r--pr/src/misc/prthinfo.c14
-rw-r--r--pr/src/misc/prtime.c29
-rw-r--r--pr/src/misc/prtrace.c912
-rw-r--r--pr/src/prvrsion.c65
-rw-r--r--pr/src/pthreads/ptio.c728
-rw-r--r--pr/src/pthreads/ptmisc.c1
-rw-r--r--pr/src/pthreads/ptsynch.c61
-rw-r--r--pr/src/pthreads/ptthread.c378
-rw-r--r--pr/src/threads/Makefile6
-rw-r--r--pr/src/threads/combined/prucpu.c4
-rw-r--r--pr/src/threads/combined/prucv.c3
-rw-r--r--pr/src/threads/combined/prustack.c6
-rw-r--r--pr/src/threads/combined/pruthr.c804
-rw-r--r--pr/src/threads/prcthr.c21
-rw-r--r--pr/src/threads/prtpd.c170
-rw-r--r--pr/tests/Makefile190
-rw-r--r--pr/tests/accept.c78
-rw-r--r--pr/tests/atomic.c21
-rw-r--r--pr/tests/attach.c17
-rw-r--r--pr/tests/bigfile.c135
-rw-r--r--pr/tests/cltsrv.c170
-rw-r--r--pr/tests/concur.c18
-rw-r--r--pr/tests/cvar2.c5
-rw-r--r--pr/tests/dceemu.c6
-rw-r--r--pr/tests/dll/Makefile4
-rw-r--r--pr/tests/dlltest.c79
-rw-r--r--pr/tests/foreign.c345
-rw-r--r--pr/tests/forktest.c21
-rw-r--r--pr/tests/initclk.c87
-rw-r--r--pr/tests/inrval.c157
-rw-r--r--pr/tests/instrumt.c470
-rw-r--r--pr/tests/ipv6.c65
-rw-r--r--pr/tests/joinkk.c4
-rw-r--r--pr/tests/layer.c6
-rw-r--r--pr/tests/lock.c105
-rw-r--r--pr/tests/many_cv.c2
-rw-r--r--pr/tests/multiwait.c61
-rw-r--r--pr/tests/nbconn.c574
-rw-r--r--pr/tests/nblayer.c91
-rw-r--r--pr/tests/op_filok.c37
-rw-r--r--pr/tests/op_noacc.c4
-rw-r--r--pr/tests/op_nofil.c37
-rw-r--r--pr/tests/parent.c10
-rw-r--r--pr/tests/perf.c24
-rw-r--r--pr/tests/poll_nm.c2
-rw-r--r--pr/tests/pollable.c273
-rw-r--r--pr/tests/prftest2.c2
-rw-r--r--pr/tests/priotest.c4
-rw-r--r--pr/tests/provider.c1356
-rw-r--r--pr/tests/sel_spd.c15
-rw-r--r--pr/tests/socket.c7
-rw-r--r--pr/tests/stack.c266
-rw-r--r--pr/tests/switch.c4
-rw-r--r--pr/tests/testfile.c85
-rw-r--r--pr/tests/tpd.c77
-rw-r--r--pr/tests/udpsrv.c78
-rw-r--r--pr/tests/version.c101
228 files changed, 20862 insertions, 8630 deletions
diff --git a/config/AIX.mk b/config/AIX.mk
index 5dfc9cc9..beec0ea7 100644
--- a/config/AIX.mk
+++ b/config/AIX.mk
@@ -26,8 +26,10 @@ include $(MOD_DEPTH)/config/UNIX.mk
# Temporary define for the Client; to be removed when binary release is used
#
ifdef MOZILLA_CLIENT
+ifneq ($(USE_PTHREADS),1)
CLASSIC_NSPR = 1
endif
+endif
#
# There are three implementation strategies available on AIX:
@@ -36,7 +38,7 @@ endif
ifeq ($(CLASSIC_NSPR),1)
PTHREADS_USER =
USE_PTHREADS =
- IMPL_STRATEGY = _CLASSIC
+ IMPL_STRATEGY = _EMU
DEFINES += -D_PR_LOCAL_THREADS_ONLY
else
ifeq ($(PTHREADS_USER),1)
@@ -44,17 +46,10 @@ ifeq ($(PTHREADS_USER),1)
IMPL_STRATEGY = _PTH_USER
else
USE_PTHREADS = 1
+ IMPL_STRATEGY = _PTH
endif
endif
-#
-# XXX
-# Temporary define for the Client; to be removed when binary release is used
-#
-ifdef MOZILLA_CLIENT
-IMPL_STRATEGY =
-endif
-
ifeq ($(CLASSIC_NSPR),1)
CC = xlC
CCC = xlC
@@ -67,17 +62,13 @@ CPU_ARCH = rs6000
RANLIB = ranlib
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
-
OS_CFLAGS = -qro -qroconst -DAIX -DSYSV
ifeq ($(CC),xlC_r)
OS_CFLAGS += -qarch=com
endif
ifeq ($(OS_RELEASE),4.1)
-OS_CFLAGS += -DAIX4_1
+OS_CFLAGS += -DAIX4_1 -D_PR_NO_LARGE_FILES
else
DSO_LDOPTS = -brtl -bM:SRE -bnoentry -bexpall
MKSHLIB = $(LD) $(DSO_LDOPTS)
@@ -86,7 +77,14 @@ OS_CFLAGS += -DAIX4_3
endif
endif
-endif # USE_AUTOCONF
+ifeq (,$(filter-out 4.2 4.3,$(OS_RELEASE)))
+# On these OS revisions, localtime_r() is declared if _THREAD_SAFE
+# is defined.
+ifneq ($(CLASSIC_NSPR),1)
+OS_CFLAGS += -DHAVE_POINTER_LOCALTIME_R
+endif
+OS_CFLAGS += -D_PR_HAVE_OFF64_T
+endif
#
# Special link info for constructing AIX programs. On AIX we have to
diff --git a/config/BSD_OS.mk b/config/BSD_OS.mk
index c865aa89..87b63b93 100644
--- a/config/BSD_OS.mk
+++ b/config/BSD_OS.mk
@@ -32,11 +32,7 @@ OS_CFLAGS = -DBSDI -DHAVE_STRERROR -D__386BSD__ -DNEED_BSDREGEX -Di386
OS_LIBS = -lcompat -ldl
ifeq ($(OS_RELEASE),2.1)
-OS_CFLAGS += -DBSDI_2
-endif
-
-ifdef USE_AUTOCONF
-OS_CFLAGS =
+OS_CFLAGS += -DBSDI_2 -D_PR_TIMESPEC_HAS_TS_SEC
endif
G++INCLUDES = -I/usr/include/g++
diff --git a/config/FreeBSD.mk b/config/FreeBSD.mk
index ceed49cb..d37585f7 100644
--- a/config/FreeBSD.mk
+++ b/config/FreeBSD.mk
@@ -28,17 +28,14 @@ RANLIB = ranlib
OS_REL_CFLAGS = -mno-486 -Di386
CPU_ARCH = x86
-ifdef USE_AUTOCONF
-OS_CFLAGS = $(DSO_CFLAGS)
-else
-OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -ansi -Wall -pipe -DFREEBSD -DHAVE_STRERROR -DHAVE_BSD_FLOCK -D_PR_NEED_POLL
-endif
+OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -ansi -Wall -pipe -DFREEBSD -DHAVE_STRERROR -DHAVE_BSD_FLOCK
ifeq ($(USE_PTHREADS),1)
+IMPL_STRATEGY = _PTH
OS_LIBS = -lc_r
-# XXX probably should define _THREAD_SAFE too.
-DEFINES += -D_PR_NEED_FAKE_POLL
+DEFINES += -D_THREAD_SAFE -D_PR_NEED_FAKE_POLL
else
+IMPL_STRATEGY = _EMU
OS_LIBS = -lc
DEFINES += -D_PR_LOCAL_THREADS_ONLY
endif
diff --git a/config/HP-UX.mk b/config/HP-UX.mk
index f6471f41..6f32a955 100644
--- a/config/HP-UX.mk
+++ b/config/HP-UX.mk
@@ -24,13 +24,14 @@ include $(MOD_DEPTH)/config/UNIX.mk
DLL_SUFFIX = sl
ifdef NS_USE_GCC
-CC = gcc
-CCC = g++
-OS_CFLAGS =
+ CC = gcc
+ CCC = g++
+ OS_CFLAGS =
+ COMPILER_TAG = _gcc
else
-CC = cc -Ae
-CCC = CC
-OS_CFLAGS = +ESlit
+ CC = cc -Ae
+ CCC = CC -ext
+ OS_CFLAGS = +ESlit
endif
RANLIB = echo
@@ -52,6 +53,14 @@ ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
OS_CFLAGS += -D_PR_NEED_H_ERRNO
endif
+# Do we have localtime_r()? Does it return 'int' or 'struct tm *'?
+ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
+OS_CFLAGS += -DHAVE_INT_LOCALTIME_R
+endif
+ifeq (,$(filter-out B.10.30 B.11.00,$(OS_RELEASE)))
+OS_CFLAGS += -DHAVE_POINTER_LOCALTIME_R
+endif
+
#
# XXX
# Temporary define for the Client; to be removed when binary release is used
@@ -72,12 +81,12 @@ endif
#
ifeq ($(basename $(OS_RELEASE)),A.09)
OS_CFLAGS += -DHPUX9
-DEFAULT_IMPL_STRATEGY = _CLASSIC
+DEFAULT_IMPL_STRATEGY = _EMU
endif
ifeq ($(OS_RELEASE),B.10.01)
OS_CFLAGS += -DHPUX10
-DEFAULT_IMPL_STRATEGY = _CLASSIC
+DEFAULT_IMPL_STRATEGY = _EMU
endif
ifeq ($(OS_RELEASE),B.10.10)
@@ -87,6 +96,9 @@ endif
ifeq ($(OS_RELEASE),B.10.20)
OS_CFLAGS += -DHPUX10 -DHPUX10_20
+ifndef NS_USE_GCC
+OS_CFLAGS += +DAportable +DS1.1
+endif
DEFAULT_IMPL_STRATEGY = _PTH
endif
@@ -96,7 +108,7 @@ endif
ifeq ($(OS_RELEASE),B.10.30)
ifndef NS_USE_GCC
-CCC = /opt/aCC/bin/aCC
+CCC = /opt/aCC/bin/aCC -ext
OS_CFLAGS += +DAportable +DS1.1
endif
OS_CFLAGS += -DHPUX10 -DHPUX10_30
@@ -105,23 +117,30 @@ endif
# 11.00 is similar to 10.30.
ifeq ($(OS_RELEASE),B.11.00)
-ifndef NS_USE_GCC
-CCC = /opt/aCC/bin/aCC
-OS_CFLAGS += +DAportable +DS1.1
-endif
-OS_CFLAGS += -DHPUX10 -DHPUX11
+ ifndef NS_USE_GCC
+ CCC = /opt/aCC/bin/aCC -ext
+ ifeq ($(USE_64), 1)
+ OS_CFLAGS += +DA2.0W +DChpux
+ COMPILER_TAG = _64
+ else
+ OS_CFLAGS += +DAportable +DS1.1
+ COMPILER_TAG = _32
+ endif
+ endif
+OS_CFLAGS += -DHPUX10 -DHPUX11 -D_LARGEFILE64_SOURCE -D_PR_HAVE_OFF64_T
DEFAULT_IMPL_STRATEGY = _PTH
endif
-ifeq ($(DEFAULT_IMPL_STRATEGY),_CLASSIC)
+ifeq ($(DEFAULT_IMPL_STRATEGY),_EMU)
CLASSIC_NSPR = 1
endif
ifeq ($(DEFAULT_IMPL_STRATEGY),_PTH)
USE_PTHREADS = 1
+IMPL_STRATEGY = _PTH
ifeq ($(CLASSIC_NSPR),1)
USE_PTHREADS =
-IMPL_STRATEGY = _CLASSIC
+IMPL_STRATEGY = _EMU
endif
ifeq ($(PTHREADS_USER),1)
USE_PTHREADS =
@@ -129,18 +148,14 @@ IMPL_STRATEGY = _PTH_USER
endif
endif
-#
-# XXX
-# Temporary define for the Client; to be removed when binary release is used
-#
-ifdef MOZILLA_CLIENT
-IMPL_STRATEGY =
-endif
-
ifeq ($(CLASSIC_NSPR),1)
DEFINES += -D_PR_LOCAL_THREADS_ONLY
endif
+ifeq (,$(filter-out A.09 B.10,$(basename $(OS_RELEASE))))
+DEFINES += -D_PR_NO_LARGE_FILES
+endif
+
#
# To use the true pthread (kernel thread) library on 10.30 and
# 11.00, we should define _POSIX_C_SOURCE to be 199506L.
@@ -173,7 +188,3 @@ DSO_CFLAGS = +Z
endif
HAVE_PURIFY = 1
-
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-endif
diff --git a/config/IRIX.mk b/config/IRIX.mk
index 686e98cd..8c5e9f30 100644
--- a/config/IRIX.mk
+++ b/config/IRIX.mk
@@ -22,50 +22,80 @@
include $(MOD_DEPTH)/config/UNIX.mk
#
-# The default implementation strategy for Irix is classic nspr.
+# XXX
+# Temporary define for the Client; to be removed when binary release is used
#
-ifeq ($(USE_PTHREADS),1)
-IMPL_STRATEGY = _PTH
+ifdef MOZILLA_CLIENT
+ifneq ($(USE_PTHREADS),1)
+CLASSIC_NSPR = 1
endif
-
-ifdef NS_USE_GCC
-CC = gcc
-COMPILER_TAG = _gcc
-AS = $(CC) -x assembler-with-cpp
-ODD_CFLAGS = -Wall -Wno-format
-ifdef BUILD_OPT
-OPTIMIZER = -O6
endif
-else
-CC = cc
-CCC = CC
-ODD_CFLAGS = -fullwarn -xansi
-ifdef BUILD_OPT
-ifeq ($(USE_N32),1)
-OPTIMIZER = -O -OPT:Olimit=4000
+#
+# The default implementation strategy for Irix is pthreads.
+# Classic nspr (user-level threads on top of sprocs) is also
+# available.
+#
+ifeq ($(CLASSIC_NSPR),1)
+ IMPL_STRATEGY = _MxN
else
-OPTIMIZER = -O -Olimit 4000
-endif
-
+ USE_PTHREADS = 1
+ USE_N32 = 1
+ IMPL_STRATEGY = _PTH
endif
-# For 6.x machines, include this flag
-ifeq ($(basename $(OS_RELEASE)),6)
-ifeq ($(USE_N32),1)
-ODD_CFLAGS += -n32 -exceptions -woff 1209,1642,3201
-COMPILER_TAG = _n32
-else
-ODD_CFLAGS += -32 -multigot
-endif
+ifdef NS_USE_GCC
+ CC = gcc
+ COMPILER_TAG = _gcc
+ AS = $(CC) -x assembler-with-cpp -D_ASM -mips2
+ ODD_CFLAGS = -Wall -Wno-format
+ ifdef BUILD_OPT
+ OPTIMIZER = -O6
+ endif
else
-ODD_CFLAGS += -xgot
-endif
+ CC = cc
+ CCC = CC
+ ODD_CFLAGS = -fullwarn -xansi
+ ifdef BUILD_OPT
+ ifneq ($(USE_N32),1)
+ OPTIMIZER = -O -Olimit 4000
+ else
+ OPTIMIZER = -O -OPT:Olimit=4000
+ endif
+ endif
+
+#
+# The default behavior is still -o32 generation, hence the explicit tests
+# for -n32 and -64 and implicitly assuming -o32. If that changes, ...
+#
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ODD_CFLAGS += -multigot
+ SHLIB_LD_OPTS = -no_unresolved
+ ifeq ($(USE_N32),1)
+ ODD_CFLAGS += -n32 -woff 1209
+ COMPILER_TAG = _n32
+ LDOPTS += -n32
+ SHLIB_LD_OPTS += -n32
+ ifeq ($(OS_RELEASE), 6_2)
+ LDOPTS += -Wl,-woff,85
+ SHLIB_LD_OPTS += -woff 85
+ endif
+ else
+ ifeq ($(USE_64),1)
+ ODD_CFLAGS += -64
+ COMPILER_TAG = _64
+ else
+ ODD_CFLAGS += -32
+ COMPILER_TAG = _o32
+ endif
+ endif
+ else
+ ODD_CFLAGS += -xgot
+ endif
endif
ODD_CFLAGS += -DSVR4 -DIRIX
-
CPU_ARCH = mips
RANLIB = /bin/true
@@ -78,30 +108,15 @@ ifeq ($(OS_RELEASE),5.3)
OS_CFLAGS += -DIRIX5_3
endif
-ifeq ($(OS_RELEASE),6.2)
-OS_CFLAGS += -DIRIX6_2
-endif
-
-ifeq ($(OS_RELEASE),6.3)
-OS_CFLAGS += -DIRIX6_3
-endif
-
ifndef NO_MDUPDATE
OS_CFLAGS += $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
else
OS_CFLAGS += $(NOMD_OS_CFLAGS)
endif
-# catch unresolved symbols
-ifeq ($(basename $(OS_RELEASE)),6)
-SHLIB_LD_OPTS = -no_unresolved
-ifeq ($(USE_N32),1)
-SHLIB_LD_OPTS += -n32
-else
-SHLIB_LD_OPTS += -32
-endif
-endif
-
+# -rdata_shared is an ld option that puts string constants and
+# const data into the text segment, where they will be shared
+# across processes and be read-only.
MKSHLIB = $(LD) $(SHLIB_LD_OPTS) -rdata_shared -shared -soname $(@:$(OBJDIR)/%.so=%.so)
HAVE_PURIFY = 1
@@ -111,7 +126,3 @@ DSO_LDOPTS = -elf -shared -all
ifdef DSO_BACKEND
DSO_LDOPTS += -soname $(DSO_NAME)
endif
-
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-endif
diff --git a/config/Linux.mk b/config/Linux.mk
index e880e4a3..50736123 100644
--- a/config/Linux.mk
+++ b/config/Linux.mk
@@ -26,13 +26,25 @@
include $(MOD_DEPTH)/config/UNIX.mk
#
-# The default implementation strategy for Linux is classic nspr.
+# XXX
+# Temporary define for the Client; to be removed when binary release is used
#
-ifeq ($(USE_PTHREADS),1)
-IMPL_STRATEGY = _PTH
-DEFINES += -D_REENTRANT
-else
+ifdef MOZILLA_CLIENT
+ifneq ($(USE_PTHREADS),1)
+CLASSIC_NSPR = 1
+endif
+endif
+
+#
+# The default implementation strategy for Linux is pthreads.
+#
+ifeq ($(CLASSIC_NSPR),1)
+IMPL_STRATEGY = _EMU
DEFINES += -D_PR_LOCAL_THREADS_ONLY
+else
+USE_PTHREADS = 1
+IMPL_STRATEGY = _PTH
+DEFINES += -D_REENTRANT
endif
ifeq (86,$(findstring 86,$(OS_TEST)))
@@ -43,8 +55,8 @@ CPU_ARCH := arm
else
CPU_ARCH := $(OS_TEST)
endif
-CPU_ARCH_TAG = _$(CPU_ARCH)
endif
+CPU_ARCH_TAG = _$(CPU_ARCH)
CC = gcc
CCC = g++
@@ -56,11 +68,7 @@ G++INCLUDES = -I/usr/include/g++
PLATFORM_FLAGS = -ansi -Wall -pipe -DLINUX -Dlinux
PORT_FLAGS = -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR
-ifdef USE_AUTOCONF
-OS_CFLAGS = $(DSO_CFLAGS) #-include $(MOD_DEPTH)/include/config.h
-else
OS_CFLAGS = $(DSO_CFLAGS) $(PLATFORM_FLAGS) $(PORT_FLAGS)
-endif
######################################################################
# Version-specific stuff
diff --git a/config/Makefile b/config/Makefile
index 0a6d459d..f3e19971 100644
--- a/config/Makefile
+++ b/config/Makefile
@@ -21,20 +21,58 @@ MOD_DEPTH = ..
include $(MOD_DEPTH)/config/config.mk
-CSRCS = nsinstall.c pathsub.c
+CSRCS = nsinstall.c now.c
PLSRCS = nfspwd.pl
-ifneq ($(OS_ARCH),WINNT)
-PROGRAM = $(OBJDIR)/nsinstall
-TARGETS = $(PROGRAM) $(PLSRCS:.pl=)
+ifeq ($(OS_ARCH), WINNT)
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifeq ($(USE_N32),1)
+ XLDOPTS += -n32 -Wl,-woff,85
+ ifeq ($(OS_RELEASE), 6_2)
+ XLDOPTS += -Wl,-woff,85
+ endif
+ else
+ ifeq ($(USE_64),1)
+ XLDOPTS += -64
+ else
+ XLDOPTS += -32
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+ ifeq ($(USE_64),1)
+ XLDOPTS += +DD64
+ endif
endif
include $(MOD_DEPTH)/config/rules.mk
+PROGS = $(OBJDIR)/now$(PROG_SUFFIX)
+
+ifeq ($(OS_ARCH),WINNT)
+TARGETS = $(PROGS)
+else
+PROGS += $(OBJDIR)/nsinstall$(PROG_SUFFIX)
+TARGETS = $(PROGS) $(PLSRCS:.pl=)
+endif
+
# Redefine MAKE_OBJDIR for just this directory
define MAKE_OBJDIR
if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); fi
endef
export:: $(TARGETS)
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ $(CC) $(XCFLAGS) $< $(XLDOPTS) -o $@
+
diff --git a/config/NCR.mk b/config/NCR.mk
index 3922d3da..98d07596 100644
--- a/config/NCR.mk
+++ b/config/NCR.mk
@@ -31,9 +31,7 @@ export PATH:=$(PATH):/opt/ncc/bin
RANLIB = true
GCC_FLAGS_EXTRA = -pipe
-ifndef USE_AUTOCONF
DEFINES += -DSVR4 -DSYSV -DHAVE_STRERROR -DNCR -D_PR_LOCAL_THREADS_ONLY
-endif
ifdef NS_USE_NATIVE
CC = cc
diff --git a/config/NEC.mk b/config/NEC.mk
index 3a884748..7ca64c7e 100644
--- a/config/NEC.mk
+++ b/config/NEC.mk
@@ -36,11 +36,7 @@ MKSHLIB = $(LD) $(DSO_LDOPTS)
RANLIB = /bin/true
DEFINES += -D_PR_LOCAL_THREADS_ONLY
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
OS_CFLAGS = $(ODD_CFLAGS) -DSVR4 -D__SVR4 -DNEC -Dnec_ews -DHAVE_STRERROR
-endif
OS_LIBS = -lsocket -lnsl -ldl $(LDOPTIONS)
LDOPTIONS = -lc -L/usr/ucblib -lucb
diff --git a/config/NEWS-OS.mk b/config/NEWS-OS.mk
index 443ef1db..b0307c02 100644
--- a/config/NEWS-OS.mk
+++ b/config/NEWS-OS.mk
@@ -39,11 +39,7 @@ G++INCLUDES =
PLATFORM_FLAGS = -Xa -fullwarn -DSONY
PORT_FLAGS = -DSYSV -DSVR4 -D__svr4 -D__svr4__ -D_PR_LOCAL_THREADS_ONLY -DHAVE_SVID_GETTOD
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
OS_CFLAGS = $(PLATFORM_FLAGS) $(PORT_FLAGS)
-endif
######################################################################
# Version-specific stuff
diff --git a/config/NetBSD.mk b/config/NetBSD.mk
index 2d3b1ba6..b1a5c759 100644
--- a/config/NetBSD.mk
+++ b/config/NetBSD.mk
@@ -32,11 +32,7 @@ else
CPU_ARCH = $(OS_TEST)
endif
-ifdef USE_AUTOCONF
-OS_CFLAGS = $(DSO_CFLAGS)
-else
OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -ansi -Wall -pipe -DNETBSD -DHAVE_STRERROR -DHAVE_BSD_FLOCK
-endif
ifeq ($(USE_PTHREADS),1)
OS_LIBS = -lc_r
diff --git a/config/OSF1.mk b/config/OSF1.mk
index 2f8c5792..b1d10694 100644
--- a/config/OSF1.mk
+++ b/config/OSF1.mk
@@ -46,22 +46,15 @@ endif
# Classic nspr is also available.
#
ifneq ($(OS_RELEASE),V3.2)
-USE_PTHREADS = 1
ifeq ($(CLASSIC_NSPR), 1)
- USE_PTHREADS =
- IMPL_STRATEGY := _CLASSIC
+ IMPL_STRATEGY = _EMU
DEFINES += -D_PR_LOCAL_THREADS_ONLY
+else
+ USE_PTHREADS = 1
+ IMPL_STRATEGY = _PTH
endif
endif
-#
-# XXX
-# Temporary define for the Client; to be removed when binary release is used
-#
-ifdef MOZILLA_CLIENT
-IMPL_STRATEGY =
-endif
-
CC = cc $(NON_LD_FLAGS) -std1 -readonly_strings
# The C++ compiler cxx has -readonly_strings on by default.
CCC = cxx
@@ -76,19 +69,15 @@ endif
NON_LD_FLAGS = -ieee_with_inexact
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
-OS_CFLAGS = -DOSF1 -D_REENTRANT -taso
+OS_CFLAGS = -DOSF1 -D_REENTRANT
ifeq ($(OS_RELEASE),V3.2)
-OS_CFLAGS += -DOSF1V3
+OS_CFLAGS += -DHAVE_INT_LOCALTIME_R
endif
ifeq (V4,$(findstring V4,$(OS_RELEASE)))
-OS_CFLAGS += -DOSF1V4
+OS_CFLAGS += -DHAVE_POINTER_LOCALTIME_R
endif
-endif # USE_AUTOCONF
ifeq ($(USE_PTHREADS),1)
OS_CFLAGS += -pthread
diff --git a/config/OpenBSD.mk b/config/OpenBSD.mk
new file mode 100644
index 00000000..ca9f8dbd
--- /dev/null
+++ b/config/OpenBSD.mk
@@ -0,0 +1,63 @@
+#
+# The contents of this file are subject to the Netscape Public License
+# Version 1.0 (the "NPL"); you may not use this file except in
+# compliance with the NPL. You may obtain a copy of the NPL at
+# http://www.mozilla.org/NPL/
+#
+# Software distributed under the NPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+# for the specific language governing rights and limitations under the
+# NPL.
+#
+# The Initial Developer of this code under the NPL is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All Rights
+# Reserved.
+#
+
+#
+# Config stuff for OpenBSD
+#
+
+include $(MOD_DEPTH)/config/UNIX.mk
+
+CC = gcc
+CCC = g++
+RANLIB = ranlib
+
+OS_REL_CFLAGS =
+ifeq (86,$(findstring 86,$(OS_TEST)))
+CPU_ARCH = x86
+else
+CPU_ARCH = $(OS_TEST)
+endif
+
+OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -ansi -Wall -pipe -DOPENBSD
+DHAVE_STRERROR -DHAVE_BSD_FLOCK
+
+ifeq ($(USE_PTHREADS),1)
+OS_LIBS = -lc_r
+# XXX probably should define _THREAD_SAFE too.
+else
+OS_LIBS = -lc
+DEFINES += -D_PR_LOCAL_THREADS_ONLY
+endif
+
+ARCH = openbsd
+
+DSO_CFLAGS = -fPIC
+DSO_LDFLAGS =
+DSO_LDOPTS = -Bshareable
+ifeq ($(OS_TEST),alpha)
+DSO_LDOPTS = -shared
+endif
+ifeq ($(OS_TEST),mips)
+DSO_LDOPTS = -shared
+endif
+ifeq ($(OS_TEST),pmax)
+DSO_LDOPTS = -shared
+endif
+
+MKSHLIB = $(LD) $(DSO_LDOPTS)
+
+G++INCLUDES = -I/usr/include/g++
diff --git a/config/Rhapsody.mk b/config/Rhapsody.mk
index 37ef1e61..e2fe2184 100644
--- a/config/Rhapsody.mk
+++ b/config/Rhapsody.mk
@@ -21,19 +21,21 @@
include $(MOD_DEPTH)/config/UNIX.mk
-CC = cc
+CC = cc
ifeq ($(OS_RELEASE),5.0)
-CCC = cc++
+CCC = cc++
else
-CCC = c++
+CCC = c++
endif
RANLIB = ranlib
-OS_REL_CFLAGS = -Dppc
+ifeq (86,$(findstring 86,$(OS_TEST)))
+OS_REL_CFLAGS = -mno-486 -Di386
+CPU_ARCH = i386
+else
+OS_REL_CFLAGS = -Dppc
CPU_ARCH = ppc
-
-#OS_REL_CFLAGS = -mno-486 -Di386
-#CPU_ARCH = x86
+endif
# "Commons" are tentative definitions in a global scope, like this:
# int x;
@@ -45,20 +47,16 @@ CPU_ARCH = ppc
# definitions so that the linker can catch multiply-defined symbols.
# Also, common symbols are not allowed with Rhapsody dynamic libraries.
-ifdef USE_AUTOCONF
-OS_CFLAGS = $(DSO_CFLAGS)
-else
OS_CFLAGS = $(DSO_CFLAGS) $(OS_REL_CFLAGS) -Wmost -fno-common -pipe -DRHAPSODY -DHAVE_STRERROR -DHAVE_BSD_FLOCK
-endif
-DEFINES += -D_PR_LOCAL_THREADS_ONLY -D_PR_NEED_FAKE_POLL
+DEFINES += -D_PR_LOCAL_THREADS_ONLY
ARCH = rhapsody
# May override this with -bundle to create a loadable module.
-DSO_LDOPTS = -dynamiclib
+DSO_LDOPTS = -dynamiclib -compatibility_version 1 -current_version 1 -all_load
MKSHLIB = $(CC) -arch $(CPU_ARCH) $(DSO_LDOPTS)
DLL_SUFFIX = dylib
-#G++INCLUDES = -I/usr/include/g++
+G++INCLUDES = -I/usr/include/g++
diff --git a/config/SCOOS.mk b/config/SCOOS.mk
index 8890f551..c1d24468 100644
--- a/config/SCOOS.mk
+++ b/config/SCOOS.mk
@@ -33,12 +33,7 @@ DEFINES += -D_PR_LOCAL_THREADS_ONLY
# -DSCO - Changes to Netscape source (consistent with AIX, LINUX, etc..)
# -Dsco - Needed for /usr/include/X11/*
#
-ifdef USE_AUTOCONF
-OS_CFLAGS
-else
OS_CFLAGS = -DSYSV -D_SVID3 -DHAVE_STRERROR -D_PR_NEED_H_ERRNO -DSCO -Dsco
-endif
-
#OS_LIBS = -lpmapi -lsocket -lc
MKSHLIB = $(LD) $(DSO_LDOPTS)
diff --git a/config/SINIX.mk b/config/SINIX.mk
index 6cf899e3..1be48be5 100644
--- a/config/SINIX.mk
+++ b/config/SINIX.mk
@@ -70,11 +70,7 @@ RANLIB = /bin/true
NOMD_OS_CFLAGS = $(ODD_CFLAGS)
# we do not have -MDupdate ...
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
OS_CFLAGS = $(NOMD_OS_CFLAGS)
-endif
OS_LIBS = -lsocket -lnsl -lresolv -ldl -lc
NOSUCHFILE = /no-such-file
diff --git a/config/SunOS.mk b/config/SunOS.mk
index 9aca9f61..0a3b0c40 100644
--- a/config/SunOS.mk
+++ b/config/SunOS.mk
@@ -20,7 +20,7 @@
# 4 and 5 are vastly different, so we use 2 different files.
#
ifeq ($(basename $(OS_RELEASE)),4.1)
-include $(topsrcdir)/config/SunOS4.mk
+include $(MOD_DEPTH)/config/SunOS4.mk
else
-include $(topsrcdir)/config/SunOS5.mk
+include $(MOD_DEPTH)/config/SunOS5.mk
endif
diff --git a/config/SunOS4.mk b/config/SunOS4.mk
index c0aa387d..9723732d 100644
--- a/config/SunOS4.mk
+++ b/config/SunOS4.mk
@@ -26,6 +26,7 @@ include $(MOD_DEPTH)/config/UNIX.mk
DLL_SUFFIX = so.1.0
CC = gcc
+CCC = g++
COMPILER_TAG = _gcc
RANLIB = ranlib
@@ -35,11 +36,7 @@ CPU_ARCH = sparc
DEFINES += -D_PR_LOCAL_THREADS_ONLY
# Purify doesn't like -MDupdate
NOMD_OS_CFLAGS = -Wall -Wno-format -DSUNOS4
-ifdef USE_AUTOCONF
-OS_CFLAGS = $(DSO_CFLAGS)
-else
OS_CFLAGS = $(DSO_CFLAGS) $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
-endif
MKSHLIB = $(LD) $(DSO_LDOPTS)
diff --git a/config/SunOS5.mk b/config/SunOS5.mk
index 8801afbf..4f7bd714 100644
--- a/config/SunOS5.mk
+++ b/config/SunOS5.mk
@@ -26,48 +26,36 @@ include $(MOD_DEPTH)/config/UNIX.mk
# Temporary define for the Client; to be removed when binary release is used
#
ifdef MOZILLA_CLIENT
+ifneq ($(USE_PTHREADS),1)
LOCAL_THREADS_ONLY = 1
+endif
ifndef NS_USE_NATIVE
NS_USE_GCC = 1
endif
endif
#
-# The default implementation strategy on Solaris is global threads only.
-# Local threads only and pthreads are also available.
+# The default implementation strategy on Solaris is pthreads.
+# Global threads only and local threads only are also available.
#
-ifeq ($(USE_PTHREADS),1)
- IMPL_STRATEGY = _PTH
+ifeq ($(GLOBAL_THREADS_ONLY),1)
+ IMPL_STRATEGY = _NATIVE
+ DEFINES += -D_PR_GLOBAL_THREADS_ONLY
else
ifeq ($(LOCAL_THREADS_ONLY),1)
- IMPL_STRATEGY = _LOCAL
+ IMPL_STRATEGY = _EMU
DEFINES += -D_PR_LOCAL_THREADS_ONLY
else
- DEFINES += -D_PR_GLOBAL_THREADS_ONLY
+ USE_PTHREADS = 1
+ IMPL_STRATEGY = _PTH
endif
endif
-#
-# XXX
-# Temporary define for the Client; to be removed when binary release is used
-#
-ifdef MOZILLA_CLIENT
-IMPL_STRATEGY =
-endif
-
ifdef NS_USE_GCC
CC = gcc -Wall
CCC = g++ -Wall
-#
-# XXX
-# Temporary define for the Client; to be removed when binary release is used
-#
-ifdef MOZILLA_CLIENT
-#COMPILER_TAG = _gcc
-else
COMPILER_TAG = _gcc
-endif
-#ASFLAGS += -x assembler-with-cpp
+ASFLAGS += -x assembler-with-cpp
ifdef NO_MDUPDATE
OS_CFLAGS = $(NOMD_OS_CFLAGS)
else
@@ -97,7 +85,6 @@ OS_DEFINES = -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS
ifeq ($(OS_TEST),i86pc)
CPU_ARCH = x86
-CPU_ARCH_TAG = _i86pc
OS_DEFINES += -Di386
# The default debug format, DWARF (-g), is not supported by gcc
# on i386-ANY-sysv4/solaris, but the stabs format is. It is
@@ -111,21 +98,20 @@ endif
else
CPU_ARCH = sparc
endif
+CPU_ARCH_TAG = _$(CPU_ARCH)
ifeq (5.5,$(findstring 5.5,$(OS_RELEASE)))
OS_DEFINES += -DSOLARIS2_5
+else
+OS_DEFINES += -D_PR_HAVE_OFF64_T
endif
ifneq ($(LOCAL_THREADS_ONLY),1)
-OS_DEFINES += -D_REENTRANT
+OS_DEFINES += -D_REENTRANT -DHAVE_POINTER_LOCALTIME_R
endif
# Purify doesn't like -MDupdate
-ifdef USE_AUTOCONF
-NOMD_OS_CFLAGS = $(DSO_CFLAGS) #-DSOLARIS
-else
NOMD_OS_CFLAGS = $(DSO_CFLAGS) $(OS_DEFINES) $(SOL_CFLAGS)
-endif
MKSHLIB = $(LD) $(DSO_LDOPTS)
diff --git a/config/UNIX.mk b/config/UNIX.mk
index af93ac8d..d822543f 100644
--- a/config/UNIX.mk
+++ b/config/UNIX.mk
@@ -15,13 +15,13 @@
# Reserved.
#
+PR_UNIXOS = 1
XP_DEFINE = -DXP_UNIX
OBJ_SUFFIX = o
LIB_SUFFIX = a
DLL_SUFFIX = so
AR = ar cr $@
-ifndef USE_AUTOCONF
ifdef BUILD_OPT
OPTIMIZER = -O
DEFINES = -UDEBUG -DNDEBUG
@@ -33,8 +33,11 @@ OBJDIR_TAG = _DBG
endif
# Name of the binary code directories
+ifdef MOZILLA_CLIENT
+OBJDIR_NAME = $(OS_CONFIG)$(CPU_ARCH_TAG)$(OBJDIR_TAG).OBJ
+else
OBJDIR_NAME = $(OS_CONFIG)$(CPU_ARCH_TAG)$(COMPILER_TAG)$(IMPL_STRATEGY)$(OBJDIR_TAG).OBJ
-endif # !USE_AUTOCONF
+endif
MKDEPEND_DIR = $(DEPTH)/config/mkdepend
MKDEPEND = $(MKDEPEND_DIR)/$(OBJDIR_NAME)/mkdepend
diff --git a/config/UNIXWARE.mk b/config/UNIXWARE.mk
index c2b14602..f15a5a41 100644
--- a/config/UNIXWARE.mk
+++ b/config/UNIXWARE.mk
@@ -33,11 +33,7 @@ CCC = $(NSDEPTH)/build/hcpp
RANLIB = true
DEFINES += -D_PR_LOCAL_THREADS_ONLY
-ifdef USE_AUTOCONF
-OS_CFLAGS =
-else
OS_CFLAGS = -DSVR4 -DSYSV -DUNIXWARE
-endif
MKSHLIB = $(LD) $(DSO_LDOPTS)
DSO_LDOPTS = -G
diff --git a/config/WIN32.mk b/config/WIN32.mk
index a7d7e173..138755fe 100644
--- a/config/WIN32.mk
+++ b/config/WIN32.mk
@@ -29,22 +29,6 @@ ifdef PR_CLIENT_BUILD_WINDOWS
SHELL = $(MOZ_TOOLS_FLIPPED)/bin/shmsdos.exe
endif
-#
-# On NT, we use static thread local storage by default because it
-# gives us better performance. However, we can't use static TLS
-# on Alpha NT because the Alpha version of MSVC does not seem to
-# support the -GT flag, which is necessary to make static TLS safe
-# for fibers.
-#
-# On Win95, we use the TlsXXX() functions by default because that
-# allows us to load the NSPR DLL at run time using LoadLibrary().
-#
-ifeq ($(OS_TARGET),WINNT)
-ifneq ($(CPU_ARCH),ALPHA)
-USE_STATIC_TLS = 1
-endif
-endif
-
CC = cl
CCC = cl
LINK = link
@@ -96,35 +80,36 @@ OPTIMIZER = -Od -Z7
DEFINES = -DDEBUG -D_DEBUG -UNDEBUG
DLLFLAGS = -DEBUG -DEBUGTYPE:CV -OUT:"$@"
-ifeq ($(MOZ_BITS),32)
ifdef GLOWCODE
-ifdef MOZ_DEBUG
DLLFLAGS = -DEBUG -DEBUGTYPE:both -INCLUDE:_GlowCode -OUT:"$@"
endif
-endif
-endif
OBJDIR_TAG = _DBG
LDFLAGS = -DEBUG -DEBUGTYPE:CV
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 fibers on NT. Therefore, if we use static local
-# storage (i.e., __declspec(thread) variables), we need the -GT
+# 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)
-ifeq ($(USE_STATIC_TLS),1)
OS_CFLAGS += -GT
-endif
ifeq ($(CPU_ARCH),x86)
OS_CFLAGS += -G5
endif
diff --git a/config/config.mk b/config/config.mk
index ce3f5432..741cd1a7 100644
--- a/config/config.mk
+++ b/config/config.mk
@@ -16,18 +16,14 @@
# Reserved.
#
-ifndef topsrcdir
-topsrcdir = $(MOD_DEPTH)
-endif
-
# Configuration information for building in the NSPR source module
# Define an include-at-most-once-flag
NSPR_CONFIG_MK = 1
-include $(topsrcdir)/config/module.df
+include $(MOD_DEPTH)/config/module.df
-include $(topsrcdir)/config/arch.mk
+include $(MOD_DEPTH)/config/arch.mk
ifndef NSDEPTH
NSDEPTH = $(MOD_DEPTH)/..
@@ -46,29 +42,15 @@ NFSPWD = $(MOD_DEPTH)/config/nfspwd
LIBNSPR = $(DIST)/lib/libnspr.$(LIB_SUFFIX)
PURELIBNSPR = $(DIST)/lib/libpurenspr.$(LIB_SUFFIX)
-CFLAGS = $(OPTIMIZER) $(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) \
- $(XCFLAGS)
+CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+CCCFLAGS = $(CCC_ONLY_FLAGS) $(OPTIMIZER) $(OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
# For purify
-NOMD_CFLAGS = $(OPTIMIZER) $(NOMD_OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) \
- $(XCFLAGS)
-
-ifdef USE_AUTOCONF
-OPTIMIZER = $(ACCFLAGS)
-DEFINES += -UDEBUG -DNDEBUG -DTRIMMED
-endif
+NOMD_CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
-ifdef MOZ_DEBUG
-ifdef USE_AUTOCONF
-OPTIMIZER = $(ACCFLAGS)
-else
-OPTIMIZER = -g
-endif
-JAVA_OPTIMIZER = -g
-DEFINES = -DDEBUG -UNDEBUG -DDEBUG_$(shell $(WHOAMI)) -DTRACING
-XBCFLAGS = -FR$*
-endif
-
-include $(topsrcdir)/config/$(OS_TARGET).mk
+include $(MOD_DEPTH)/config/$(OS_TARGET).mk
# Figure out where the binary code lives.
BUILD = $(OBJDIR_NAME)
@@ -79,18 +61,8 @@ MOZ_INCL = $(NSDEPTH)/dist/public/win16
MOZ_DIST = $(NSDEPTH)/dist/WIN16D_D.OBJ
endif
-ifdef USE_AUTOCONF
-EMACS = $(ACEMACS)
-PERL = $(ACPERL)
-RANLIB = $(ACRANLIB)
-UNZIP_PROG = $(ACUNZIP)
-WHOAMI = $(ACWHOAMI)
-ZIP_PROG = $(ACZIP)
-DEPENDENCIES = .md
-else
VPATH = $(OBJDIR)
DEPENDENCIES = $(OBJDIR)/.md
-endif
ifdef BUILD_DEBUG_GC
DEFINES += -DDEBUG_GC
diff --git a/config/now.c b/config/now.c
new file mode 100644
index 00000000..0f270d98
--- /dev/null
+++ b/config/now.c
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(XP_UNIX)
+#include <sys/time.h>
+#elif defined(WIN32)
+#include <sys/timeb.h>
+#else
+#error "Architecture not supported"
+#endif
+
+
+int main(int argc, char **argv)
+{
+#if defined(XP_UNIX)
+ long long now;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ now = ((1000000LL) * tv.tv_sec) + (long long)tv.tv_usec;
+#if defined(OSF1)
+ return fprintf(stdout, "%ld", now);
+#else
+ return fprintf(stdout, "%lld", now);
+#endif
+
+#elif defined(WIN32)
+ __int64 now;
+ struct timeb b;
+ ftime(&b);
+ now = b.time;
+ now *= 1000000;
+ now += (1000 * b.millitm);
+ return fprintf(stdout, "%I64d", now);
+#else
+#error "Architecture not supported"
+#endif
+} /* main */
+
+/* now.c */
diff --git a/config/nsinstall.c b/config/nsinstall.c
index 75acbfcc..8e48b357 100644
--- a/config/nsinstall.c
+++ b/config/nsinstall.c
@@ -24,21 +24,26 @@
#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
#include <assert.h>
#include <fcntl.h>
-#include <errno.h>
#include <grp.h>
#include <pwd.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utime.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#ifdef USE_REENTRANT_LIBC
+#include "libc_r.h"
+#endif /* USE_REENTRANT_LIBC */
+
#include "pathsub.h"
#define HAVE_LCHOWN
-#if defined(AIX) || defined(BSDI) || defined(HPUX) || defined(linux) || defined(SUNOS4) || defined(SCO) || defined(UNIXWARE) || defined(RHAPSODY)
+#if defined(AIX) || defined(BSDI) || defined(HPUX) || defined(LINUX) || defined(SUNOS4) || defined(SCO) || defined(UNIXWARE) || defined(RHAPSODY)
#undef HAVE_LCHOWN
#endif
@@ -50,7 +55,7 @@
#define GETCWD_CAN_MALLOC
#endif
-#ifdef linux
+#ifdef LINUX
#include <getopt.h>
#endif
@@ -70,7 +75,7 @@ usage(void)
fprintf(stderr,
"usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
" %*s [-DdltR] file [file ...] directory\n",
- program, strlen(program), "");
+ program, (int)strlen(program), "");
exit(2);
}
@@ -79,8 +84,7 @@ mkdirs(char *path, mode_t mode)
{
char *cp;
struct stat sb;
- int res;
-
+
while (*path == '/' && path[1] == '/')
path++;
while ((cp = strrchr(path, '/')) && cp[1] == '\0')
@@ -93,11 +97,7 @@ mkdirs(char *path, mode_t mode)
}
*cp = '/';
}
- res = mkdir(path, mode);
- if ((res != 0) && (errno == EEXIST))
- return 0;
- else
- return res;
+ return mkdir(path, mode);
}
static uid_t
@@ -340,3 +340,191 @@ main(int argc, char **argv)
free(todir);
return 0;
}
+
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+
+char *program;
+
+void
+fail(char *format, ...)
+{
+ int error;
+ va_list ap;
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_INIT_R();
+#endif
+
+ error = errno;
+ fprintf(stderr, "%s: ", program);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (error)
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_R(errno);
+ fprintf(stderr, ": %s", r_strerror_r);
+#else
+ fprintf(stderr, ": %s", strerror(errno));
+#endif
+
+ putc('\n', stderr);
+ exit(1);
+}
+
+char *
+getcomponent(char *path, char *name)
+{
+ if (*path == '\0')
+ return 0;
+ if (*path == '/') {
+ *name++ = '/';
+ } else {
+ do {
+ *name++ = *path++;
+ } while (*path != '/' && *path != '\0');
+ }
+ *name = '\0';
+ while (*path == '/')
+ path++;
+ return path;
+}
+
+#ifdef UNIXWARE
+/* Sigh. The static buffer in Unixware's readdir is too small. */
+struct dirent * readdir(DIR *d)
+{
+ static struct dirent *buf = NULL;
+#define MAX_PATH_LEN 1024
+
+
+ if(buf == NULL)
+ buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN)
+;
+ return(readdir_r(d, buf));
+}
+#endif
+
+char *
+ino2name(ino_t ino, char *dir)
+{
+ DIR *dp;
+ struct dirent *ep;
+ char *name;
+
+ dp = opendir("..");
+ if (!dp)
+ fail("cannot read parent directory");
+ for (;;) {
+ if (!(ep = readdir(dp)))
+ fail("cannot find current directory");
+ if (ep->d_ino == ino)
+ break;
+ }
+ name = xstrdup(ep->d_name);
+ closedir(dp);
+ return name;
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ fail("cannot allocate %u bytes", size);
+ return p;
+}
+
+char *
+xstrdup(char *s)
+{
+ return strcpy((char*)xmalloc(strlen(s) + 1), s);
+}
+
+char *
+xbasename(char *path)
+{
+ char *cp;
+
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0')
+ *cp = '\0';
+ if (!cp) return path;
+ return cp + 1;
+}
+
+void
+xchdir(char *dir)
+{
+ if (chdir(dir) < 0)
+ fail("cannot change directory to %s", dir);
+}
+
+int
+relatepaths(char *from, char *to, char *outpath)
+{
+ char *cp, *cp2;
+ int len;
+ char buf[NAME_MAX];
+
+ assert(*from == '/' && *to == '/');
+ for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
+ if (*cp == '\0')
+ break;
+ while (cp[-1] != '/')
+ cp--, cp2--;
+ if (cp - 1 == to) {
+ /* closest common ancestor is /, so use full pathname */
+ len = strlen(strcpy(outpath, to));
+ if (outpath[len] != '/') {
+ outpath[len++] = '/';
+ outpath[len] = '\0';
+ }
+ } else {
+ len = 0;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ strcpy(outpath + len, "../");
+ len += 3;
+ }
+ while ((cp = getcomponent(cp, buf)) != 0) {
+ sprintf(outpath + len, "%s/", buf);
+ len += strlen(outpath + len);
+ }
+ }
+ return len;
+}
+
+void
+reversepath(char *inpath, char *name, int len, char *outpath)
+{
+ char *cp, *cp2;
+ char buf[NAME_MAX];
+ struct stat sb;
+
+ cp = strcpy(outpath + PATH_MAX - (len + 1), name);
+ cp2 = inpath;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ if (strcmp(buf, ".") == 0)
+ continue;
+ if (strcmp(buf, "..") == 0) {
+ if (stat(".", &sb) < 0)
+ fail("cannot stat current directory");
+ name = ino2name(sb.st_ino, "..");
+ len = strlen(name);
+ cp -= len + 1;
+ strcpy(cp, name);
+ cp[len] = '/';
+ free(name);
+ xchdir("..");
+ } else {
+ cp -= 3;
+ strncpy(cp, "../", 3);
+ xchdir(buf);
+ }
+ }
+ strcpy(outpath, cp);
+}
diff --git a/config/pathsub.c b/config/pathsub.c
deleted file mode 100644
index eab73a46..00000000
--- a/config/pathsub.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
-/*
-** Pathname subroutines.
-**
-** Brendan Eich, 8/29/95
-*/
-#include <assert.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include "pathsub.h"
-#ifdef USE_REENTRANT_LIBC
-#include "libc_r.h"
-#endif /* USE_REENTRANT_LIBC */
-
-char *program;
-
-void
-fail(char *format, ...)
-{
- int error;
- va_list ap;
-
-#ifdef USE_REENTRANT_LIBC
- R_STRERROR_INIT_R();
-#endif
-
- error = errno;
- fprintf(stderr, "%s: ", program);
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- if (error)
-
-#ifdef USE_REENTRANT_LIBC
- R_STRERROR_R(errno);
- fprintf(stderr, ": %s", r_strerror_r);
-#else
- fprintf(stderr, ": %s", strerror(errno));
-#endif
-
- putc('\n', stderr);
- exit(1);
-}
-
-char *
-getcomponent(char *path, char *name)
-{
- if (*path == '\0')
- return 0;
- if (*path == '/') {
- *name++ = '/';
- } else {
- do {
- *name++ = *path++;
- } while (*path != '/' && *path != '\0');
- }
- *name = '\0';
- while (*path == '/')
- path++;
- return path;
-}
-
-#ifdef UNIXWARE
-/* Sigh. The static buffer in Unixware's readdir is too small. */
-struct dirent * readdir(DIR *d)
-{
- static struct dirent *buf = NULL;
-#define MAX_PATH_LEN 1024
-
-
- if(buf == NULL)
- buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN)
-;
- return(readdir_r(d, buf));
-}
-#endif
-
-char *
-ino2name(ino_t ino, char *dir)
-{
- DIR *dp;
- struct dirent *ep;
- char *name;
-
- dp = opendir("..");
- if (!dp)
- fail("cannot read parent directory");
- for (;;) {
- if (!(ep = readdir(dp)))
- fail("cannot find current directory");
- if (ep->d_ino == ino)
- break;
- }
- name = xstrdup(ep->d_name);
- closedir(dp);
- return name;
-}
-
-void *
-xmalloc(size_t size)
-{
- void *p = malloc(size);
- if (!p)
- fail("cannot allocate %u bytes", size);
- return p;
-}
-
-char *
-xstrdup(char *s)
-{
- return strcpy((char*)xmalloc(strlen(s) + 1), s);
-}
-
-char *
-xbasename(char *path)
-{
- char *cp;
-
- while ((cp = strrchr(path, '/')) && cp[1] == '\0')
- *cp = '\0';
- if (!cp) return path;
- return cp + 1;
-}
-
-void
-xchdir(char *dir)
-{
- if (chdir(dir) < 0)
- fail("cannot change directory to %s", dir);
-}
-
-int
-relatepaths(char *from, char *to, char *outpath)
-{
- char *cp, *cp2;
- int len;
- char buf[NAME_MAX];
-
- assert(*from == '/' && *to == '/');
- for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
- if (*cp == '\0')
- break;
- while (cp[-1] != '/')
- cp--, cp2--;
- if (cp - 1 == to) {
- /* closest common ancestor is /, so use full pathname */
- len = strlen(strcpy(outpath, to));
- if (outpath[len] != '/') {
- outpath[len++] = '/';
- outpath[len] = '\0';
- }
- } else {
- len = 0;
- while ((cp2 = getcomponent(cp2, buf)) != 0) {
- strcpy(outpath + len, "../");
- len += 3;
- }
- while ((cp = getcomponent(cp, buf)) != 0) {
- sprintf(outpath + len, "%s/", buf);
- len += strlen(outpath + len);
- }
- }
- return len;
-}
-
-void
-reversepath(char *inpath, char *name, int len, char *outpath)
-{
- char *cp, *cp2;
- char buf[NAME_MAX];
- struct stat sb;
-
- cp = strcpy(outpath + PATH_MAX - (len + 1), name);
- cp2 = inpath;
- while ((cp2 = getcomponent(cp2, buf)) != 0) {
- if (strcmp(buf, ".") == 0)
- continue;
- if (strcmp(buf, "..") == 0) {
- if (stat(".", &sb) < 0)
- fail("cannot stat current directory");
- name = ino2name(sb.st_ino, "..");
- len = strlen(name);
- cp -= len + 1;
- strcpy(cp, name);
- cp[len] = '/';
- free(name);
- xchdir("..");
- } else {
- cp -= 3;
- strncpy(cp, "../", 3);
- xchdir(buf);
- }
- }
- strcpy(outpath, cp);
-}
diff --git a/config/rules.mk b/config/rules.mk
index 29f991fc..fc1fdc14 100644
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -47,12 +47,9 @@
# ($OBJDIR automatically prepended to it)
#
################################################################################
-ifndef topsrcdir
-topsrcdir = $(MOD_DEPTH)
-endif
ifndef NSPR_CONFIG_MK
-include $(topsrcdir)/config/config.mk
+include $(MOD_DEPTH)/config/config.mk
endif
#
@@ -90,8 +87,10 @@ LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a
else
+ifdef MKSHLIB
SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
endif
+endif
ifdef HAVE_PURIFY
ifdef DSO_BACKEND
PURE_LIBRARY = $(OBJDIR)/purelib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
@@ -151,10 +150,6 @@ ALL_TRASH = $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
$(NOSUCHFILE) \
so_locations
-ifdef USE_AUTOCONF
-ALL_TRASH := $(filter-out $(OBJDIR), $(ALL_TRASH))
-endif
-
ifdef DIRS
LOOP_OVER_DIRS = \
@for d in $(DIRS); do \
@@ -187,11 +182,7 @@ clean::
+$(LOOP_OVER_DIRS)
clobber::
-ifdef USE_AUTOCONF
- rm -rf $(OBJS) $(TARGETS) $(GARBAGE) so_locations $(NOSUCHFILE)
-else
rm -rf $(OBJS) $(TARGETS) $(OBJDIR) $(GARBAGE) so_locations $(NOSUCHFILE)
-endif
+$(LOOP_OVER_DIRS)
realclean clobber_all::
@@ -326,9 +317,9 @@ endif
$(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), WINNT)
- $(CCC) -Fo$@ -c $(CFLAGS) $<
+ $(CCC) -Fo$@ -c $(CCCFLAGS) $<
else
- $(CCC) -o $@ -c $(CFLAGS) $<
+ $(CCC) -o $@ -c $(CCCFLAGS) $<
endif
WCCFLAGS1 = $(subst /,\\,$(CFLAGS))
@@ -346,18 +337,18 @@ else
$(CC) -Fo$@ -c $(CFLAGS) $*.c
endif
else
- $(CC) -o $@ -c $(CFLAGS) $<
+ $(CC) -o $@ -c $(CFLAGS) $*.c
endif
$(OBJDIR)/%.$(OBJ_SUFFIX): %.s
@$(MAKE_OBJDIR)
- $(AS) -o $@ $(ASFLAGS) -c $<
+ $(AS) -o $@ $(ASFLAGS) -c $*.s
%.i: %.c
$(CC) -C -E $(CFLAGS) $< > $*.i
%: %.pl
- rm -f $@; cp $< $@; chmod +x $@
+ rm -f $@; cp $*.pl $@; chmod +x $@
################################################################################
# Special gmake rules.
@@ -375,3 +366,12 @@ $(OBJDIR)/%.$(OBJ_SUFFIX): %.s
# name already exists.
#
.PHONY: all alltags clean export install libs realclean release
+
+#
+# List the target pattern of an implicit rule as a dependency of the
+# special target .PRECIOUS to preserve intermediate files made by
+# implicit rules whose target patterns match that file's name.
+# (See GNU Make documentation, Edition 0.51, May 1996, Sec. 10.4,
+# p. 107.)
+#
+.PRECIOUS: $(OBJDIR)/%.$(OBJ_SUFFIX)
diff --git a/lib/Makefile b/lib/Makefile
index 8b062c3f..cf279130 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,7 +23,7 @@ export NSPR20=1
include $(MOD_DEPTH)/config/config.mk
-DIRS = ds libc msgc
+DIRS = ds libc
include $(MOD_DEPTH)/config/rules.mk
diff --git a/lib/ds/Makefile b/lib/ds/Makefile
index e4071d95..23e8c7bc 100644
--- a/lib/ds/Makefile
+++ b/lib/ds/Makefile
@@ -106,7 +106,9 @@ include $(MOD_DEPTH)/config/rules.mk
export:: $(TARGETS)
$(INSTALL) -m 444 $(HEADERS) $(DIST)/include
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
+ifdef SHARED_LIBRARY
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
+endif
ifeq ($(MOZ_BITS),16)
$(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
diff --git a/lib/ds/plevent.c b/lib/ds/plevent.c
index d164955e..32271025 100644
--- a/lib/ds/plevent.c
+++ b/lib/ds/plevent.c
@@ -192,7 +192,7 @@ PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event)
int i, entryCount = self->monitor->entryCount;
event->synchronousResult = (void*)PR_TRUE;
- PR_PostEvent(self, event);
+ PL_PostEvent(self, event);
/* We need to temporarily give up our event queue monitor if
we're holding it, otherwise, the thread we're going to wait
for notification from won't be able to enter it to process
@@ -330,7 +330,7 @@ PL_RevokeEvents(PLEventQueue* self, void* owner)
{
PRCList* qp = self->queue.next;
while (qp != &self->queue) {
- PREvent* event = PR_EVENT_PTR(qp);
+ PLEvent* event = PR_EVENT_PTR(qp);
qp = qp->next;
PR_ASSERT(event->owner != owner);
}
diff --git a/lib/ds/plhash.c b/lib/ds/plhash.c
index e8dd2eda..fb4d5c1f 100644
--- a/lib/ds/plhash.c
+++ b/lib/ds/plhash.c
@@ -60,7 +60,7 @@ DefaultFreeTable(void *pool, void *item)
#pragma unused (pool)
#endif
- PR_DELETE(item);
+ PR_Free(item);
}
static PLHashEntry * PR_CALLBACK
@@ -81,7 +81,7 @@ DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
#endif
if (flag == HT_FREE_ENTRY)
- PR_DELETE(he);
+ PR_Free(he);
}
static PLHashAllocOps defaultHashAllocOps = {
@@ -92,10 +92,10 @@ static PLHashAllocOps defaultHashAllocOps = {
PR_IMPLEMENT(PLHashTable *)
PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
PLHashComparator keyCompare, PLHashComparator valueCompare,
- PLHashAllocOps *allocOps, void *allocPriv)
+ const PLHashAllocOps *allocOps, void *allocPriv)
{
PLHashTable *ht;
- PRUint32 nb;
+ PRSize nb;
if (n <= MINBUCKETS) {
n = MINBUCKETSLOG2;
@@ -113,7 +113,7 @@ PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
memset(ht, 0, sizeof *ht);
ht->shift = PL_HASH_BITS - n;
n = 1 << n;
-#if defined(XP_PC) && !defined(_WIN32)
+#if defined(WIN16)
if (n > 16000) {
(*allocOps->freeTable)(allocPriv, ht);
return 0;
@@ -140,7 +140,7 @@ PL_HashTableDestroy(PLHashTable *ht)
{
PRUint32 i, n;
PLHashEntry *he, *next;
- PLHashAllocOps *allocOps = ht->allocOps;
+ const PLHashAllocOps *allocOps = ht->allocOps;
void *allocPriv = ht->allocPriv;
n = NBUCKETS(ht);
@@ -201,7 +201,7 @@ PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
{
PRUint32 i, n;
PLHashEntry *he, *next, **oldbuckets;
- PRUint32 nb;
+ PRSize nb;
/* Grow the table if it is overloaded */
n = NBUCKETS(ht);
@@ -211,7 +211,7 @@ PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
#endif
ht->shift--;
oldbuckets = ht->buckets;
-#if defined(XP_PC) && !defined(_WIN32)
+#if defined(WIN16)
if (2 * n > 16000)
return 0;
#endif /* WIN16 */
@@ -280,7 +280,7 @@ PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
{
PRUint32 i, n;
PLHashEntry *next, **oldbuckets;
- PRUint32 nb;
+ PRSize nb;
*hep = he->next;
(*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
diff --git a/lib/ds/plhash.h b/lib/ds/plhash.h
index bbca07d7..24898d2c 100644
--- a/lib/ds/plhash.h
+++ b/lib/ds/plhash.h
@@ -21,7 +21,6 @@
/*
* API to portable hash table code.
*/
-#include <stddef.h>
#include <stdio.h>
#include "prtypes.h"
@@ -30,10 +29,10 @@ PR_BEGIN_EXTERN_C
typedef struct PLHashEntry PLHashEntry;
typedef struct PLHashTable PLHashTable;
typedef PRUint32 PLHashNumber;
-#define PL_HASH_BITS 32
+#define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */
typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key);
typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2);
-typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg);
+typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn index, void *arg);
/* Flag bits in PLHashEnumerator's return value */
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
@@ -65,7 +64,7 @@ struct PLHashTable {
PLHashFunction keyHash; /* key hash function */
PLHashComparator keyCompare; /* key comparison function */
PLHashComparator valueCompare; /* value comparison function */
- PLHashAllocOps *allocOps; /* allocation operations */
+ const PLHashAllocOps *allocOps; /* allocation operations */
void *allocPriv; /* allocation private data */
#ifdef HASHMETER
PRUint32 nlookups; /* total number of lookups */
@@ -80,24 +79,13 @@ struct PLHashTable {
* If allocOps is null, use default allocator ops built on top of malloc().
*/
PR_EXTERN(PLHashTable *)
-PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
+PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash,
PLHashComparator keyCompare, PLHashComparator valueCompare,
- PLHashAllocOps *allocOps, void *allocPriv);
+ const PLHashAllocOps *allocOps, void *allocPriv);
PR_EXTERN(void)
PL_HashTableDestroy(PLHashTable *ht);
-/* Low level access methods */
-PR_EXTERN(PLHashEntry **)
-PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
-
-PR_EXTERN(PLHashEntry *)
-PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
- const void *key, void *value);
-
-PR_EXTERN(void)
-PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
-
/* Higher level access methods */
PR_EXTERN(PLHashEntry *)
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
@@ -105,27 +93,39 @@ PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
PR_EXTERN(PRBool)
PL_HashTableRemove(PLHashTable *ht, const void *key);
-PR_EXTERN(PRIntn)
-PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
-
PR_EXTERN(void *)
PL_HashTableLookup(PLHashTable *ht, const void *key);
PR_EXTERN(PRIntn)
-PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
+PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
/* General-purpose C string hash function. */
PR_EXTERN(PLHashNumber)
PL_HashString(const void *key);
/* Compare strings using strcmp(), return true if equal. */
-PR_EXTERN(int)
+PR_EXTERN(PRIntn)
PL_CompareStrings(const void *v1, const void *v2);
/* Stub function just returns v1 == v2 */
PR_EXTERN(PRIntn)
PL_CompareValues(const void *v1, const void *v2);
+/* Low level access methods */
+PR_EXTERN(PLHashEntry **)
+PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
+
+PR_EXTERN(PLHashEntry *)
+PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
+ const void *key, void *value);
+
+PR_EXTERN(void)
+PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
+
+/* This can be trivially implemented using PL_HashTableEnumerateEntries. */
+PR_EXTERN(PRIntn)
+PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
+
PR_END_EXTERN_C
#endif /* plhash_h___ */
diff --git a/lib/libc/src/Makefile b/lib/libc/src/Makefile
index 1e5c546a..e8550b9e 100644
--- a/lib/libc/src/Makefile
+++ b/lib/libc/src/Makefile
@@ -31,6 +31,7 @@ endif
INCLUDES = -I$(DIST)/include
CSRCS =\
+ plvrsion.c \
strlen.c \
strcpy.c \
strdup.c \
@@ -96,13 +97,52 @@ endif
include $(MOD_DEPTH)/config/rules.mk
#
+# Version information generation (begin)
+#
+RM = rm
+ECHO = echo
+INCLUDES = -I$(DIST)/include
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = libplc$(MOD_VERSION).$(DLL_SUFFIX)
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date)
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(OS_ARCH), WINNT)
+ SUF = i64
+ SH_QUOTE =
+else
+ SUF = LL
+ SH_QUOTE = "
+endif
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) $(SH_QUOTE)#define _BUILD_STRING \"$(SH_DATE)\"$(SH_QUOTE) > $(TINC)
+ @$(ECHO) $(SH_QUOTE)#define _BUILD_TIME $(SH_NOW)$(SUF)$(SH_QUOTE) >> $(TINC)
+ @$(ECHO) $(SH_QUOTE)#define _PRODUCTION \"$(PROD)\"$(SH_QUOTE) >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): $(TINC)
+ifeq ($(OS_ARCH), WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) plvrsion.c
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) plvrsion.c
+endif
+#
+# Version information generation (end)
+#
+
+#
# The Client build wants the shared libraries in $(DIST)/bin,
# so we also install them there.
#
export:: $(TARGETS)
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
+ifdef SHARED_LIBRARY
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
+endif
ifeq ($(MOZ_BITS),16)
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
diff --git a/lib/libc/src/plerror.c b/lib/libc/src/plerror.c
index 840af143..48f3f959 100644
--- a/lib/libc/src/plerror.c
+++ b/lib/libc/src/plerror.c
@@ -100,6 +100,10 @@ static const char *tags[] =
"PR_ALREADY_INITIATED_ERROR",
"PR_GROUP_EMPTY_ERROR",
"PR_INVALID_STATE_ERROR",
+ "PR_NETWORK_DOWN_ERROR",
+ "PR_SOCKET_SHUTDOWN_ERROR",
+ "PR_CONNECT_ABORTED_ERROR",
+ "PR_HOST_UNREACHABLE_ERROR",
"PR_MAX_ERROR"
};
diff --git a/lib/libc/src/plvrsion.c b/lib/libc/src/plvrsion.c
new file mode 100644
index 00000000..ea3b9c8b
--- /dev/null
+++ b/lib/libc/src/plvrsion.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#define _BUILD_TIME 0
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+
+static PRVersionDescription prVersionDescription_libplc21 =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "http://www.mozilla.org/NPL/",
+ /* specialString */ ""
+};
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+ return &prVersionDescription_libplc21;
+} /* versionEntryPointType */
+
+/* prvrsion.c */
+
diff --git a/lib/msgc/include/gcint.h b/lib/msgc/include/gcint.h
index 741e1c87..3da3e443 100644
--- a/lib/msgc/include/gcint.h
+++ b/lib/msgc/include/gcint.h
@@ -75,7 +75,7 @@ extern RootFinder *_pr_rootFinders;
typedef struct CollectorTypeStr {
GCType gctype;
- uint32 flags;
+ PRUint32 flags;
} CollectorType;
#define GC_MAX_TYPES 256
diff --git a/lib/msgc/include/prgc.h b/lib/msgc/include/prgc.h
index 9acb44d0..5c471a99 100644
--- a/lib/msgc/include/prgc.h
+++ b/lib/msgc/include/prgc.h
@@ -65,8 +65,8 @@ typedef PRInt32 (*PRWalkFun)(void GCPTR* obj, void* data);
*/
typedef struct GCType {
/*
- ** Scan an object that is in the GC heap and call PR_LiveObject on
- ** all of the pointers in it. If this slot is null then the object
+ ** Scan an object that is in the GC heap and call GCInfo.livePointer
+ ** on all of the pointers in it. If this slot is null then the object
** won't be scanned (i.e. it has no embedded pointers).
*/
void (PR_CALLBACK *scan)(void GCPTR *obj);
@@ -353,7 +353,7 @@ PR_EXTERN(PRBool) PR_GC_In_Heap(void GCPTR *object);
/*
** Simple bounds check to see if a pointer is anywhere near the GC heap.
-** Used to avoid calls to PR_ProcessRoot and PR_LiveObject by object
+** Used to avoid calls to PR_ProcessRoot and GCInfo.livePointer by object
** scanning code.
*/
#if !defined(XP_PC) || defined(_WIN32)
diff --git a/lib/msgc/src/Makefile b/lib/msgc/src/Makefile
index 05413af9..6164d38d 100644
--- a/lib/msgc/src/Makefile
+++ b/lib/msgc/src/Makefile
@@ -105,7 +105,9 @@ include $(MOD_DEPTH)/config/rules.mk
export:: $(TARGETS)
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
+ifdef SHARED_LIBRARY
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
+endif
ifeq ($(MOZ_BITS),16)
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
diff --git a/lib/msgc/src/prmsgc.c b/lib/msgc/src/prmsgc.c
index 76a9860e..a707092d 100644
--- a/lib/msgc/src/prmsgc.c
+++ b/lib/msgc/src/prmsgc.c
@@ -733,7 +733,10 @@ void ScanScanQ(GCScanQ *iscan)
next = &nextQ;
while (scan->queued) {
_GCTRACE(GC_MARK, ("continue scanQ @ 0x%x (%d)", scan, scan->queued));
- /* Set pointer to current scanQ so that pr_liveObject can find it */
+ /*
+ * Set pointer to current scanQ so that _pr_gcData.livePointer
+ * can find it.
+ */
pScanQ = next;
next->queued = 0;
@@ -1890,7 +1893,7 @@ pr_ConservativeWalkPointer(void* ptr, PRWalkFun walkRootPointer, void* data)
return walkRootPointer(p, data);
}
-static int32 PR_CALLBACK
+static PRInt32 PR_CALLBACK
pr_ConservativeWalkBlock(void **base, PRInt32 count,
PRWalkFun walkRootPointer, void* data)
{
@@ -2083,7 +2086,7 @@ PR_DumpMemory(PRBool detailed)
/******************************************************************************/
-static int32 PR_CALLBACK
+static PRInt32 PR_CALLBACK
pr_DumpRootPointer(PRWord* p, void* data)
{
#ifdef XP_MAC
@@ -2247,7 +2250,7 @@ PRWord* pr_traceObj; /* set this in the debugger, then execute PR_TraceRoot() */
static PRInt32 PR_CALLBACK
pr_TraceRootObject(void* obj, void* data);
-static int32 PR_CALLBACK
+static PRInt32 PR_CALLBACK
pr_TraceRootPointer(PRWord *p, void* data)
{
PRInt32 printTrace = 0;
@@ -3094,6 +3097,12 @@ PR_AllocSimpleMemory(PRWord requestedBytes, PRInt32 tix)
PR_ASSERT( bytes < MAX_ALLOC_SIZE );
#endif
/* Java can ask for objects bigger than 4M, but it won't get them */
+ /*
+ * This check was added because there is a fundamental limit of
+ * the size field maintained by the gc code. Going over the 4M
+ * limit caused some bits to roll over into another bit field,
+ * violating the max segment size and causing a bug.
+ */
if (bytes >= MAX_ALLOC_SIZE) {
return NULL;
}
@@ -3183,7 +3192,7 @@ PR_AllocSimpleMemory(PRWord requestedBytes, PRInt32 tix)
{
PRInt64 now = PR_Now();
double delta;
- int32 bin;
+ PRInt32 bin;
GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
end->allocTime = allocTime;
diff --git a/lib/msgc/src/unixgc.c b/lib/msgc/src/unixgc.c
index 0f8def44..1c36f65b 100644
--- a/lib/msgc/src/unixgc.c
+++ b/lib/msgc/src/unixgc.c
@@ -31,7 +31,7 @@
#if defined(SOLARIS)
#define _MD_MMAP_FLAGS MAP_SHARED
-#elif defined(OSF1) || defined(RELIANTUNIX)
+#elif defined(RELIANTUNIX)
#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED
#else
#define _MD_MMAP_FLAGS MAP_PRIVATE
diff --git a/lib/msgc/tests/Makefile b/lib/msgc/tests/Makefile
index 7ede0d52..e3f4b1c7 100644
--- a/lib/msgc/tests/Makefile
+++ b/lib/msgc/tests/Makefile
@@ -105,7 +105,7 @@ endif
endif
ifeq ($(OS_ARCH), HP-UX)
-LDOPTS += -Wl,+s,+b,$(PWD)/$(DIST)/lib
+LDOPTS += -z -Wl,+s,+b,$(PWD)/$(DIST)/lib
endif
# AIX
diff --git a/lib/prstreams/Makefile b/lib/prstreams/Makefile
index 164878de..1cfaef52 100644
--- a/lib/prstreams/Makefile
+++ b/lib/prstreams/Makefile
@@ -23,59 +23,66 @@ include $(MOD_DEPTH)/config/config.mk
# Disable optimization of the nspr on SunOS4.1.3
ifeq ($(OS_ARCH),SunOS)
-ifeq ($(OS_RELEASE),4.1.3_U1)
-OPTIMIZER =
-endif
+ ifeq ($(OS_RELEASE),4.1.3_U1)
+ OPTIMIZER =
+ endif
endif
+
ifeq ($(OS_ARCH), IRIX)
-CFLAGS += -KPIC
-ifneq ($(OS_RELEASE),5.3)
-CFLAGS += -exceptions
+ CFLAGS += -KPIC
+ ifneq ($(OS_RELEASE),5.3)
+ CFLAGS += -exceptions
+ endif
endif
+
+ifeq ($(OS_ARCH),HP-UX)
+ ifeq (($USE_64),1)
+ CCCFLAGS += +DA2.0W
+ endif
endif
INCLUDES = -I$(DIST)/include -I../../../include
HEADERS = *.h
-CXXSRCS = \
- prstrms.cpp \
+CXXSRCS = \
+ prstrms.cpp \
$(NULL)
OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
ifeq ($(OS_ARCH), WINNT)
-ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
-EXTRA_LIBS = $(DIST)/lib/nspr$(MOD_VERSION).lib
-else
-DLLBASE=/BASE:0x30000000
-RES=$(OBJDIR)/prstrms.res
-RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
-OS_LIBS = user32.lib
-EXTRA_LIBS = $(DIST)/lib/libnspr$(MOD_VERSION).lib
-endif
-else
-ifeq ($(OS_ARCH), AIX)
- ifeq ($(OS_RELEASE), 4.1)
- ifeq ($(CLASSIC_NSPR),1)
- OS_LIBS += -lC -lc
+ ifeq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
+ EXTRA_LIBS = $(DIST)/lib/nspr$(MOD_VERSION).lib
else
- OS_LIBS += -lC_r -lc_r
+ DLLBASE=/BASE:0x30000000
+ RES=$(OBJDIR)/prstrms.res
+ RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
+ OS_LIBS = user32.lib
+ EXTRA_LIBS = $(DIST)/lib/libnspr$(MOD_VERSION).lib
+ endif
+else
+ ifeq ($(OS_ARCH), AIX)
+ ifeq ($(OS_RELEASE), 4.1)
+ ifeq ($(CLASSIC_NSPR),1)
+ OS_LIBS += -lC -lc
+ else
+ OS_LIBS += -lC_r -lc_r
+ endif
+ else
+ ifeq ($(CLASSIC_NSPR),1)
+ MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib -p 0
+ else
+ MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0
+ endif
+ OS_LIBS += -ldl
+ endif
endif
- else
- ifeq ($(CLASSIC_NSPR),1)
- MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib -p 0
+ ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
+ EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)_shr
else
- MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0
+ EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)
endif
- OS_LIBS += -ldl
- endif
-endif
-ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
-EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)_shr
-else
-EXTRA_LIBS = -L$(DIST)/lib -lnspr$(MOD_VERSION)
-endif
endif
# On NCR and SCOOS, we can't link with extra libraries when
@@ -83,14 +90,14 @@ endif
# complain, but we would run into weird problems at run-time.
# Therefore on these platforms, we link just the object files.
ifeq ($(OS_ARCH),NCR)
-EXTRA_LIBS =
+ EXTRA_LIBS =
endif
ifeq ($(OS_ARCH),SCOOS)
-EXTRA_LIBS =
+ EXTRA_LIBS =
endif
ifeq ($(OS_ARCH), UNIXWARE)
-OS_LIBS += -lC
+ OS_LIBS += -lC
endif
LIBRARY_NAME = prstrms
diff --git a/macbuild/NSPR20PPC.mcp b/macbuild/NSPR20PPC.mcp
index edbc8198..57934998 100644
--- a/macbuild/NSPR20PPC.mcp
+++ b/macbuild/NSPR20PPC.mcp
Binary files differ
diff --git a/pr/include/MANIFEST b/pr/include/MANIFEST
index 9cb2adea..6ef1b6d0 100644
--- a/pr/include/MANIFEST
+++ b/pr/include/MANIFEST
@@ -7,6 +7,7 @@ pratom.h
prbit.h
prclist.h
prcmon.h
+prcountr.h
prcvar.h
prdtoa.h
prenv.h
@@ -23,13 +24,16 @@ prmem.h
prmon.h
prmwait.h
prnetdb.h
+prolock.h
prpdce.h
prprf.h
prproces.h
prsystem.h
prthread.h
prtime.h
+prtrace.h
prtypes.h
+prvrsion.h
prwin16.h
obsolete/protypes.h
@@ -39,6 +43,3 @@ obsolete/probslet.h
private/prpriv.h
private/pprio.h
private/pprthred.h
-
-md/prosdep.h
-md/_macos.h
diff --git a/pr/include/md/Makefile b/pr/include/md/Makefile
index afb752ea..a365ef91 100644
--- a/pr/include/md/Makefile
+++ b/pr/include/md/Makefile
@@ -24,7 +24,11 @@ HEADERS = $(wildcard *.h)
include $(MOD_DEPTH)/config/rules.mk
ifeq ($(OS_ARCH),IRIX)
-MDCPUCFG_H = _irix.cfg
+ifeq ($(USE_64), 1)
+MDCPUCFG_H = _irix64.cfg
+else
+MDCPUCFG_H = _irix32.cfg
+endif
endif
ifeq ($(OS_ARCH),WINNT)
@@ -55,12 +59,20 @@ ifeq ($(OS_ARCH),FreeBSD)
MDCPUCFG_H = _freebsd.cfg
endif
+ifeq ($(OS_ARCH),OpenBSD)
+MDCPUCFG_H = _openbsd.cfg
+endif
+
ifeq ($(OS_ARCH),NetBSD)
MDCPUCFG_H = _netbsd.cfg
endif
ifeq ($(OS_ARCH),HP-UX)
-MDCPUCFG_H = _hpux.cfg
+ifeq ($(USE_64), 1)
+MDCPUCFG_H = _hpux64.cfg
+else
+MDCPUCFG_H = _hpux32.cfg
+endif
endif
ifeq ($(OS_ARCH),Linux)
diff --git a/pr/include/md/_aix.h b/pr/include/md/_aix.h
index 7ea19b7f..cc7906c8 100644
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -54,15 +54,31 @@
#define HAVE_DLL
#define USE_DLFCN
#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+/* Timer operations */
+#define AIX_TIMERS
+#if defined(AIX_TIMERS)
+extern PRIntervalTime _MD_AixGetInterval(void);
+#define _MD_GET_INTERVAL _MD_AixGetInterval
+
+extern PRIntervalTime _MD_AixIntervalPerSec(void);
+#define _MD_INTERVAL_PER_SEC _MD_AixIntervalPerSec
+
+#else /* defined(AIX_TIMERS) */
#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#endif /* defined(AIX_TIMERS) */
/* The atomic operations */
#include <sys/atomic_op.h>
#define _PR_HAVE_ATOMIC_OPS
+#define _PR_HAVE_ATOMIC_CAS
#define _MD_INIT_ATOMIC()
#define _MD_ATOMIC_INCREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, 1) + 1)
+#define _MD_ATOMIC_ADD(ptr, val) ((PRInt32)fetch_and_add((atomic_p)ptr, val) + val)
#define _MD_ATOMIC_DECREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, -1) - 1)
#define _MD_ATOMIC_SET(val, newval) _AIX_AtomicSet(val, newval)
@@ -138,6 +154,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_bsdi.h b/pr/include/md/_bsdi.h
index 3e3eca9f..2639b2e3 100644
--- a/pr/include/md/_bsdi.h
+++ b/pr/include/md/_bsdi.h
@@ -37,6 +37,8 @@
#define HAVE_BSD_FLOCK
#define NEED_TIME_R
#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_NO_LARGE_FILES
#if defined(BSDI_2)
#define PROT_NONE 0x0
@@ -110,6 +112,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_darwin.cfg b/pr/include/md/_darwin.cfg
index 73fc491c..a0787fc9 100644
--- a/pr/include/md/_darwin.cfg
+++ b/pr/include/md/_darwin.cfg
@@ -27,8 +27,14 @@
#define RHAPOSDY
#endif
+#if defined(i386)
+#undef IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#else
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
+#endif
+
#define HAVE_LONG_LONG
#undef HAVE_ALIGNED_DOUBLES
#define HAVE_ALIGNED_LONGLONGS 1
@@ -53,6 +59,7 @@
#define PR_BITS_PER_FLOAT 32
#define PR_BITS_PER_DOUBLE 64
#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
#define PR_BITS_PER_BYTE_LOG2 3
#define PR_BITS_PER_SHORT_LOG2 4
@@ -117,3 +124,4 @@
#endif /* NO_NSPR_10_SUPPORT */
#endif /* nspr_cpucfg___ */
+
diff --git a/pr/include/md/_darwin.h b/pr/include/md/_darwin.h
index 052da11f..476b8e38 100644
--- a/pr/include/md/_darwin.h
+++ b/pr/include/md/_darwin.h
@@ -38,24 +38,23 @@
#define _MD_MMAP_FLAGS MAP_PRIVATE
#undef HAVE_STACK_GROWING_UP
-#define HAVE_WEAK_MALLOC_SYMBOLS
-/* do this until I figure out the rhapsody dll stuff. */
#define HAVE_DLL
-#define USE_RLD
-#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_TIMESPEC_HAS_TS_SEC
+#define _PR_NO_LARGE_FILES
#define USE_SETJMP
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
#include <setjmp.h>
#define PR_CONTEXT_TYPE jmp_buf
-#define CONTEXT(_th) ((_th)->md.context)
-
-#define _MD_GET_SP(_th) (_th)->md.context[0]
-#define PR_NUM_GCREGS _JBLEN
+#define CONTEXT(_th) ((_th)->md.context)
+#define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack)
+#define PR_NUM_GCREGS _JBLEN
/*
** Initialize a thread context to run "_main()" when started
@@ -66,7 +65,7 @@
if (setjmp(CONTEXT(_thread))) { \
_main(); \
} \
- _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
}
#define _MD_SWITCH_CONTEXT(_thread) \
@@ -113,6 +112,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -149,14 +184,14 @@ extern void _MD_YIELD(void);
#endif /* ! _PR_PTHREADS */
-extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
-
-#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_EARLY_INIT _MD_EarlyInit
#define _MD_FINAL_INIT _PR_UnixInit
-#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
/*
* We wrapped the select() call. _MD_SELECT refers to the built-in,
diff --git a/pr/include/md/_dgux.cfg b/pr/include/md/_dgux.cfg
index 4fb5dd46..4cde625a 100644
--- a/pr/include/md/_dgux.cfg
+++ b/pr/include/md/_dgux.cfg
@@ -71,9 +71,6 @@
#define PR_ALIGN_OF_DOUBLE 4
#define PR_ALIGN_OF_POINTER 4
-#define _PR_USE_POLL
-#define _PR_POLL_AVAILABLE
-
#ifndef NO_NSPR_10_SUPPORT
#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
diff --git a/pr/include/md/_dgux.h b/pr/include/md/_dgux.h
index 2c3e4f49..f428e03a 100644
--- a/pr/include/md/_dgux.h
+++ b/pr/include/md/_dgux.h
@@ -44,6 +44,8 @@
#define NEED_STRFTIME_LOCK
#define NEED_TIME_R
#define _PR_NEED_STRCASECMP
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
#define USE_SETJMP
diff --git a/pr/include/md/_freebsd.h b/pr/include/md/_freebsd.h
index 916c11c2..6e459fb5 100644
--- a/pr/include/md/_freebsd.h
+++ b/pr/include/md/_freebsd.h
@@ -37,6 +37,8 @@
#define HAVE_DLL
#define USE_DLFCN
#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_NO_LARGE_FILES
#define USE_SETJMP
@@ -106,6 +108,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_hpux.h b/pr/include/md/_hpux.h
index 2675a97e..f9e312a4 100644
--- a/pr/include/md/_hpux.h
+++ b/pr/include/md/_hpux.h
@@ -43,6 +43,9 @@
#ifndef HAVE_STRERROR
#define HAVE_STRERROR
#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
#undef _PR_HAVE_ATOMIC_OPS
@@ -117,6 +120,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -150,8 +189,16 @@ struct _MDCPU {
#define _MD_FINAL_INIT _PR_UnixInit
#endif
+#if defined(HPUX_LW_TIMER)
+extern void _PR_HPUX_LW_IntervalInit(void);
+extern PRIntervalTime _PR_HPUX_LW_GetInterval(void);
+#define _MD_INTERVAL_INIT _PR_HPUX_LW_IntervalInit
+#define _MD_GET_INTERVAL _PR_HPUX_LW_GetInterval
+#define _MD_INTERVAL_PER_SEC() 1000
+#else
#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#endif
/*
* We wrapped the select() call. _MD_SELECT refers to the built-in,
@@ -160,8 +207,6 @@ struct _MDCPU {
#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
-extern void _MD_hpux_install_sigfpe_handler(void);
-
#ifdef HPUX11
extern void _MD_hpux_map_sendfile_error(int err);
#if !defined(_PR_PTHREADS)
diff --git a/pr/include/md/_hpux.cfg b/pr/include/md/_hpux32.cfg
index 885af381..2889f693 100644
--- a/pr/include/md/_hpux.cfg
+++ b/pr/include/md/_hpux32.cfg
@@ -69,9 +69,9 @@
#define PR_ALIGN_OF_DOUBLE 8
#define PR_ALIGN_OF_POINTER 4
-#undef HAVE_LONG_LONG
+#define HAVE_LONG_LONG
#define HAVE_ALIGNED_DOUBLES
-#undef HAVE_ALIGNED_LONGLONGS
+#define HAVE_ALIGNED_LONGLONGS
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_hpux64.cfg b/pr/include/md/_hpux64.cfg
new file mode 100644
index 00000000..f790215c
--- /dev/null
+++ b/pr/include/md/_hpux64.cfg
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef HPUX
+#define HPUX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/pr/include/md/_irix.h b/pr/include/md/_irix.h
index 694b809b..b6b2b034 100644
--- a/pr/include/md/_irix.h
+++ b/pr/include/md/_irix.h
@@ -19,6 +19,13 @@
#ifndef nspr_irix_defs_h___
#define nspr_irix_defs_h___
+#define _PR_HAVE_ATOMIC_CAS
+
+/*
+ * MipsPro assembler defines _LANGUAGE_ASSEMBLY
+ */
+#ifndef _LANGUAGE_ASSEMBLY
+
#include "prclist.h"
#include "prthread.h"
#include <sys/ucontext.h>
@@ -46,6 +53,11 @@
#define HAVE_DLL
#define USE_DLFCN
#define _PR_HAVE_ATOMIC_OPS
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM
+#define _PR_HAVE_OFF64_T
+#define HAVE_POINTER_LOCALTIME_R
/* Initialization entry points */
PR_EXTERN(void) _MD_EarlyInit(void);
@@ -57,11 +69,11 @@ PR_EXTERN(void) _MD_IrixInit(void);
#define _MD_INIT_IO()
/* Timer operations */
-PR_EXTERN(PRIntervalTime) _MD_GetInterval(void);
-#define _MD_GET_INTERVAL _MD_GetInterval
+PR_EXTERN(PRIntervalTime) _MD_IrixGetInterval(void);
+#define _MD_GET_INTERVAL _MD_IrixGetInterval
-PR_EXTERN(PRIntervalTime) _MD_IntervalPerSec(void);
-#define _MD_INTERVAL_PER_SEC _MD_IntervalPerSec
+PR_EXTERN(PRIntervalTime) _MD_IrixIntervalPerSec(void);
+#define _MD_INTERVAL_PER_SEC _MD_IrixIntervalPerSec
/* GC operations */
PR_EXTERN(void *) _MD_GetSP(PRThread *thread);
@@ -71,6 +83,7 @@ PR_EXTERN(void *) _MD_GetSP(PRThread *thread);
#include <mutex.h>
#define _MD_INIT_ATOMIC()
#define _MD_ATOMIC_INCREMENT(val) add_then_test((unsigned long*)val, 1)
+#define _MD_ATOMIC_ADD(ptr, val) add_then_test((unsigned long*)ptr, (unsigned long)val)
#define _MD_ATOMIC_DECREMENT(val) add_then_test((unsigned long*)val, 0xffffffff)
#define _MD_ATOMIC_SET(val, newval) test_and_set((unsigned long*)val, newval)
@@ -107,8 +120,8 @@ struct sproc_private_data {
extern char *_nspr_sproc_private;
#define _PR_PRDA() ((struct sproc_private_data *) _nspr_sproc_private)
-#define _MD_CURRENT_THREAD() (_PR_PRDA()->me)
#define _MD_SET_CURRENT_THREAD(_thread) _PR_PRDA()->me = (_thread)
+#define _MD_THIS_THREAD() (_PR_PRDA()->me)
#define _MD_LAST_THREAD() (_PR_PRDA()->last)
#define _MD_SET_LAST_THREAD(_thread) _PR_PRDA()->last = (_thread)
#define _MD_CURRENT_CPU() (_PR_PRDA()->cpu)
@@ -120,13 +133,16 @@ extern char *_nspr_sproc_private;
#define _MD_GET_SPROC_PID() (_PR_PRDA()->sproc_pid)
PR_EXTERN(struct PRThread*) _MD_get_attached_thread(void);
+PR_EXTERN(struct PRThread*) _MD_get_current_thread(void);
#define _MD_GET_ATTACHED_THREAD() _MD_get_attached_thread()
+#define _MD_CURRENT_THREAD() _MD_get_current_thread()
#define _MD_CHECK_FOR_EXIT() { \
- if (_pr_irix_exit_now) { \
+ if (_pr_irix_exit_now) { \
_PR_POST_SEM(_pr_irix_exit_sem); \
- exit(0); \
- } \
+ _MD_Wakeup_CPUs(); \
+ _exit(0); \
+ } \
}
#define _MD_ATTACH_THREAD(threadp)
@@ -137,23 +153,26 @@ PR_EXTERN(struct PRThread*) _MD_get_attached_thread(void);
extern struct _PRCPU *_pr_primordialCPU;
extern usema_t *_pr_irix_exit_sem;
extern PRInt32 _pr_irix_exit_now;
+extern int _pr_irix_primoridal_cpu_fd[];
+extern PRInt32 _pr_irix_process_exit;
+extern PRInt32 _pr_irix_process_exit_code;
/* Thread operations */
#define _PR_LOCK_HEAP() { \
PRIntn _is; \
if (_pr_primordialCPU) { \
- if (_PR_MD_CURRENT_THREAD() && \
+ if (_MD_GET_ATTACHED_THREAD() && \
!_PR_IS_NATIVE_THREAD( \
- _PR_MD_CURRENT_THREAD())) \
+ _MD_GET_ATTACHED_THREAD())) \
_PR_INTSOFF(_is); \
_PR_LOCK(_pr_heapLock); \
}
#define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \
_PR_UNLOCK(_pr_heapLock); \
- if (_PR_MD_CURRENT_THREAD() && \
+ if (_MD_GET_ATTACHED_THREAD() && \
!_PR_IS_NATIVE_THREAD( \
- _PR_MD_CURRENT_THREAD())) \
+ _MD_GET_ATTACHED_THREAD())) \
_PR_INTSON(_is); \
} \
}
@@ -179,7 +198,7 @@ struct _MDLock {
#define _PR_LOCK(lock) { \
PRIntn _is; \
- PRThread *me = _PR_MD_CURRENT_THREAD(); \
+ PRThread *me = _MD_GET_ATTACHED_THREAD(); \
if (me && !_PR_IS_NATIVE_THREAD(me)) \
_PR_INTSOFF(_is); \
ussetlock(lock); \
@@ -189,7 +208,7 @@ struct _MDLock {
#define _PR_UNLOCK(lock) { \
PRIntn _is; \
- PRThread *me = _PR_MD_CURRENT_THREAD(); \
+ PRThread *me = _MD_GET_ATTACHED_THREAD(); \
if (me && !_PR_IS_NATIVE_THREAD(me)) \
_PR_INTSOFF(_is); \
usunsetlock(lock); \
@@ -216,9 +235,6 @@ struct _MDThread {
PRInt32 id;
PRInt32 suspending_id;
int errcode;
- PRStatus *creation_status; /* points to the variable in which
- * a newly created child thread is
- * to store its creation status */
};
struct _MDThreadStack {
@@ -237,6 +253,43 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+
struct _MDCPU {
PRInt32 id;
PRInt32 suspending_id;
@@ -290,9 +343,13 @@ struct _MDCPU {
longjmp(jb, 1); \
PR_END_MACRO
-PR_EXTERN(PRStatus) _MD_InitThread(struct PRThread *thread, PRBool wakeup_parent);
+PR_EXTERN(PRStatus) _MD_InitThread(struct PRThread *thread,
+ PRBool wakeup_parent);
+PR_EXTERN(PRStatus) _MD_InitAttachedThread(struct PRThread *thread,
+ PRBool wakeup_parent);
#define _MD_INIT_THREAD(thread) _MD_InitThread(thread, PR_TRUE)
-#define _MD_INIT_ATTACHED_THREAD(thread) _MD_InitThread(thread, PR_FALSE)
+#define _MD_INIT_ATTACHED_THREAD(thread) \
+ _MD_InitAttachedThread(thread, PR_FALSE)
PR_EXTERN(void) _MD_ExitThread(struct PRThread *thread);
#define _MD_EXIT_THREAD _MD_ExitThread
@@ -329,6 +386,9 @@ PR_EXTERN(void) _MD_CleanThread(struct PRThread *thread);
PR_EXTERN(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout);
#define _MD_WAIT _MD_wait
+PR_EXTERN(void) _PR_MD_primordial_cpu();
+PR_EXTERN(void) _PR_MD_WAKEUP_PRIMORDIAL_CPU();
+
PR_EXTERN(PRStatus) _MD_WakeupWaiter(struct PRThread *);
#define _MD_WAKEUP_WAITER _MD_WakeupWaiter
@@ -353,6 +413,8 @@ PR_EXTERN(PRStatus) _MD_CreateThread(
extern void _MD_CleanupBeforeExit(void);
#define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
+PR_EXTERN(void) _PR_MD_PRE_CLEANUP(PRThread *me);
+
/* The following defines the unwrapped versions of select() and poll(). */
extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
@@ -375,4 +437,6 @@ PR_EXTERN(void) _MD_InitRunningCPU(struct _PRCPU *cpu);
#endif /* defined(_PR_PTHREADS) */
+#endif /* _LANGUAGE_ASSEMBLY */
+
#endif /* nspr_irix_defs_h___ */
diff --git a/pr/include/md/_irix.cfg b/pr/include/md/_irix32.cfg
index 2070760b..c5016880 100644
--- a/pr/include/md/_irix.cfg
+++ b/pr/include/md/_irix32.cfg
@@ -78,8 +78,7 @@
#define HAVE_ALIGNED_DOUBLES
#define HAVE_ALIGNED_LONGLONGS
-#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_irix64.cfg b/pr/include/md/_irix64.cfg
new file mode 100644
index 00000000..7df5f997
--- /dev/null
+++ b/pr/include/md/_irix64.cfg
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef _SGI_MP_SOURCE
+#define _SGI_MP_SOURCE
+#endif
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef IRIX
+#define IRIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h
index 0c4a5f6a..c7c33ce8 100644
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -64,6 +64,14 @@
#endif
#define USE_SETJMP
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#if defined(__alpha)
+#define _PR_HAVE_LARGE_OFF_T
+#else
+#define _PR_NO_LARGE_FILES
+#endif
#ifdef _PR_PTHREADS
@@ -282,6 +290,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -334,7 +378,7 @@ extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
#define _MD_SELECT __select
#ifdef _PR_POLL_AVAILABLE
-#include <poll.h>
+#include <sys/poll.h>
extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds,
int timeout);
#define _MD_POLL __syscall_poll
diff --git a/pr/include/md/_macos.h b/pr/include/md/_macos.h
index f1e2d5c6..ffeb1fa8 100644
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -103,6 +103,7 @@ struct _MDFileDesc {
#define _MD_BLOCK_CLOCK_INTERRUPTS()
#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
/*
** CPU Related definitions
@@ -462,11 +463,13 @@ typedef short PROSFD;
// Errors not found in the Mac StdCLib
#define EACCES 13 // Permission denied
#define ENOENT -43 // No such file or directory
+#define EMFILE 24 // Too many open files
#define _OS_INVALID_FD_VALUE -1
#define STDERR_FILENO 2
#if !defined(MAC_NSPR_STANDALONE)
+#define MAC_PATH_SEPARATOR ':'
#define PATH_SEPARATOR ':'
#define PATH_SEPARATOR_STR ":"
#define DIRECTORY_SEPARATOR '/'
@@ -476,6 +479,10 @@ typedef short PROSFD;
#define UNIX_THIS_DIRECTORY_STR "./"
#define UNIX_PARENT_DIRECTORY_STR "../"
+#define MAX_PATH 512
+#define MAX_MAC_FILENAME 31
+#define MAXPATHLEN MAX_PATH
+
// Alias a few names
#define getenv PR_GetEnv
@@ -527,6 +534,10 @@ extern void dprintf(const char *format, ...);
extern PRUint8 CallCacheFlushers(size_t blockSize);
#endif
+enum {
+ kPrivateNSPREventType = 13
+};
+
#if defined(MAC_NSPR_STANDALONE)
extern void* reallocSmaller(void* block, size_t newSize);
#endif
@@ -535,7 +546,7 @@ extern void* reallocSmaller(void* block, size_t newSize);
/*
** PR_GetSystemInfo related definitions
*/
-#define _PR_SI_SYSNAME "Mac OS"
+#define _PR_SI_SYSNAME "MacOS"
#define _PR_SI_ARCHITECTURE "PowerPC"
/*
diff --git a/pr/include/md/_ncr.cfg b/pr/include/md/_ncr.cfg
index 337b933d..dde85210 100644
--- a/pr/include/md/_ncr.cfg
+++ b/pr/include/md/_ncr.cfg
@@ -71,8 +71,7 @@
#define PR_ALIGN_OF_DOUBLE 4
#define PR_ALIGN_OF_POINTER 4
-#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_ncr.h b/pr/include/md/_ncr.h
index 75fa7ded..82a84e63 100644
--- a/pr/include/md/_ncr.h
+++ b/pr/include/md/_ncr.h
@@ -45,6 +45,9 @@
#define HAVE_WEAK_IO_SYMBOLS
#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+
#undef HAVE_STACK_GROWING_UP
#define HAVE_NETCONFIG
#define NEED_STRFTIME_LOCK
@@ -124,6 +127,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_nec.h b/pr/include/md/_nec.h
index e949dd0c..8c5e5b5e 100644
--- a/pr/include/md/_nec.h
+++ b/pr/include/md/_nec.h
@@ -108,6 +108,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_netbsd.h b/pr/include/md/_netbsd.h
index 6065f370..497d658b 100644
--- a/pr/include/md/_netbsd.h
+++ b/pr/include/md/_netbsd.h
@@ -134,6 +134,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_nspr_pthread.h b/pr/include/md/_nspr_pthread.h
index 312c8def..1daeb61a 100644
--- a/pr/include/md/_nspr_pthread.h
+++ b/pr/include/md/_nspr_pthread.h
@@ -119,6 +119,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
jmp_buf jb;
pthread_t pthread;
diff --git a/pr/include/md/_openbsd.cfg b/pr/include/md/_openbsd.cfg
new file mode 100644
index 00000000..967d36e5
--- /dev/null
+++ b/pr/include/md/_openbsd.cfg
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef OPENBSD
+#define OPENBSD
+#endif
+
+#if defined(__i386__) || defined(__arm32__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__sparc__)
+
+#undef IS_LITTLE_ENDIAN 1
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__alpha__)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__powerpc__) || defined(__m68k__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#else
+
+#error Must define constants for type sizes here.
+
+#endif
+
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/pr/include/md/_openbsd.h b/pr/include/md/_openbsd.h
new file mode 100644
index 00000000..d34d5e58
--- /dev/null
+++ b/pr/include/md/_openbsd.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef nspr_openbsd_defs_h___
+#define nspr_openbsd_defs_h___
+
+#include <sys/syscall.h>
+
+#define PR_LINKER_ARCH "openbsd"
+#define _PR_SI_SYSNAME "OpenBSD"
+#if defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__alpha__)
+#define _PR_SI_ARCHITECTURE "alpha"
+#elif defined(__m68k__)
+#define _PR_SI_ARCHITECTURE "m68k"
+#elif defined(__powerpc__)
+#define _PR_SI_ARCHITECTURE "powerpc"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(__arm32__)
+#define _PR_SI_ARCHITECTURE "arm32"
+#endif
+
+#define PR_DLL_SUFFIX ".so.1.0"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
+
+#define USE_SETJMP
+
+#ifndef _PR_PTHREADS
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+#if defined(__i386__) || defined(__sparc__) || defined(__m68k__) || defined(__powerpc__)
+#define JB_SP_INDEX 2
+#elif defined(__alpha__)
+#define JB_SP_INDEX 34
+#elif defined(__arm32__)
+/*
+ * On the arm32, the jmpbuf regs underwent a namechange after NetBSD 1.3
+ */
+#ifdef JMPBUF_REG_R13
+#define JB_SP_INDEX JMPBUF_REG_R13
+#else
+#define JB_SP_INDEX _JB_REG_R13
+#endif
+#else
+#error "Need to define SP index in jmp_buf here"
+#endif
+#define _MD_GET_SP(_th) (_th)->md.context[JB_SP_INDEX]
+
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread), 1)) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+
+#endif /* nspr_openbsd_defs_h___ */
diff --git a/pr/include/md/_os2.h b/pr/include/md/_os2.h
index ab67224a..bd38535e 100644
--- a/pr/include/md/_os2.h
+++ b/pr/include/md/_os2.h
@@ -245,6 +245,7 @@ extern PRInt32 _MD_CloseSocket(PRInt32 osfd);
#define _MD_INIT_ATOMIC _PR_MD_INIT_ATOMIC
#define _MD_ATOMIC_INCREMENT(x) _PR_MD_ATOMIC_INCREMENT(x)
+#define _MD_ATOMIC_ADD(x,y) _PR_MD_ATOMIC_ADD(x,y)
#define _MD_ATOMIC_DECREMENT(x) _PR_MD_ATOMIC_DECREMENT(x)
#define _MD_ATOMIC_SET(x,y) _PR_MD_ATOMIC_SET(x, y)
@@ -340,6 +341,7 @@ extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
#define _MD_START_INTERRUPTS()
#define _MD_STOP_INTERRUPTS()
#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
#define _MD_BLOCK_CLOCK_INTERRUPTS()
#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
diff --git a/pr/include/md/_osf1.cfg b/pr/include/md/_osf1.cfg
index 16bc9ac9..27ef81ca 100644
--- a/pr/include/md/_osf1.cfg
+++ b/pr/include/md/_osf1.cfg
@@ -75,8 +75,7 @@
#define PR_ALIGN_OF_DOUBLE 8
#define PR_ALIGN_OF_POINTER 8
-#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_osf1.h b/pr/include/md/_osf1.h
index 473dee28..ab2baadd 100644
--- a/pr/include/md/_osf1.h
+++ b/pr/include/md/_osf1.h
@@ -28,15 +28,10 @@
#define _PR_SI_ARCHITECTURE "alpha"
#define PR_DLL_SUFFIX ".so"
-#define _PR_VMBASE 0x30000000
-#define _PR_STACK_VMBASE 0x50000000
-#define _MD_DEFAULT_STACK_SIZE 131072L
-/*
- * OSF1 needs the MAP_FIXED flag to ensure that mmap returns a pointer
- * with the upper 32 bits zero. This is because Java sticks a pointer
- * into an int.
- */
-#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 131072L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
#undef HAVE_STACK_GROWING_UP
#undef HAVE_WEAK_IO_SYMBOLS
@@ -47,6 +42,13 @@
#define NEED_TIME_R
#define USE_DLFCN
+#define _PR_HAVE_ATOMIC_OPS
+#define _PR_HAVE_ATOMIC_CAS
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define _PR_HAVE_LARGE_OFF_T
+
#define USE_SETJMP
#include <setjmp.h>
@@ -116,6 +118,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -159,15 +197,13 @@ extern int __poll(struct pollfd filedes[], unsigned int nfds, int timeout);
/*
* Atomic operations
*/
-
-/* builtins.h is not available for OSF1 V3.2. */
-#ifndef OSF1V3
+#ifdef _PR_HAVE_ATOMIC_OPS
#include <machine/builtins.h>
-#define _PR_HAVE_ATOMIC_OPS
#define _MD_INIT_ATOMIC()
#define _MD_ATOMIC_INCREMENT(val) (__ATOMIC_INCREMENT_LONG(val) + 1)
+#define _MD_ATOMIC_ADD(ptr, val) (__ATOMIC_ADD_LONG(ptr, val) + val)
#define _MD_ATOMIC_DECREMENT(val) (__ATOMIC_DECREMENT_LONG(val) - 1)
#define _MD_ATOMIC_SET(val, newval) __ATOMIC_EXCH_LONG(val, newval)
-#endif /* OSF1V3 */
+#endif /* _PR_HAVE_ATOMIC_OPS */
#endif /* nspr_osf1_defs_h___ */
diff --git a/pr/include/md/_pth.h b/pr/include/md/_pth.h
index 72ab48af..9ca91a74 100644
--- a/pr/include/md/_pth.h
+++ b/pr/include/md/_pth.h
@@ -25,6 +25,7 @@
#define _PR_MD_BLOCK_CLOCK_INTERRUPTS()
#define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _PR_MD_DISABLE_CLOCK_INTERRUPTS()
+#define _PR_MD_ENABLE_CLOCK_INTERRUPTS()
/* In good standards fashion, the DCE threads (based on posix-4) are not
* quite the same as newer posix implementations. These are mostly name
@@ -70,7 +71,7 @@
#define PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
|| defined(HPUX) || defined(LINUX) || defined(FREEBSD) \
- || defined(NETBSD)
+ || defined(NETBSD) || defined(OPENBSD)
#define PTHREAD_ZERO_THR_HANDLE(t) (t) = 0
#define PTHREAD_THR_HANDLE_IS_ZERO(t) (t) == 0
#define PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
@@ -100,21 +101,6 @@
#error "Cannot determine pthread strategy"
#endif
-/*
- * See if we have the privilege to set the scheduling policy and
- * priority of threads. Returns 0 if privilege is available.
- * Returns EPERM otherwise.
- */
-
-#ifdef AIX
-#define PT_PRIVCHECK() privcheck(SET_PROC_RAC)
-#elif defined(HPUX) && !defined(_PR_DCETHREADS)
-PR_EXTERN(PRIntn) pt_hpux_privcheck(void);
-#define PT_PRIVCHECK() pt_hpux_privcheck()
-#else
-#define PT_PRIVCHECK() 0
-#endif /* AIX */
-
#if defined(_PR_DCETHREADS)
#define PTHREAD_EXPLICIT_SCHED PTHREAD_DEFAULT_SCHED
#endif
@@ -136,7 +122,7 @@ PR_EXTERN(PRIntn) pt_hpux_privcheck(void);
*/
#if defined(_PR_DCETHREADS) || defined(FREEBSD) \
|| (defined(LINUX) && defined(__alpha)) \
- || defined(NETBSD)
+ || defined(NETBSD) || defined(OPENBSD)
#define PT_NO_ATFORK
#endif
@@ -144,7 +130,7 @@ PR_EXTERN(PRIntn) pt_hpux_privcheck(void);
* These platforms don't have sigtimedwait()
*/
#if (defined(AIX) && !defined(AIX4_3)) || defined(LINUX) \
- || defined(FREEBSD) || defined(NETBSD)
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)
#define PT_NO_SIGTIMEDWAIT
#endif
@@ -186,20 +172,26 @@ PR_EXTERN(PRIntn) pt_hpux_privcheck(void);
*/
#define PT_PRIO_MIN 1
#define PT_PRIO_MAX 127
-#elif defined(FREEBSD) || defined(NETBSD) /* XXX */
+#elif defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) /* XXX */
#define PT_PRIO_MIN 0
#define PT_PRIO_MAX 126
#else
#error "pthreads is not supported for this architecture"
#endif
-/* Needed for garbage collection -- Look at PR_Suspend/PR_Resume implementation */
-#if defined(OSF1)
-#define PTHREAD_YIELD() pthread_yield_np()
-#elif defined(HPUX10_30) || defined(HPUX11)
-#define PTHREAD_YIELD() sched_yield()
-#elif defined(HPUX)
+/*
+ * The PTHREAD_YIELD function is called from a signal handler.
+ * Needed for garbage collection -- Look at PR_Suspend/PR_Resume
+ * implementation.
+ */
+#if defined(_PR_DCETHREADS)
#define PTHREAD_YIELD() pthread_yield()
+#elif defined(OSF1)
+/*
+ * sched_yield can't be called from a signal handler. Must use
+ * the _np version.
+ */
+#define PTHREAD_YIELD() pthread_yield_np()
#elif defined(AIX)
extern int (*_PT_aix_yield_fcn)();
#define PTHREAD_YIELD() (*_PT_aix_yield_fcn)()
@@ -211,12 +203,9 @@ extern int (*_PT_aix_yield_fcn)();
onemillisec.tv_nsec = 1000000L; \
nanosleep(&onemillisec,NULL); \
PR_END_MACRO
-#elif defined(SOLARIS)
-#define PTHREAD_YIELD() sched_yield()
-#elif defined(LINUX)
+#elif defined(HPUX) || defined(LINUX) || defined(SOLARIS) \
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)
#define PTHREAD_YIELD() sched_yield()
-#elif defined(FREEBSD) || defined(NETBSD)
-#define PTHREAD_YIELD() pthread_yield()
#else
#error "Need to define PTHREAD_YIELD for this platform"
#endif
diff --git a/pr/include/md/_reliantunix.cfg b/pr/include/md/_reliantunix.cfg
index 634acfe3..9cf253d8 100644
--- a/pr/include/md/_reliantunix.cfg
+++ b/pr/include/md/_reliantunix.cfg
@@ -76,8 +76,7 @@
#define PR_ALIGN_OF_DOUBLE 8
#define PR_ALIGN_OF_POINTER 4
-#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_reliantunix.h b/pr/include/md/_reliantunix.h
index d7afb63d..a327b122 100644
--- a/pr/include/md/_reliantunix.h
+++ b/pr/include/md/_reliantunix.h
@@ -47,6 +47,8 @@
#define HAVE_WEAK_IO_SYMBOLS
#define HAVE_WEAK_MALLOC_SYMBOLS
#define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
/*
* Mike Patnode indicated that it is possibly safe now to use context-switching
@@ -109,6 +111,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_rhapsody.cfg b/pr/include/md/_rhapsody.cfg
index 73fc491c..a0787fc9 100644
--- a/pr/include/md/_rhapsody.cfg
+++ b/pr/include/md/_rhapsody.cfg
@@ -27,8 +27,14 @@
#define RHAPOSDY
#endif
+#if defined(i386)
+#undef IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#else
#undef IS_LITTLE_ENDIAN
#define IS_BIG_ENDIAN 1
+#endif
+
#define HAVE_LONG_LONG
#undef HAVE_ALIGNED_DOUBLES
#define HAVE_ALIGNED_LONGLONGS 1
@@ -53,6 +59,7 @@
#define PR_BITS_PER_FLOAT 32
#define PR_BITS_PER_DOUBLE 64
#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
#define PR_BITS_PER_BYTE_LOG2 3
#define PR_BITS_PER_SHORT_LOG2 4
@@ -117,3 +124,4 @@
#endif /* NO_NSPR_10_SUPPORT */
#endif /* nspr_cpucfg___ */
+
diff --git a/pr/include/md/_rhapsody.h b/pr/include/md/_rhapsody.h
index 052da11f..476b8e38 100644
--- a/pr/include/md/_rhapsody.h
+++ b/pr/include/md/_rhapsody.h
@@ -38,24 +38,23 @@
#define _MD_MMAP_FLAGS MAP_PRIVATE
#undef HAVE_STACK_GROWING_UP
-#define HAVE_WEAK_MALLOC_SYMBOLS
-/* do this until I figure out the rhapsody dll stuff. */
#define HAVE_DLL
-#define USE_RLD
-#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_TIMESPEC_HAS_TS_SEC
+#define _PR_NO_LARGE_FILES
#define USE_SETJMP
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
#include <setjmp.h>
#define PR_CONTEXT_TYPE jmp_buf
-#define CONTEXT(_th) ((_th)->md.context)
-
-#define _MD_GET_SP(_th) (_th)->md.context[0]
-#define PR_NUM_GCREGS _JBLEN
+#define CONTEXT(_th) ((_th)->md.context)
+#define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack)
+#define PR_NUM_GCREGS _JBLEN
/*
** Initialize a thread context to run "_main()" when started
@@ -66,7 +65,7 @@
if (setjmp(CONTEXT(_thread))) { \
_main(); \
} \
- _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
}
#define _MD_SWITCH_CONTEXT(_thread) \
@@ -113,6 +112,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -149,14 +184,14 @@ extern void _MD_YIELD(void);
#endif /* ! _PR_PTHREADS */
-extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
-
-#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_EARLY_INIT _MD_EarlyInit
#define _MD_FINAL_INIT _PR_UnixInit
-#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
/*
* We wrapped the select() call. _MD_SELECT refers to the built-in,
diff --git a/pr/include/md/_scoos.cfg b/pr/include/md/_scoos.cfg
index 3f414650..6ef8fa90 100644
--- a/pr/include/md/_scoos.cfg
+++ b/pr/include/md/_scoos.cfg
@@ -71,8 +71,7 @@
#define PR_ALIGN_OF_DOUBLE 4
#define PR_ALIGN_OF_POINTER 4
-#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_scoos.h b/pr/include/md/_scoos.h
index 45764f74..faa8e9ff 100644
--- a/pr/include/md/_scoos.h
+++ b/pr/include/md/_scoos.h
@@ -45,6 +45,9 @@
#define HAVE_WEAK_IO_SYMBOLS
#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+
#define NEED_STRFTIME_LOCK
#define NEED_TIME_R
#define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */
@@ -113,6 +116,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h
index 04d0aa91..aaa646c1 100644
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -48,8 +48,14 @@
#undef _PR_HAVE_ATOMIC_OPS
#else
#define _PR_HAVE_ATOMIC_OPS
+#define _PR_HAVE_ATOMIC_CAS
#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM
+
+#include "prinrval.h"
PR_EXTERN(PRIntervalTime) _MD_Solaris_GetInterval(void);
#define _MD_GET_INTERVAL _MD_Solaris_GetInterval
PR_EXTERN(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
@@ -64,6 +70,9 @@ PR_EXTERN(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
PR_EXTERN(PRInt32) _MD_AtomicIncrement(PRInt32 *val);
#define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
+PR_EXTERN(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD _MD_AtomicAdd
+
PR_EXTERN(PRInt32) _MD_AtomicDecrement(PRInt32 *val);
#define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
@@ -285,6 +294,43 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field, common to all Unix platforms
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
@@ -566,6 +612,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_sony.h b/pr/include/md/_sony.h
index f8846024..1ff68977 100644
--- a/pr/include/md/_sony.h
+++ b/pr/include/md/_sony.h
@@ -103,6 +103,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_sunos4.h b/pr/include/md/_sunos4.h
index 823d22fb..41d4258c 100644
--- a/pr/include/md/_sunos4.h
+++ b/pr/include/md/_sunos4.h
@@ -52,6 +52,8 @@
#define NEED_STRFTIME_LOCK
#define NEED_TIME_R
#define HAVE_BSD_FLOCK
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
@@ -145,6 +147,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_unix_errors.h b/pr/include/md/_unix_errors.h
index b022462c..03ca7a02 100644
--- a/pr/include/md/_unix_errors.h
+++ b/pr/include/md/_unix_errors.h
@@ -138,6 +138,9 @@ PR_EXTERN(void) _MD_unix_map_select_error(int err);
PR_EXTERN(void) _MD_unix_map_poll_error(int err);
#define _PR_MD_MAP_POLL_ERROR _MD_unix_map_poll_error
+PR_EXTERN(void) _MD_unix_map_poll_revents_error(int err);
+#define _PR_MD_MAP_POLL_REVENTS_ERROR _MD_unix_map_poll_revents_error
+
PR_EXTERN(void) _MD_unix_map_flock_error(int err);
#define _PR_MD_MAP_FLOCK_ERROR _MD_unix_map_flock_error
diff --git a/pr/include/md/_unixos.h b/pr/include/md/_unixos.h
index 4555a948..a801553f 100644
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -37,26 +37,27 @@
#include <stddef.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <errno.h>
#include "prio.h"
#include "prmem.h"
#include "prclist.h"
-/* To pick up fd_set */
-#if defined(HPUX)
-#include <sys/time.h>
-#elif defined(OSF1) || defined(AIX) || defined(SOLARIS) || defined(IRIX) \
- || defined(UNIXWARE) || defined(NCR) || defined(SNI) || defined(NEC) \
- || defined(BSDI) || defined(SONY)
-#include <sys/select.h>
-#elif defined(SUNOS4) || defined(SCO) || defined(FREEBSD) \
- || defined(NETBSD) || defined(RHAPSODY) || defined(DGUX)
-#include <sys/types.h>
-#elif defined(LINUX)
+/*
+ * For select(), fd_set, and struct timeval.
+ *
+ * In The Single UNIX(R) Specification, Version 2,
+ * the header file for select() is <sys/time.h>.
+ *
+ * fd_set is defined in <sys/types.h>. Usually
+ * <sys/time.h> includes <sys/types.h>, but on some
+ * older systems <sys/time.h> does not include
+ * <sys/types.h>, so we include it explicitly.
+ */
#include <sys/time.h>
#include <sys/types.h>
-#else
-#error Find out what include file defines fd_set on this platform
+#if defined(AIX) /* Only pre-4.2 AIX needs it, but for simplicity... */
+#include <sys/select.h>
#endif
#define PR_DIRECTORY_SEPARATOR '/'
@@ -64,7 +65,6 @@
#define PR_PATH_SEPARATOR ':'
#define PR_PATH_SEPARATOR_STR ":"
#define GCPTR
-
typedef int (*FARPROC)();
/*
@@ -73,6 +73,26 @@ typedef int (*FARPROC)();
#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
extern PRIntervalTime intr_timeout_ticks;
+/*
+ * The bit flags for the in_flags and out_flags fields
+ * of _PR_UnixPollDesc
+ */
+#ifdef _PR_USE_POLL
+#define _PR_UNIX_POLL_READ POLLIN
+#define _PR_UNIX_POLL_WRITE POLLOUT
+#define _PR_UNIX_POLL_EXCEPT POLLPRI
+#define _PR_UNIX_POLL_ERR POLLERR
+#define _PR_UNIX_POLL_NVAL POLLNVAL
+#define _PR_UNIX_POLL_HUP POLLHUP
+#else /* _PR_USE_POLL */
+#define _PR_UNIX_POLL_READ 0x1
+#define _PR_UNIX_POLL_WRITE 0x2
+#define _PR_UNIX_POLL_EXCEPT 0x4
+#define _PR_UNIX_POLL_ERR 0x8
+#define _PR_UNIX_POLL_NVAL 0x10
+#define _PR_UNIX_POLL_HUP 0x20
+#endif /* _PR_USE_POLL */
+
typedef struct _PRUnixPollDesc {
PRInt32 osfd;
PRInt16 in_flags;
@@ -92,8 +112,10 @@ typedef struct PRPollQueue {
((PRPollQueue*) ((char*) (_qp) - offsetof(PRPollQueue,links)))
-extern PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUintn how,
- PRIntervalTime timeout);
+extern PRInt32 _PR_WaitForMultipleFDs(
+ _PRUnixPollDesc *unixpds,
+ PRInt32 pdcnt,
+ PRIntervalTime timeout);
extern void _PR_Unblock_IO_Wait(struct PRThread *thr);
#if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY)
@@ -113,45 +135,9 @@ struct _MDDir {
DIR *d;
};
-/*
- * md-specific cpu structure field, common to all Unix platforms
- */
-#define _PR_MD_MAX_OSFD FD_SETSIZE
-
-struct _MDCPU_Unix {
- PRCList ioQ;
- PRUint32 ioq_timeout;
- PRInt32 ioq_max_osfd;
- PRInt32 ioq_osfd_cnt;
-#ifndef _PR_USE_POLL
- fd_set fd_read_set, fd_write_set, fd_exception_set;
- PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
- fd_exception_cnt[_PR_MD_MAX_OSFD];
-#else
- struct pollfd *ioq_pollfds;
- int ioq_pollfds_size;
-#endif /* _PR_USE_POLL */
-};
struct _PRCPU;
extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu);
-#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
-#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
-#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
-#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
-#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
-#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
-#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
-#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
-#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
-#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
-#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
-#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
-#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
-
-#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
-
-
/*
** Make a redzone at both ends of the stack segment. Disallow access
** to those pages of memory. It's ok if the mprotect call's don't
@@ -248,6 +234,7 @@ extern PRStatus _MD_KillUnixProcess(struct PRProcess *process);
#define _MD_START_INTERRUPTS _MD_StartInterrupts
#define _MD_STOP_INTERRUPTS _MD_StopInterrupts
#define _MD_DISABLE_CLOCK_INTERRUPTS _MD_DisableClockInterrupts
+#define _MD_ENABLE_CLOCK_INTERRUPTS _MD_EnableClockInterrupts
#define _MD_BLOCK_CLOCK_INTERRUPTS _MD_BlockClockInterrupts
#define _MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UnblockClockInterrupts
@@ -291,7 +278,9 @@ extern void _MD_FreeSegment(PRSegment *seg);
/************************************************************************/
+#if !defined(HPUX_LW_TIMER)
#define _MD_INTERVAL_INIT()
+#endif
#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
@@ -304,11 +293,6 @@ extern void _MD_FreeSegment(PRSegment *seg);
extern PRInt32 _MD_AvailableSocket(PRInt32 osfd);
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
extern void _MD_InitSegs(void);
extern void _MD_StartInterrupts(void);
extern void _MD_StopInterrupts(void);
@@ -327,7 +311,7 @@ extern PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info);
extern PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info);
extern PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info);
extern PRInt32 _MD_rename(const char *from, const char *to);
-extern PRInt32 _MD_access(const char *name, PRIntn how);
+extern PRInt32 _MD_access(const char *name, PRAccessHow how);
extern PRInt32 _MD_mkdir(const char *name, PRIntn mode);
extern PRInt32 _MD_rmdir(const char *name);
extern PRInt32 _MD_accept_read(PRInt32 sock, PRInt32 *newSock,
@@ -516,4 +500,72 @@ extern int poll(struct pollfd *, unsigned long, int);
#endif /* _PR_NEED_FAKE_POLL */
+/*
+** A vector of the UNIX I/O calls we use. These are here to smooth over
+** the rough edges needed for large files. All of NSPR's implmentaions
+** go through this vector using syntax of the form
+** result = _md_iovector.xxx64(args);
+*/
+
+#if defined(SOLARIS2_5)
+/*
+** Special case: Solaris 2.5.1
+** Solaris starts to have 64-bit file I/O in 2.6. We build on Solaris
+** 2.5.1 so that we can use the same binaries on both Solaris 2.5.1 and
+** 2.6. At run time, we detect whether 64-bit file I/O is available by
+** looking up the 64-bit file function symbols in libc. At build time,
+** we need to define the 64-bit file I/O datatypes that are compatible
+** with their definitions on Solaris 2.6.
+*/
+typedef PRInt64 off64_t;
+typedef PRUint64 ino64_t;
+typedef PRUint64 blkcnt64_t;
+struct stat64 {
+ dev_t st_dev;
+ long st_pad1[3];
+ ino64_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ long t_pad2[2];
+ off64_t st_size;
+ timestruc_t st_atim;
+ timestruc_t st_mtim;
+ timestruc_t st_ctim;
+ long st_blksize;
+ blkcnt64_t st_blocks;
+ char st_fstype[_ST_FSTYPSZ];
+ long st_pad4[8];
+};
+typedef struct stat64 _MDStat64;
+
+#elif defined(_PR_HAVE_OFF64_T)
+typedef struct stat64 _MDStat64;
+#elif defined(_PR_HAVE_LARGE_OFF_T) || defined(_PR_NO_LARGE_FILES)
+typedef struct stat _MDStat64;
+#else
+#error "I don't know yet"
+#endif
+
+typedef PRIntn (*_MD_Fstat64)(PRIntn osfd, _MDStat64 *buf);
+typedef PRIntn (*_MD_Open64)(const char *path, int oflag, ...);
+typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf);
+typedef PRInt64 (*_MD_Lseek64)(PRIntn osfd, PRInt64, PRIntn whence);
+typedef PRIntn (*_MD_Lockf64)(PRIntn osfd, PRIntn function, PRInt64 size);
+typedef void* (*_MD_Mmap64)(
+ void *addr, PRSize len, PRIntn prot, PRIntn flags,
+ PRIntn fildes, PRInt64 offset);
+struct _MD_IOVector
+{
+ _MD_Open64 _open64;
+ _MD_Mmap64 _mmap64;
+ _MD_Stat64 _stat64;
+ _MD_Fstat64 _fstat64;
+ _MD_Lockf64 _lockf64;
+ _MD_Lseek64 _lseek64;
+};
+extern struct _MD_IOVector _md_iovector;
+
#endif /* prunixos_h___ */
diff --git a/pr/include/md/_unixware.cfg b/pr/include/md/_unixware.cfg
index d8261908..fd96a083 100644
--- a/pr/include/md/_unixware.cfg
+++ b/pr/include/md/_unixware.cfg
@@ -71,8 +71,7 @@
#define PR_ALIGN_OF_DOUBLE 4
#define PR_ALIGN_OF_POINTER 4
-#define _PR_USE_POLL
-#define _PR_POLL_AVAILABLE
+#define _PR_POLL_BACKCOMPAT
#ifndef NO_NSPR_10_SUPPORT
diff --git a/pr/include/md/_unixware.h b/pr/include/md/_unixware.h
index 9a0afda3..b1ce660a 100644
--- a/pr/include/md/_unixware.h
+++ b/pr/include/md/_unixware.h
@@ -36,6 +36,8 @@
#ifndef HAVE_WEAK_IO_SYMBOLS
#define HAVE_WEAK_IO_SYMBOLS
#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
#undef HAVE_STACK_GROWING_UP
#define HAVE_NETCONFIG
@@ -114,6 +116,42 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
struct _MDCPU_Unix md_unix;
};
diff --git a/pr/include/md/_win16.h b/pr/include/md/_win16.h
index bb8ba5a3..399b7c6d 100644
--- a/pr/include/md/_win16.h
+++ b/pr/include/md/_win16.h
@@ -296,6 +296,7 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
#define _MD_INIT_ATOMIC()
#define _MD_ATOMIC_INCREMENT(x) (*x++)
+#define _MD_ATOMIC_ADD(ptr, val) ((*x) += val)
#define _MD_ATOMIC_DECREMENT(x) (*x--)
#define _MD_ATOMIC_SET(x,y) (*x, y)
@@ -388,6 +389,7 @@ PR_EXTERN(void) _MD_INIT_RUNNING_CPU(struct _PRCPU *cpu );
#define _MD_START_INTERRUPTS()
#define _MD_STOP_INTERRUPTS()
#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
#define _MD_BLOCK_CLOCK_INTERRUPTS()
#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h
index 9cfbc1b4..a4710b7f 100644
--- a/pr/include/md/_win95.h
+++ b/pr/include/md/_win95.h
@@ -222,13 +222,17 @@ extern PRInt32 _MD_CloseSocket(PRInt32 osfd);
#define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT
#define _MD_SELECT select
#define _MD_FSYNC _PR_MD_FSYNC
+#define READ_FD 1
+#define WRITE_FD 2
#define _MD_INIT_ATOMIC()
#if defined(_M_IX86) || defined(_X86_)
#define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD
#define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT
#else /* non-x86 processors */
#define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x)
+#define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val)
#define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x)
#endif /* x86 */
#define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y)
@@ -325,6 +329,7 @@ extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
#define _MD_START_INTERRUPTS()
#define _MD_STOP_INTERRUPTS()
#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
#define _MD_BLOCK_CLOCK_INTERRUPTS()
#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
@@ -368,9 +373,11 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
/* --- Native-Thread Specific Definitions ------------------------------- */
+extern struct PRThread * _MD_CURRENT_THREAD(void);
+
#ifdef _PR_USE_STATIC_TLS
extern __declspec(thread) struct PRThread *_pr_currentThread;
-#define _MD_CURRENT_THREAD() _pr_currentThread
+#define _MD_GET_ATTACHED_THREAD() _pr_currentThread
#define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
extern __declspec(thread) struct PRThread *_pr_thread_last_run;
@@ -382,7 +389,7 @@ extern __declspec(thread) struct _PRCPU *_pr_currentCPU;
#define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = 0)
#else /* _PR_USE_STATIC_TLS */
extern DWORD _pr_currentThreadIndex;
-#define _MD_CURRENT_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex))
+#define _MD_GET_ATTACHED_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex))
#define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentThreadIndex, (_thread))
extern DWORD _pr_lastThreadIndex;
diff --git a/pr/include/md/_winnt.h b/pr/include/md/_winnt.h
index 7695e5f6..9de2cf05 100644
--- a/pr/include/md/_winnt.h
+++ b/pr/include/md/_winnt.h
@@ -34,6 +34,7 @@
#include <errno.h>
#include "prio.h"
+#include "prclist.h"
/*
* Internal configuration macros
@@ -49,6 +50,7 @@
#define HAVE_SOCKET_REUSEADDR
#define HAVE_SOCKET_KEEPALIVE
#define _PR_HAVE_ATOMIC_OPS
+#define _PR_HAVE_ATOMIC_CAS
/* --- Common User-Thread/Native-Thread Definitions --------------------- */
@@ -72,9 +74,39 @@ struct _MDCPU {
int unused;
};
+enum _MDIOModel {
+ _MD_BlockingIO = 0x38,
+ _MD_MultiWaitIO = 0x49
+};
+
+typedef struct _MDOverlapped {
+ OVERLAPPED overlapped; /* Used for async I/O */
+
+ enum _MDIOModel ioModel; /* The I/O model to implement
+ * using overlapped I/O.
+ */
+
+ union {
+ struct _MDThread *mdThread; /* For blocking I/O, this structure
+ * is embedded in the _MDThread
+ * structure.
+ */
+ struct {
+ PRCList links; /* for group->io_ready list */
+ struct PRRecvWait *desc; /* For multiwait I/O, this structure
+ * is associated with a PRRecvWait
+ * structure.
+ */
+ struct PRWaitGroup *group;
+ struct TimerEvent *timer;
+ DWORD error;
+ } mw;
+ } data;
+} _MDOverlapped;
+
struct _MDThread {
/* The overlapped structure must be first! */
- OVERLAPPED overlapped; /* Used for async IO for this thread */
+ struct _MDOverlapped overlapped; /* Used for async IO for this thread */
void *acceptex_buf; /* Used for AcceptEx() */
TRANSMIT_FILE_BUFFERS *xmit_bufs; /* Used for TransmitFile() */
HANDLE blocked_sema; /* Threads block on this when waiting
@@ -168,6 +200,7 @@ struct _MDProcess {
/* --- IO stuff --- */
+extern PRInt32 _md_Associate(HANDLE);
extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket);
#define _MD_OPEN _PR_MD_OPEN
@@ -213,9 +246,11 @@ extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket);
#define _MD_INIT_ATOMIC()
#if defined(_M_IX86) || defined(_X86_)
#define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD
#define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT
#else /* non-x86 processors */
#define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x)
+#define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val)
#define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x)
#endif /* x86 */
#define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y)
@@ -321,6 +356,7 @@ extern struct _MDLock _pr_ioq_lock;
#define _MD_START_INTERRUPTS()
#define _MD_STOP_INTERRUPTS()
#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
#define _MD_BLOCK_CLOCK_INTERRUPTS()
#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
@@ -370,43 +406,73 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
/* --- Native-Thread Specific Definitions ------------------------------- */
-#ifdef _PR_USE_STATIC_TLS
+extern BOOL _pr_use_static_tls;
extern __declspec(thread) struct PRThread *_pr_current_fiber;
-#define _MD_CURRENT_THREAD() _pr_current_fiber
-#define _MD_SET_CURRENT_THREAD(_thread) (_pr_current_fiber = (_thread))
+extern DWORD _pr_currentFiberIndex;
-extern __declspec(thread) struct PRThread *_pr_fiber_last_run;
-#define _MD_LAST_THREAD() _pr_fiber_last_run
-#define _MD_SET_LAST_THREAD(_thread) (_pr_fiber_last_run = (_thread))
+#define _MD_GET_ATTACHED_THREAD() \
+ (_pr_use_static_tls ? _pr_current_fiber \
+ : (PRThread *) TlsGetValue(_pr_currentFiberIndex))
-extern __declspec(thread) struct _PRCPU *_pr_current_cpu;
-#define _MD_CURRENT_CPU() _pr_current_cpu
-#define _MD_SET_CURRENT_CPU(_cpu) (_pr_current_cpu = (_cpu))
+extern struct PRThread * _MD_CURRENT_THREAD(void);
-extern __declspec(thread) PRUintn _pr_ints_off;
-#define _MD_SET_INTSOFF(_val) (_pr_ints_off = (_val))
-#define _MD_GET_INTSOFF() _pr_ints_off
+#define _MD_SET_CURRENT_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_current_fiber = (_thread); \
+ } else { \
+ TlsSetValue(_pr_currentFiberIndex, (_thread)); \
+ } \
+ PR_END_MACRO
-#else /* _PR_USE_STATIC_TLS */
+extern __declspec(thread) struct PRThread *_pr_fiber_last_run;
+extern DWORD _pr_lastFiberIndex;
-extern DWORD _pr_currentFiberIndex;
-#define _MD_CURRENT_THREAD() ((PRThread *) TlsGetValue(_pr_currentFiberIndex))
-#define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentFiberIndex, (_thread))
+#define _MD_LAST_THREAD() \
+ (_pr_use_static_tls ? _pr_fiber_last_run \
+ : (PRThread *) TlsGetValue(_pr_lastFiberIndex))
-extern DWORD _pr_lastFiberIndex;
-#define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastFiberIndex))
-#define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastFiberIndex, (_thread))
+#define _MD_SET_LAST_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_fiber_last_run = (_thread); \
+ } else { \
+ TlsSetValue(_pr_lastFiberIndex, (_thread)); \
+ } \
+ PR_END_MACRO
+extern __declspec(thread) struct _PRCPU *_pr_current_cpu;
extern DWORD _pr_currentCPUIndex;
-#define _MD_CURRENT_CPU() ((struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
-#define _MD_SET_CURRENT_CPU(_cpu) TlsSetValue(_pr_currentCPUIndex, (_cpu))
+#define _MD_CURRENT_CPU() \
+ (_pr_use_static_tls ? _pr_current_cpu \
+ : (struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
+
+#define _MD_SET_CURRENT_CPU(_cpu) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_current_cpu = (_cpu); \
+ } else { \
+ TlsSetValue(_pr_currentCPUIndex, (_cpu)); \
+ } \
+ PR_END_MACRO
+
+extern __declspec(thread) PRUintn _pr_ints_off;
extern DWORD _pr_intsOffIndex;
-#define _MD_SET_INTSOFF(_val) TlsSetValue(_pr_intsOffIndex, (LPVOID) (_val))
-#define _MD_GET_INTSOFF() ((PRUintn) TlsGetValue(_pr_intsOffIndex))
-#endif /* _PR_USE_STATIC_TLS */
+#define _MD_GET_INTSOFF() \
+ (_pr_use_static_tls ? _pr_ints_off \
+ : (PRUintn) TlsGetValue(_pr_intsOffIndex))
+
+#define _MD_SET_INTSOFF(_val) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_ints_off = (_val); \
+ } else { \
+ TlsSetValue(_pr_intsOffIndex, (LPVOID) (_val)); \
+ } \
+ PR_END_MACRO
/* --- Initialization stuff --- */
#define _MD_INIT_LOCKS()
diff --git a/pr/include/md/prosdep.h b/pr/include/md/prosdep.h
index bd8e6a19..98002558 100644
--- a/pr/include/md/prosdep.h
+++ b/pr/include/md/prosdep.h
@@ -50,9 +50,6 @@ PR_BEGIN_EXTERN_C
#elif defined(XP_UNIX)
-#include "md/_unixos.h"
-#include "md/_unix_errors.h"
-
#if defined(AIX)
#include "md/_aix.h"
@@ -62,6 +59,9 @@ PR_BEGIN_EXTERN_C
#elif defined(NETBSD)
#include "md/_netbsd.h"
+#elif defined(OPENBSD)
+#include "md/_openbsd.h"
+
#elif defined(BSDI)
#include "md/_bsdi.h"
@@ -112,6 +112,9 @@ PR_BEGIN_EXTERN_C
#endif
+#include "md/_unixos.h"
+#include "md/_unix_errors.h"
+
#else
#error "The platform is not Unix, Windows, or Mac"
diff --git a/pr/include/nspr.h b/pr/include/nspr.h
index 4539af58..a2800df2 100644
--- a/pr/include/nspr.h
+++ b/pr/include/nspr.h
@@ -37,6 +37,7 @@
#include "prlong.h"
#include "prmem.h"
#include "prmon.h"
+#include "prmwait.h"
#include "prnetdb.h"
#include "prprf.h"
#include "prproces.h"
diff --git a/pr/include/obsolete/pralarm.h b/pr/include/obsolete/pralarm.h
index 5afb65a5..422a7b6a 100644
--- a/pr/include/obsolete/pralarm.h
+++ b/pr/include/obsolete/pralarm.h
@@ -46,6 +46,7 @@
#include "prtypes.h"
#include "prinrval.h"
+
PR_BEGIN_EXTERN_C
/**********************************************************************/
diff --git a/pr/include/obsolete/protypes.h b/pr/include/obsolete/protypes.h
index e9fba9dc..e70b03b4 100644
--- a/pr/include/obsolete/protypes.h
+++ b/pr/include/obsolete/protypes.h
@@ -26,6 +26,7 @@
#if !defined(PROTYPES_H)
#define PROTYPES_H
+
/* SVR4 typedef of uint is commonly found on UNIX machines. */
#ifdef XP_UNIX
#include <sys/types.h>
diff --git a/pr/include/pratom.h b/pr/include/pratom.h
index 48d162a9..d8ad0a8e 100644
--- a/pr/include/pratom.h
+++ b/pr/include/pratom.h
@@ -25,6 +25,7 @@
#define pratom_h___
#include "prtypes.h"
+#include "prlock.h"
PR_BEGIN_EXTERN_C
@@ -35,7 +36,7 @@ PR_BEGIN_EXTERN_C
** INPUTS:
** val: a pointer to the value to increment
** RETURN:
-** the returned value has the same sign as the result
+** the returned value is the result of the increment
*/
PR_EXTERN(PRInt32) PR_AtomicIncrement(PRInt32 *val);
@@ -46,7 +47,7 @@ PR_EXTERN(PRInt32) PR_AtomicIncrement(PRInt32 *val);
** INPUTS:
** val: a pointer to the value to decrement
** RETURN:
-** the returned value has the same sign as the result
+** the returned value is the result of the decrement
*/
PR_EXTERN(PRInt32) PR_AtomicDecrement(PRInt32 *val);
@@ -55,13 +56,96 @@ PR_EXTERN(PRInt32) PR_AtomicDecrement(PRInt32 *val);
** DESCRIPTION:
** Atomically set a 32 bit value.
** INPUTS:
-** val: A pointer to a 32 bit value to bet set
+** val: A pointer to a 32 bit value to be set
** newval: The newvalue to assign to val
** RETURN:
** Returns the prior value
*/
PR_EXTERN(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval);
+/*
+** FUNCTION: PR_AtomicAdd
+** DESCRIPTION:
+** Atomically add a 32 bit value.
+** INPUTS:
+** ptr: a pointer to the value to increment
+** val: value to be added
+** RETURN:
+** the returned value is the result of the addition
+*/
+PR_EXTERN(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+
+/*
+** LIFO linked-list (stack)
+*/
+typedef struct PRStackElemStr PRStackElem;
+
+struct PRStackElemStr {
+ PRStackElem *prstk_elem_next; /* next pointer MUST be at offset 0;
+ assembly language code relies on this */
+};
+
+typedef struct PRStackStr PRStack;
+
+struct PRStackStr {
+ PRStackElem prstk_head; /* head MUST be at offset 0; assembly
+ language code relies on this
+ */
+ PRLock *prstk_lock;
+ char *prstk_name;
+};
+
+
+/*
+** FUNCTION: PR_CreateStack
+** DESCRIPTION:
+** Create a stack, a LIFO linked list
+** INPUTS:
+** stack_name: a pointer to string containing the name of the stack
+** RETURN:
+** A pointer to the created stack, if successful, else NULL.
+*/
+PR_EXTERN(PRStack *) PR_CreateStack(const char *stack_name);
+
+/*
+** FUNCTION: PR_StackPush
+** DESCRIPTION:
+** Push an element on the top of the stack
+** INPUTS:
+** stack: pointer to the stack
+** stack_elem: pointer to the stack element
+** RETURN:
+** None
+*/
+PR_EXTERN(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem);
+
+/*
+** FUNCTION: PR_StackPop
+** DESCRIPTION:
+** Remove the element on the top of the stack
+** INPUTS:
+** stack: pointer to the stack
+** RETURN:
+** A pointer to the stack element removed from the top of the stack,
+** if non-empty,
+** else NULL
+*/
+PR_EXTERN(PRStackElem *) PR_StackPop(PRStack *stack);
+
+/*
+** FUNCTION: PR_DestroyStack
+** DESCRIPTION:
+** Destroy the stack
+** INPUTS:
+** stack: pointer to the stack
+** RETURN:
+** PR_SUCCESS - if successfully deleted
+** PR_FAILURE - if the stack is not empty
+** PR_GetError will return
+** PR_INVALID_STATE_ERROR - stack is not empty
+*/
+PR_EXTERN(PRStatus) PR_DestroyStack(PRStack *stack);
+
PR_END_EXTERN_C
#endif /* pratom_h___ */
diff --git a/pr/include/prbit.h b/pr/include/prbit.h
index 57853384..72beb243 100644
--- a/pr/include/prbit.h
+++ b/pr/include/prbit.h
@@ -20,6 +20,7 @@
#define prbit_h___
#include "prtypes.h"
+PR_BEGIN_EXTERN_C
/*
** A prbitmap_t is a long integer that can be used for bitmaps
@@ -87,4 +88,5 @@ PR_EXTERN(PRIntn) PR_FloorLog2(PRUint32 i);
(_log2) += 1; \
PR_END_MACRO
+PR_END_EXTERN_C
#endif /* prbit_h___ */
diff --git a/pr/include/prcountr.h b/pr/include/prcountr.h
new file mode 100644
index 00000000..44d5fb43
--- /dev/null
+++ b/pr/include/prcountr.h
@@ -0,0 +1,512 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef prcountr_h___
+#define prcountr_h___
+
+/*----------------------------------------------------------------------------
+** prcountr.h -- NSPR Instrumentation counters
+**
+** The NSPR Counter Feature provides a means to "count
+** something." Counters can be dynamically defined, incremented,
+** decremented, set, and deleted under application program
+** control.
+**
+** The Counter Feature is intended to be used as instrumentation,
+** not as operational data. If you need a counter for operational
+** data, use native integral types.
+**
+** Counters are 32bit unsigned intergers. On overflow, a counter
+** will wrap. No exception is recognized or reported.
+**
+** A counter can be dynamically created using a two level naming
+** convention. A "handle" is returned when the counter is
+** created. The counter can subsequently be addressed by its
+** handle. An API is provided to get an existing counter's handle
+** given the names with which it was originally created.
+** Similarly, a counter's name can be retrieved given its handle.
+**
+** The counter naming convention is a two-level hierarchy. The
+** QName is the higher level of the hierarchy; RName is the
+** lower level. RNames can be thought of as existing within a
+** QName. The same RName can exist within multiple QNames. QNames
+** are unique. The NSPR Counter is not a near-zero overhead
+** feature. Application designers should be aware of
+** serialization issues when using the Counter API. Creating a
+** counter locks a large asset, potentially causing a stall. This
+** suggest that applications should create counters at component
+** initialization, for example, and not create and destroy them
+** willy-nilly. ... You have been warned.
+**
+** Incrementing and Adding to counters uses atomic operations.
+** The performance of these operations will vary from platform
+** to platform. On platforms where atomic operations are not
+** supported the overhead may be substantial.
+**
+** When traversing the counter database with FindNext functions,
+** the instantaneous values of any given counter is that at the
+** moment of extraction. The state of the entire counter database
+** may not be viewed as atomic.
+**
+** The counter interface may be disabled (No-Op'd) at compile
+** time. When DEBUG is defined at compile time, the Counter
+** Feature is compiled into NSPR and applications invoking it.
+** When DEBUG is not defined, the counter macros compile to
+** nothing. To force the Counter Feature to be compiled into an
+** optimized build, define FORCE_NSPR_COUNTERS at compile time
+** for both NSPR and the application intending to use it.
+**
+** Application designers should use the macro form of the Counter
+** Feature methods to minimize performance impact in optimized
+** builds. The macros normally compile to nothing on optimized
+** builds.
+**
+** Application designers should be aware of the effects of
+** debug and optimized build differences when using result of the
+** Counter Feature macros in expressions.
+**
+** The Counter Feature is thread-safe and SMP safe.
+**
+** /lth. 09-Jun-1998.
+*/
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Opaque counter handle type.
+** ... don't even think of looking in here.
+**
+*/
+typedef void * PRCounterHandle;
+
+#define PRCOUNTER_NAME_MAX 31
+#define PRCOUNTER_DESC_MAX 255
+
+
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DEFINE_COUNTER() -- Define a PRCounterHandle
+**
+** DESCRIPTION: PR_DEFINE_COUNTER() is used to define a counter
+** handle.
+**
+*/
+#define PR_DEFINE_COUNTER(name) PRCounterHandle name
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_INIT_COUNTER_HANDLE() -- Set the value of a PRCounterHandle
+**
+** DESCRIPTION:
+** PR_INIT_COUNTER_HANDLE() sets the value of a PRCounterHandle
+** to value.
+**
+*/
+#define PR_INIT_COUNTER_HANDLE(handle,value)\
+ (handle) = (PRCounterHandle)(value)
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateCounter() -- Create a counter
+**
+** DESCRIPTION: PR_CreateCounter() creates a counter object and
+** initializes it to zero.
+**
+** The macro form takes as its first argument the name of the
+** PRCounterHandle to receive the handle returned from
+** PR_CreateCounter().
+**
+** INPUTS:
+** qName: The QName for the counter object. The maximum length
+** of qName is defined by PRCOUNTER_NAME_MAX
+**
+** rName: The RName for the counter object. The maximum length
+** of qName is defined by PRCOUNTER_NAME_MAX
+**
+** descrioption: The description of the counter object. The
+** maximum length of description is defined by
+** PRCOUNTER_DESC_MAX.
+**
+** OUTPUTS:
+**
+** RETURNS:
+** PRCounterHandle.
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_CREATE_COUNTER(handle,qName,rName,description)\
+ (handle) = PR_CreateCounter((qName),(rName),(description))
+
+PR_EXTERN(PRCounterHandle)
+ PR_CreateCounter(
+ const char *qName,
+ const char *rName,
+ const char *description
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyCounter() -- Destroy a counter object.
+**
+** DESCRIPTION: PR_DestroyCounter() removes a counter and
+** unregisters its handle from the counter database.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be destroyed.
+**
+** OUTPUTS:
+** The counter is destroyed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_DESTROY_COUNTER(handle) PR_DestroyCounter((handle))
+
+PR_EXTERN(void)
+ PR_DestroyCounter(
+ PRCounterHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounterHandleFromName() -- Retreive a
+** counter's handle give its name.
+**
+** DESCRIPTION: PR_GetCounterHandleFromName() retreives a
+** counter's handle from the counter database, given the name
+** the counter was originally created with.
+**
+** INPUTS:
+** qName: Counter's original QName.
+** rName: Counter's original RName.
+**
+** OUTPUTS:
+**
+** RETURNS:
+** PRCounterHandle or PRCounterError.
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)\
+ (handle) = PR_GetCounterHandleFromName((qName),(rName))
+
+PR_EXTERN(PRCounterHandle)
+ PR_GetCounterHandleFromName(
+ const char *qName,
+ const char *rName
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounterNameFromHandle() -- Retreive a
+** counter's name, given its handle.
+**
+** DESCRIPTION: PR_GetCounterNameFromHandle() retreives a
+** counter's name given its handle.
+**
+** INPUTS:
+** qName: Where to store a pointer to qName.
+** rName: Where to store a pointer to rName.
+** description: Where to store a pointer to description.
+**
+** OUTPUTS: Pointers to the Counter Feature's copies of the names
+** used when the counters were created.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description)\
+ PR_GetCounterNameFromHandle((handle),(qName),(rName),(description))
+
+PR_EXTERN(void)
+ PR_GetCounterNameFromHandle(
+ PRCounterHandle handle,
+ const char **qName,
+ const char **rName,
+ const char **description
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_IncrementCounter() -- Add one to the referenced
+** counter.
+**
+** DESCRIPTION: Add one to the referenced counter.
+**
+** INPUTS:
+** handle: The PRCounterHandle of the counter to be incremented
+**
+** OUTPUTS: The counter is incrementd.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_INCREMENT_COUNTER(handle) PR_IncrementCounter(handle)
+
+PR_EXTERN(void)
+ PR_IncrementCounter(
+ PRCounterHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DecrementCounter() -- Subtract one from the
+** referenced counter
+**
+** DESCRIPTION: Subtract one from the referenced counter.
+**
+** INPUTS:
+** handle: The PRCounterHandle of the coutner to be
+** decremented.
+**
+** OUTPUTS: the counter is decremented.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_DECREMENT_COUNTER(handle) PR_DecrementCounter(handle)
+
+PR_EXTERN(void)
+ PR_DecrementCounter(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_AddToCounter() -- Add a value to a counter.
+**
+** DESCRIPTION: Add value to the counter referenced by handle.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be added to.
+**
+** value: the value to be added to the counter.
+**
+** OUTPUTS: new value for counter.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_ADD_TO_COUNTER(handle,value)\
+ PR_AddToCounter((handle),(value))
+
+PR_EXTERN(void)
+ PR_AddToCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SubtractFromCounter() -- A value is subtracted
+** from a counter.
+**
+** DESCRIPTION:
+** Subtract a value from a counter.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be subtracted
+** from.
+**
+** value: the value to be subtracted from the counter.
+**
+** OUTPUTS: new value for counter
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_SUBTRACT_FROM_COUNTER(handle,value)\
+ PR_SubtractFromCounter((handle),(value))
+
+PR_EXTERN(void)
+ PR_SubtractFromCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounter() -- Retreive the value of a counter
+**
+** DESCRIPTION:
+** Retreive the value of a counter.
+**
+** INPUTS:
+** handle: the PR_CounterHandle of the counter to be retreived
+**
+** OUTPUTS:
+**
+** RETURNS: The value of the referenced counter
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_COUNTER(counter,handle)\
+ (counter) = PR_GetCounter((handle))
+
+PR_EXTERN(PRUint32)
+ PR_GetCounter(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SetCounter() -- Replace the content of counter
+** with value.
+**
+** DESCRIPTION: The contents of the referenced counter are
+** replaced by value.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter whose contents
+** are to be replaced.
+**
+** value: the new value of the counter.
+**
+** OUTPUTS:
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_SET_COUNTER(handle,value) PR_SetCounter((handle),(value))
+
+PR_EXTERN(void)
+ PR_SetCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextCounterQname() -- Retreive the next QName counter
+** handle iterator
+**
+** DESCRIPTION:
+** PR_FindNextCounterQname() retreives the first or next Qname
+** the counter data base, depending on the value of handle. When
+** handle is NULL, the function attempts to retreive the first
+** QName handle in the database. When handle is a handle previosly
+** retreived QName handle, then the function attempts to retreive
+** the next QName handle.
+**
+** INPUTS:
+** handle: PRCounterHandle or NULL.
+**
+** OUTPUTS: returned
+**
+** RETURNS: PRCounterHandle or NULL when no more QName counter
+** handles are present.
+**
+** RESTRICTIONS:
+** A concurrent PR_CreateCounter() or PR_DestroyCounter() may
+** cause unpredictable results.
+**
+** A PRCounterHandle returned from this function may only be used
+** in another PR_FindNextCounterQname() function call; other
+** operations may cause unpredictable results.
+**
+*/
+#define PR_FIND_NEXT_COUNTER_QNAME(next,handle)\
+ (next) = PR_FindNextCounterQname((handle))
+
+PR_EXTERN(PRCounterHandle)
+ PR_FindNextCounterQname(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextCounterRname() -- Retreive the next RName counter
+** handle iterator
+**
+** DESCRIPTION:
+** PR_FindNextCounterRname() retreives the first or next RNname
+** handle from the counter data base, depending on the
+** value of handle. When handle is NULL, the function attempts to
+** retreive the first RName handle in the database. When handle is
+** a handle previosly retreived RName handle, then the function
+** attempts to retreive the next RName handle.
+**
+** INPUTS:
+** handle: PRCounterHandle or NULL.
+** qhandle: PRCounterHandle of a previously aquired via
+** PR_FIND_NEXT_QNAME_HANDLE()
+**
+** OUTPUTS: returned
+**
+** RETURNS: PRCounterHandle or NULL when no more RName counter
+** handles are present.
+**
+** RESTRICTIONS:
+** A concurrent PR_CreateCounter() or PR_DestroyCounter() may
+** cause unpredictable results.
+**
+** A PRCounterHandle returned from this function may only be used
+** in another PR_FindNextCounterRname() function call; other
+** operations may cause unpredictable results.
+**
+*/
+#define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)\
+ (next) = PR_FindNextCounterRname((rhandle),(qhandle))
+
+PR_EXTERN(PRCounterHandle)
+ PR_FindNextCounterRname(
+ PRCounterHandle rhandle,
+ PRCounterHandle qhandle
+);
+
+
+#else /* ( !(defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)) */
+/*
+** When counters are not compiled in, provide macros that
+** evaluate to No-Ops.
+**
+*/
+
+#define PR_DEFINE_COUNTER(name) PRCounterHandle name
+#define PR_INIT_COUNTER_HANDLE(handle,value)
+#define PR_CREATE_COUNTER(handle,qName,rName,description)
+#define PR_DESTROY_COUNTER(handle)
+#define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)
+#define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description )
+#define PR_INCREMENT_COUNTER(handle)
+#define PR_DECREMENT_COUNTER(handle)
+#define PR_ADD_TO_COUNTER(handle,value)
+#define PR_SUBTRACT_FROM_COUNTER(handle,value)
+#define PR_GET_COUNTER(counter,handle) 0
+#define PR_SET_COUNTER(handle,value)
+#define PR_FIND_NEXT_COUNTER_QNAME(next,handle) NULL
+#define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)
+
+#endif /* ( !(defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)) */
+
+PR_END_EXTERN_C
+
+#endif /* prcountr_h___ */
diff --git a/pr/include/prdtoa.h b/pr/include/prdtoa.h
index fec81a59..22cfc58c 100644
--- a/pr/include/prdtoa.h
+++ b/pr/include/prdtoa.h
@@ -21,12 +21,6 @@
#include "prtypes.h"
-/*******************************************************************************/
-/*******************************************************************************/
-/****************** THESE FUNCTIONS MAY NOT BE THREAD SAFE *********************/
-/*******************************************************************************/
-/*******************************************************************************/
-
PR_BEGIN_EXTERN_C
/*
diff --git a/pr/include/prerror.h b/pr/include/prerror.h
index 0f56f106..dbb7256b 100644
--- a/pr/include/prerror.h
+++ b/pr/include/prerror.h
@@ -25,7 +25,7 @@ PR_BEGIN_EXTERN_C
typedef PRInt32 PRErrorCode;
-#define PR_NSPR_ERROR_BASE -2600
+#define PR_NSPR_ERROR_BASE -6000
#define PR_OUT_OF_MEMORY_ERROR PR_NSPR_ERROR_BASE + 0
/* Insufficient memory to perform request */
@@ -147,7 +147,11 @@ typedef PRInt32 PRErrorCode;
#define PR_ALREADY_INITIATED_ERROR PR_NSPR_ERROR_BASE + 67
#define PR_GROUP_EMPTY_ERROR PR_NSPR_ERROR_BASE + 68
#define PR_INVALID_STATE_ERROR PR_NSPR_ERROR_BASE + 69
-#define PR_MAX_ERROR PR_NSPR_ERROR_BASE + 70
+#define PR_NETWORK_DOWN_ERROR PR_NSPR_ERROR_BASE + 70
+#define PR_SOCKET_SHUTDOWN_ERROR PR_NSPR_ERROR_BASE + 71
+#define PR_CONNECT_ABORTED_ERROR PR_NSPR_ERROR_BASE + 72
+#define PR_HOST_UNREACHABLE_ERROR PR_NSPR_ERROR_BASE + 73
+#define PR_MAX_ERROR PR_NSPR_ERROR_BASE + 74
/* Place holder for the end of the list */
/*
diff --git a/pr/include/prinit.h b/pr/include/prinit.h
index cf1d5fa2..7ba12fea 100644
--- a/pr/include/prinit.h
+++ b/pr/include/prinit.h
@@ -44,7 +44,11 @@ PR_BEGIN_EXTERN_C
** The format of the version string is
** "<major version>.<minor version> <build date>"
*/
-#define PR_VERSION "2.1 yyyymmdd"
+#define PR_VERSION "3.0 yyyymmdd"
+#define PR_VMAJOR 3
+#define PR_VMINOR 0
+#define PR_VPATCH 0
+#define PR_BETA PR_TRUE
/*
** PRVersionCheck
@@ -81,8 +85,7 @@ PR_EXTERN(PRBool) PR_VersionCheck(const char *importedVersion);
/*
** Initialize the runtime. Attach a thread object to the currently
-** executing native thread of type "type" (as if PR_AttachThread were
-** called).
+** executing native thread of type "type".
**
** The specificaiton of 'maxPTDs' is ignored.
*/
@@ -142,6 +145,12 @@ PR_EXTERN(PRStatus) PR_Cleanup(void);
PR_EXTERN(void) PR_DisableClockInterrupts(void);
/*
+** Enables Interrupts
+** Enables timer signals used for pre-emptive scheduling.
+*/
+PR_EXTERN(void) PR_EnableClockInterrupts(void);
+
+/*
** Block Interrupts
** Blocks the timer signal used for pre-emptive scheduling
*/
@@ -159,6 +168,13 @@ PR_EXTERN(void) PR_UnblockClockInterrupts(void);
PR_EXTERN(void) PR_SetConcurrency(PRUintn numCPUs);
/*
+** Control the method and size of the file descriptor (PRFileDesc*)
+** cache used by the runtime. Setting 'high' to zero is for performance,
+** any other value probably for debugging (see memo on FD caching).
+*/
+PR_EXTERN(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high);
+
+/*
* Cause an immediate, nongraceful, forced termination of the process.
* It takes a PRIntn argument, which is the exit status code of the
* process.
diff --git a/pr/include/prio.h b/pr/include/prio.h
index 1cc6719e..89ffb871 100644
--- a/pr/include/prio.h
+++ b/pr/include/prio.h
@@ -1408,8 +1408,7 @@ PR_EXTERN(PRInt32) PR_TransmitFile(
** void *buf
** A pointer to a buffer to receive data sent by the client. This
** buffer must be large enough to receive <amount> bytes of data
-** and two PRNetAddr structures (thus allowing the runtime to align
-** the addresses as needed).
+** and two PRNetAddr structures, plus an extra 32 bytes.
** PRInt32 amount
** The number of bytes of client data to receive. Does not include
** the size of the PRNetAddr structures. If 0, no data will be read
@@ -1425,7 +1424,8 @@ PR_EXTERN(PRInt32) PR_TransmitFile(
** will only be valid if the function return does not indicate failure.
** PRNetAddr **peerAddr,
** The address of the remote socket. This parameter will only be
-** valid if the function return does not indicate failure.
+** valid if the function return does not indicate failure. The
+** returned address is not guaranteed to be properly aligned.
**
** RETURNS:
** The number of bytes read from the client or -1 on failure. The reason
@@ -1570,12 +1570,9 @@ struct PRPollDesc {
/*
** Bit values for PRPollDesc.in_flags or PRPollDesc.out_flags. Binary-or
** these together to produce the desired poll request.
-**
-** On Unix platforms where the poll() system call is available,
-** the various PR_POLL_XXX flags are mapped to the native poll flags.
*/
-#if defined(XP_UNIX) && defined(_PR_POLL_AVAILABLE)
+#if defined(_PR_POLL_BACKCOMPAT)
#include <poll.h>
#define PR_POLL_READ POLLIN
@@ -1583,16 +1580,18 @@ struct PRPollDesc {
#define PR_POLL_EXCEPT POLLPRI
#define PR_POLL_ERR POLLERR /* only in out_flags */
#define PR_POLL_NVAL POLLNVAL /* only in out_flags when fd is bad */
+#define PR_POLL_HUP POLLHUP /* only in out_flags */
-#else /* XP_UNIX, _PR_POLL_AVAILABLE */
+#else /* _PR_POLL_BACKCOMPAT */
#define PR_POLL_READ 0x1
#define PR_POLL_WRITE 0x2
#define PR_POLL_EXCEPT 0x4
#define PR_POLL_ERR 0x8 /* only in out_flags */
#define PR_POLL_NVAL 0x10 /* only in out_flags when fd is bad */
+#define PR_POLL_HUP 0x20 /* only in out_flags */
-#endif /* XP_UNIX, _PR_POLL_AVAILABLE */
+#endif /* _PR_POLL_BACKCOMPAT */
/*
*************************************************************************
@@ -1632,6 +1631,55 @@ struct PRPollDesc {
PR_EXTERN(PRInt32) PR_Poll(
PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout);
+/*
+**************************************************************************
+**
+** Pollable events
+**
+** A pollable event is a special kind of file descriptor.
+** The only I/O operation you can perform on a pollable event
+** is to poll it with the PR_POLL_READ flag. You can't
+** read from or write to a pollable event.
+**
+** The purpose of a pollable event is to combine event waiting
+** with I/O waiting in a single PR_Poll call. Pollable events
+** are implemented using a pipe or a pair of TCP sockets
+** connected via the loopback address, therefore setting and
+** waiting for pollable events are expensive operating system
+** calls. Do not use pollable events for general thread
+** synchronization. Use condition variables instead.
+**
+** A pollable event has two states: set and unset. Events
+** are not queued, so there is no notion of an event count.
+** A pollable event is either set or unset.
+**
+** A new pollable event is created by a PR_NewPollableEvent
+** call and is initially in the unset state.
+**
+** PR_WaitForPollableEvent blocks the calling thread until
+** the pollable event is set, and then it atomically unsets
+** the pollable event before it returns.
+**
+** To set a pollable event, call PR_SetPollableEvent.
+**
+** One can call PR_Poll with the PR_POLL_READ flag on a pollable
+** event. When the pollable event is set, PR_Poll returns with
+** the PR_POLL_READ flag set in the out_flags.
+**
+** To close a pollable event, call PR_DestroyPollableEvent
+** (not PR_Close).
+**
+**************************************************************************
+*/
+
+PR_EXTERN(PRFileDesc *) PR_NewPollableEvent(void);
+
+PR_EXTERN(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event);
+
+PR_EXTERN(PRStatus) PR_SetPollableEvent(PRFileDesc *event);
+
+PR_EXTERN(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event);
+
PR_END_EXTERN_C
#endif /* prio_h___ */
diff --git a/pr/include/private/Makefile b/pr/include/private/Makefile
index c2e38c41..3a8b1e9f 100644
--- a/pr/include/private/Makefile
+++ b/pr/include/private/Makefile
@@ -24,7 +24,7 @@ include $(MOD_DEPTH)/config/config.mk
RELEASE_HEADERS = pprio.h pprthred.h prpriv.h
RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/private
-HEADERS = $(RELEASE_HEADERS) primpl.h
+HEADERS = $(RELEASE_HEADERS) pprmwait.h primpl.h
include $(MOD_DEPTH)/config/rules.mk
diff --git a/pr/include/private/pprio.h b/pr/include/private/pprio.h
index c9d6eec1..7e73b31e 100644
--- a/pr/include/private/pprio.h
+++ b/pr/include/private/pprio.h
@@ -28,8 +28,19 @@
#include "prtypes.h"
#include "prio.h"
-NSPR_BEGIN_EXTERN_C
+PR_BEGIN_EXTERN_C
+/*
+** File descriptors of the NSPR layer can be in one of the
+** following states (stored in the 'state' field of struct
+** PRFilePrivate):
+** - _PR_FILEDESC_OPEN: The OS fd is open.
+** - _PR_FILEDESC_CLOSED: The OS fd is closed. The PRFileDesc
+** is still open but is unusable. The only operation allowed
+** on the PRFileDesc is PR_Close().
+** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc
+** structure is freed.
+*/
#define _PR_FILEDESC_OPEN 0xaaaaaaaa /* 1010101... */
#define _PR_FILEDESC_CLOSED 0x55555555 /* 0101010... */
@@ -186,6 +197,6 @@ PR_EXTERN(void) PR_NT_UseNonblock();
#endif /* WIN32 */
-NSPR_END_EXTERN_C
+PR_END_EXTERN_C
#endif /* pprio_h___ */
diff --git a/pr/src/io/pprmwait.h b/pr/include/private/pprmwait.h
index adfce668..edad3420 100644
--- a/pr/src/io/pprmwait.h
+++ b/pr/include/private/pprmwait.h
@@ -31,8 +31,8 @@
#define MAX_POLLING_INTERVAL 100
#define _PR_DEFAULT_HASH_LENGTH 59
-#define _MW_REHASH(a, i, m) _MW_HASH((PRUword)(a) + (i) + _PR_HASH_OFFSET, m)
-#define _MW_HASH(a, m) ((((PRUword)(a) >> 4) ^ ((PRUword)(a) >> 10)) % (m))
+#define _MW_REHASH(a, i, m) _MW_HASH((PRUptrdiff)(a) + (i) + _PR_HASH_OFFSET, m)
+#define _MW_HASH(a, m) ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m))
#define _MW_ABORTED(_rv) \
((PR_FAILURE == (_rv)) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
@@ -61,17 +61,52 @@ struct PRWaitGroup
PRThread* poller; /* thread that's actually doing the poll() */
PRUint16 waiting_threads; /* number of threads waiting for recv */
PRUint16 polling_count; /* number of elements in the polling list */
+ PRUint32 p_timestamp; /* pseudo-time group had element removed */
PRPollDesc *polling_list; /* list poller builds for polling */
PRIntervalTime last_poll; /* last time we polled */
_PRWaiterHash *waiter; /* pointer to hash table of wait receive objects */
+
+#ifdef WINNT
+ /*
+ * On NT, idle threads are responsible for getting completed i/o.
+ * They need to add completed i/o to the io_ready list. Since
+ * idle threads cannot use nspr locks, we have to use an md lock
+ * to protect the io_ready list.
+ */
+ _MDLock mdlock; /* protect io_ready, waiter, and wait_list */
+ PRCList wait_list; /* used in place of io_complete. reuse
+ * waitQLinks in the PRThread structure. */
+#endif /* WINNT */
};
+/**********************************************************************
+***********************************************************************
+******************** Wait group enumerations **************************
+***********************************************************************
+**********************************************************************/
typedef struct _PRGlobalState
{
PRCList group_list; /* master of the group list */
PRWaitGroup *group; /* the default (NULL) group */
} _PRGlobalState;
+#ifdef WINNT
+extern PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd);
+#endif
+
+typedef enum {_PR_ENUM_UNSEALED=0, _PR_ENUM_SEALED=0x0eadface} _PREnumSeal;
+
+struct PRMWaitEnumerator
+{
+ PRWaitGroup *group; /* group this enumerator is bound to */
+ PRThread *thread; /* thread in midst of an enumeration */
+ _PREnumSeal seal; /* trying to detect deleted objects */
+ PRUint32 p_timestamp; /* when enumeration was (re)started */
+ PRRecvWait **waiter; /* pointer into hash table */
+ PRUintn index; /* position in hash table */
+ void *pad[4]; /* some room to grow */
+};
+
#endif /* defined(_PPRMWAIT_H) */
/* pprmwait.h */
diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h
index 0d4bd69d..f4c32230 100644
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -46,6 +46,8 @@
#include "nspr.h"
#include "prpriv.h"
+typedef struct PRSegment PRSegment;
+
#ifdef XP_MAC
#include "prosdep.h"
#include "probslet.h"
@@ -128,18 +130,6 @@ typedef struct _MDFileMap _MDFileMap;
** stuff, this is a pretty small set.
*/
-struct _PT_Bookeeping
-{
- PRLock *ml; /* a lock to protect ourselves */
- PRCondVar *cv; /* used to signal global things */
- PRUint16 system, user; /* a count of the two different types */
- PRUintn this_many; /* number of threads allowed for exit */
- pthread_key_t key; /* private private data key */
- pthread_key_t highwater; /* ordinal value of next key to be allocated */
- PRThread *first, *last; /* list of threads we know about */
- PRInt32 minPrio, maxPrio; /* range of scheduling priorities */
-};
-
#define PT_CV_NOTIFIED_LENGTH 6
typedef struct _PT_Notified _PT_Notified;
struct _PT_Notified
@@ -162,7 +152,8 @@ struct _PT_Notified
#define PT_THREAD_PRIMORD 0x08 /* this is the primordial thread */
#define PT_THREAD_ABORTED 0x10 /* thread has been interrupted */
#define PT_THREAD_GCABLE 0x20 /* thread is garbage collectible */
-#define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */
+#define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */
+#define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */
/*
** Possible values for thread's suspend field
@@ -189,13 +180,23 @@ typedef struct PTDebug
PRUintn cvars_notified, delayed_cv_deletes;
} PTDebug;
-PR_EXTERN(PTDebug) PT_GetStats(void);
+PR_EXTERN(void) PT_GetStats(PTDebug* here);
PR_EXTERN(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
+#else
+
+typedef PRUintn PTDebug;
+#define PT_GetStats(_p)
+#define PT_FPrintStats(_fd, _msg)
+
#endif /* defined(DEBUG) */
#else /* defined(_PR_PTHREADS) */
+typedef PRUintn PTDebug;
+#define PT_GetStats(_p)
+#define PT_FPrintStats(_fd, _msg)
+
/*
** This section is contains those parts needed to implement NSPR on
** platforms in general. One would assume that the pthreads implementation
@@ -273,7 +274,7 @@ typedef struct _PRInterruptTable {
#define _PR_CPU_PTR(_qp) \
((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links)))
-#if !defined(IRIX)
+#if !defined(IRIX) && !defined(WIN32)
#define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD())
#endif
@@ -305,8 +306,6 @@ PR_EXTERN(PRInt32) _pr_intsOff;
#define _MD_GET_INTSOFF() 0
#define _MD_SET_INTSOFF(_val)
-#define _PR_SET_INTSOFF(_is)
-#define _PR_GET_INTSOFF(_is)
#define _PR_INTSOFF(_is)
#define _PR_FAST_INTSON(_is)
#define _PR_INTSON(_is)
@@ -337,11 +336,6 @@ PR_EXTERN(PRInt32) _pr_intsOff;
#else
-#define _PR_SET_INTSOFF(_val) \
- PR_BEGIN_MACRO \
- _PR_MD_SET_INTSOFF(_val); \
- PR_END_MACRO
-
#define _PR_INTSOFF(_is) \
PR_BEGIN_MACRO \
(_is) = _PR_MD_GET_INTSOFF(); \
@@ -556,14 +550,6 @@ typedef struct _PRPerThreadExit {
void *arg;
} _PRPerThreadExit;
-/*
- * Thread private data destructor array
- * There is a destructor (or NULL) associated with each key and
- * applied to all threads known to the system.
- * Storage allocated in prtpd.c.
- */
-extern PRThreadPrivateDTOR *_pr_tpd_destructors;
-
/* PRThread.flags */
#define _PR_SYSTEM 0x01
#define _PR_INTERRUPT 0x02
@@ -575,7 +561,7 @@ extern PRThreadPrivateDTOR *_pr_tpd_destructors;
#define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */
#define _PR_IDLE_THREAD 0x200 /* this is an idle thread */
#define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */
-#define _PR_BOUND_THREAD 0x800 /* a bound thread (only on solaris) */
+#define _PR_BOUND_THREAD 0x800 /* a bound thread */
/* PRThread.state */
#define _PR_UNBORN 0
@@ -667,9 +653,9 @@ extern PRUint32 _pr_utid;
extern struct _PRCPU *_pr_primordialCPU;
extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */
-extern PRUintn _pr_userActive; /* number of active user threads */
-extern PRUintn _pr_systemActive; /* number of active system threads */
-extern PRUintn _pr_primordialExitCount; /* number of user threads left
+extern PRInt32 _pr_userActive; /* number of active user threads */
+extern PRInt32 _pr_systemActive; /* number of active system threads */
+extern PRInt32 _pr_primordialExitCount; /* number of user threads left
* before the primordial thread
* can exit. */
extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for
@@ -718,10 +704,13 @@ PR_EXTERN(PRThread*) _PR_CreateThread(PRThreadType type,
extern void _PR_NativeDestroyThread(PRThread *thread);
extern void _PR_UserDestroyThread(PRThread *thread);
-PR_EXTERN(PRThread*) _PRI_AttachThread(
+extern PRThread* _PRI_AttachThread(
PRThreadType type, PRThreadPriority priority,
PRThreadStack *stack, PRUint32 flags);
+extern void _PRI_DetachThread(void);
+
+
#define _PR_IO_PENDING(_thread) ((_thread)->io_pending)
PR_EXTERN(void) _PR_MD_INIT_CPUS();
@@ -735,6 +724,9 @@ PR_EXTERN(void) _PR_MD_WAKEUP_CPUS();
PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void);
#define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS
+PR_EXTERN(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void);
+#define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS
+
PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
#define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS
@@ -995,34 +987,16 @@ extern PRInt32 _PR_MD_WRITEV(
PRInt32 iov_size, PRIntervalTime timeout);
#define _PR_MD_WRITEV _MD_WRITEV
-extern PRInt32 _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int whence);
-#define _PR_MD_LSEEK _MD_LSEEK
-
-extern PRInt64 _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, int whence);
-#define _PR_MD_LSEEK64 _MD_LSEEK64
-
extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd);
#define _PR_MD_FSYNC _MD_FSYNC
extern PRInt32 _PR_MD_DELETE(const char *name);
#define _PR_MD_DELETE _MD_DELETE
-extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info);
-#define _PR_MD_GETFILEINFO _MD_GETFILEINFO
-
-extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info);
-#define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64
-
-extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info);
-#define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO
-
-extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info);
-#define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64
-
extern PRInt32 _PR_MD_RENAME(const char *from, const char *to);
#define _PR_MD_RENAME _MD_RENAME
-extern PRInt32 _PR_MD_ACCESS(const char *name, PRIntn how);
+extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how);
#define _PR_MD_ACCESS _MD_ACCESS
extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf);
@@ -1174,16 +1148,63 @@ PR_EXTERN(void *) _PR_MD_GET_SP(PRThread *thread);
*************************************************************************/
/************************************************************************/
+extern PRInt32 _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence);
+#define _PR_MD_LSEEK _MD_LSEEK
+
+extern PRInt64 _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence);
+#define _PR_MD_LSEEK64 _MD_LSEEK64
+
+extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info);
+#define _PR_MD_GETFILEINFO _MD_GETFILEINFO
+
+extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info);
+#define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64
+
+extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info);
+#define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO
+
+extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info);
+#define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64
+
+
+/*****************************************************************************/
+/************************** File descriptor caching **************************/
+/*****************************************************************************/
+extern void _PR_InitFdCache(void);
+extern void _PR_CleanupFdCache(void);
+extern PRFileDesc *_PR_Getfd(void);
+extern void _PR_Putfd(PRFileDesc *fd);
+
+/*
+ * These flags are used by NSPR temporarily in the poll
+ * descriptor's out_flags field to record the mapping of
+ * NSPR's poll flags to the system poll flags.
+ *
+ * If _PR_POLL_READ_SYS_WRITE bit is set, it means the
+ * PR_POLL_READ flag specified by the topmost layer is
+ * mapped to the WRITE flag at the system layer. Similarly
+ * for the other three _PR_POLL_XXX_SYS_YYY flags. It is
+ * assumed that the PR_POLL_EXCEPT flag doesn't get mapped
+ * to other flags.
+ */
+#define _PR_POLL_READ_SYS_READ 0x1
+#define _PR_POLL_READ_SYS_WRITE 0x2
+#define _PR_POLL_WRITE_SYS_READ 0x4
+#define _PR_POLL_WRITE_SYS_WRITE 0x8
+
/*
** These methods are coerced into file descriptor methods table
** when the intended service is inappropriate for the particular
** type of file descriptor.
*/
extern PRIntn _PR_InvalidInt(void);
+extern PRInt16 _PR_InvalidInt16(void);
extern PRInt64 _PR_InvalidInt64(void);
extern PRStatus _PR_InvalidStatus(void);
extern PRFileDesc *_PR_InvalidDesc(void);
+extern PRIOMethods _pr_faulty_methods;
+
extern PRStatus _PR_MapOptionName(
PRSockOption optname, PRInt32 *level, PRInt32 *name);
extern void _PR_InitThreads(
@@ -1229,9 +1250,9 @@ struct PRCondVar {
struct PRMonitor {
const char* name; /* monitor name for debugging */
#if defined(_PR_PTHREADS)
- PRLock lock; /* the lock struture structure */
+ PRLock lock; /* the lock struture structure */
pthread_t owner; /* the owner of the lock or zero */
- PRCondVar cvar; /* condition variable queue */
+ PRCondVar *cvar; /* condition variable queue */
#else /* defined(_PR_PTHREADS) */
PRCondVar *cvar; /* associated lock and condition variable queue */
#endif /* defined(_PR_PTHREADS) */
@@ -1274,19 +1295,23 @@ struct PRThreadStack {
#endif /* defined(_PR_PTHREADS) */
};
+/*
+ * Thread private data destructor array
+ * There is a destructor (or NULL) associated with each key and
+ * applied to all threads known to the system.
+ * Storage allocated in prtpd.c.
+ */
+extern PRThreadPrivateDTOR *_pr_tpd_destructors;
+extern void _PR_DestroyThreadPrivate(PRThread*);
+typedef void (PR_CALLBACK *_PRStartFn)(void *);
struct PRThread {
PRUint32 state; /* thread's creation state */
PRThreadPriority priority; /* apparent priority, loosly defined */
- PRInt32 errorStringSize; /* byte length of current error string | zero */
- PRErrorCode errorCode; /* current NSPR error code | zero */
- PRInt32 osErrorCode; /* mapping of errorCode | zero */
-
- char *errorString; /* current error string | NULL */
void *arg; /* argument to the client's entry point */
- void (PR_CALLBACK *startFunc)(void *arg); /* the root of the client's thread */
+ _PRStartFn startFunc; /* the root of the client's thread */
PRThreadStack *stack; /* info about thread's stack (for GC) */
void *environment; /* pointer to execution environment */
@@ -1294,6 +1319,16 @@ struct PRThread {
PRThreadDumpProc dump; /* dump thread info out */
void *dumpArg; /* argument for the dump function */
+ /*
+ ** Per thread private data
+ */
+ PRUint32 tpdLength; /* thread's current vector length */
+ void **privateData; /* private data vector or NULL */
+ PRInt32 errorStringSize; /* byte length of current error string | zero */
+ PRErrorCode errorCode; /* current NSPR error code | zero */
+ PRInt32 osErrorCode; /* mapping of errorCode | zero */
+ char *errorString; /* current error string | NULL */
+
#if defined(_PR_PTHREADS)
pthread_t id; /* pthread identifier for the thread */
PRBool okToDelete; /* ok to delete the PRThread struct? */
@@ -1308,13 +1343,13 @@ struct PRThread {
#endif
#else /* defined(_PR_PTHREADS) */
_MDLock threadLock; /* Lock to protect thread state variables.
- * Protects the following fields:
- * state
- * priority
- * links
- * wait
- * cpu
- */
+ * Protects the following fields:
+ * state
+ * priority
+ * links
+ * wait
+ * cpu
+ */
PRUint32 queueCount;
PRUint32 waitCount;
@@ -1330,17 +1365,24 @@ struct PRThread {
PRUint32 id;
PRUint32 flags;
- PRUint32 no_sched;
+ PRUint32 no_sched; /* Don't schedule the thread to run.
+ * This flag has relevance only when
+ * multiple NSPR CPUs are created.
+ * When a thread is de-scheduled, there
+ * is a narrow window of time in which
+ * the thread is put on the run queue
+ * but the scheduler is actually using
+ * the stack of this thread. It is safe
+ * to run this thread on a different CPU
+ * only when its stack is not in use on
+ * any other CPU. The no_sched flag is
+ * set during this interval to prevent
+ * the thread from being scheduled on a
+ * different CPU.
+ */
PRUint32 numExits;
_PRPerThreadExit *ptes;
-
- /*
- ** Per thread private data
- */
- PRUint32 tpdLength; /* thread's current vector length */
- void **privateData; /* private data vector or NULL */
-
/* thread termination condition variable for join */
PRCondVar *term;
@@ -1413,6 +1455,7 @@ extern void _PR_InitLinker(void);
extern void _PR_InitAtomic(void);
extern void _PR_InitCPUs(void);
extern void _PR_InitDtoa(void);
+extern void _PR_InitMW(void);
extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me);
extern void _PR_CleanupThread(PRThread *thread);
extern void _PR_CleanupTPD(void);
@@ -1427,7 +1470,6 @@ extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred);
/************************************************************************/
struct PRSegment {
- PRSegmentAccess access;
void *vaddr;
PRUint32 size;
PRUintn flags;
@@ -1440,6 +1482,32 @@ struct PRSegment {
/* PRSegment.flags */
#define _PR_SEG_VM 0x1
+/***********************************************************************
+** FUNCTION: _PR_NewSegment()
+** DESCRIPTION:
+** Allocate a memory segment. The "size" value is rounded up to the
+** native system page size and a page aligned portion of memory is
+** returned. This memory is not part of the malloc heap. If "vaddr" is
+** not NULL then PR tries to allocate the segment at the desired virtual
+** address.
+** INPUTS: size: size of the desired memory segment
+** vaddr: address at which the newly aquired segment is to be
+** mapped into memory.
+** OUTPUTS: a memory segment is allocated, a PRSegment is allocated
+** RETURN: pointer to PRSegment
+***********************************************************************/
+extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr);
+
+/***********************************************************************
+** FUNCTION: _PR_DestroySegment()
+** DESCRIPTION:
+** The memory segment and the PRSegment are freed
+** INPUTS: seg: pointer to PRSegment to be freed
+** OUTPUTS: the the PRSegment and its associated memory segment are freed
+** RETURN: void
+***********************************************************************/
+extern void _PR_DestroySegment(PRSegment *seg);
+
/************************************************************************/
extern PRInt32 _pr_pageSize;
@@ -1465,14 +1533,9 @@ extern PRBool _pr_ipv6_enabled; /* defined in prnetdb.c */
/* Overriding malloc, free, etc. */
#if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \
- && (!defined(SOLARIS) || !defined(_PR_GLOBAL_THREADS_ONLY)) \
- && (!defined(AIX) || !defined(_PR_PTHREADS)) \
- && (!defined(OSF1) || !defined(_PR_PTHREADS)) \
- && (!defined(HPUX) || !defined(_PR_PTHREADS)) \
- && (!defined(IRIX) || !defined(_PR_PTHREADS)) \
- && (!defined(LINUX) || !defined(_PR_PTHREADS)) \
- && (!defined(RHAPSODY)) \
+ && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \
&& !defined(PURIFY) \
+ && !defined(RHAPSODY) \
&& !(defined (UNIXWARE) && defined (USE_SVR4_THREADS))
#define _PR_OVERRIDE_MALLOC
#endif
@@ -1531,6 +1594,9 @@ extern void _PR_MD_INIT_ATOMIC(void);
extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *);
#define _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT
+extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32);
+#define _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD
+
extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *);
#define _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT
diff --git a/pr/include/prlog.h b/pr/include/prlog.h
index 9be6c13f..8369c64c 100644
--- a/pr/include/prlog.h
+++ b/pr/include/prlog.h
@@ -74,7 +74,12 @@ PR_BEGIN_EXTERN_C
** log buffer to <size>.
**
** The environment variable NSPR_LOG_FILE specifies the log file to use
-** unless the default of "stderr" is acceptable.
+** unless the default of "stderr" is acceptable. For MS Windows
+** systems, NSPR_LOG_FILE can be set to a special value: "WinDebug"
+** (case sensitive). This value causes PR_LOG() output to be written
+** using the Windows API OutputDebugString(). OutputDebugString()
+** writes to the debugger window; some people find this helpful.
+**
**
** To put log messages in your programs, use the PR_LOG macro:
**
@@ -141,11 +146,6 @@ typedef struct PRLogModuleInfo {
PR_EXTERN(PRLogModuleInfo*) PR_NewLogModule(const char *name);
/*
-** Destroys a log module.
-*/
-PR_EXTERN(void) PR_DestroyLogModule(PRLogModuleInfo* logModule);
-
-/*
** Set the file to use for logging. Returns PR_FALSE if the file cannot
** be created
*/
diff --git a/pr/include/prmem.h b/pr/include/prmem.h
index dc88f755..2a6c766a 100644
--- a/pr/include/prmem.h
+++ b/pr/include/prmem.h
@@ -135,109 +135,6 @@ PR_EXTERN(void) PR_Free(void *ptr);
***********************************************************************/
#define PR_FREEIF(_ptr) if (_ptr) PR_DELETE(_ptr)
-/***********************************************************************
-** Typedef ENUM: PRSegmentAccess
-** DESCRIPTION:
-** Defines a number of segment accessor types for PR_Seg* functions
-**
-***********************************************************************/
-typedef struct PRSegment PRSegment;
-typedef enum {
- PR_SEGMENT_NONE,
- PR_SEGMENT_RDONLY,
- PR_SEGMENT_RDWR
-} PRSegmentAccess;
-
-/***********************************************************************
-** FUNCTION: PR_NewSegment()
-** DESCRIPTION:
-** Allocate a memory segment. The "size" value is rounded up to the
-** native system page size and a page aligned portion of memory is
-** returned. This memory is not part of the malloc heap. If "vaddr" is
-** not NULL then PR tries to allocate the segment at the desired virtual
-** address. Segments are mapped PR_SEGMENT_RDWR when created.
-** INPUTS: size: size of the desired memory segment
-** vaddr: address at which the newly aquired segment is to be
-** mapped into memory.
-** OUTPUTS: a memory segment is allocated, a PRSegment is allocated
-** RETURN: pointer to PRSegment
-***********************************************************************/
-PR_EXTERN(PRSegment*) PR_NewSegment(PRUint32 size, void *vaddr);
-
-/***********************************************************************
-** FUNCTION: PR_DestroySegment()
-** DESCRIPTION:
-** The memory segment and the PRSegment are freed
-** INPUTS: seg: pointer to PRSegment to be freed
-** OUTPUTS: the the PRSegment and its associated memory segment are freed
-** RETURN: void
-***********************************************************************/
-PR_EXTERN(void) PR_DestroySegment(PRSegment *seg);
-
-/***********************************************************************
-** FUNCTION: PR_GrowSegment()
-** DESCRIPTION:
-** Attempt to grow/shrink a memory segment. If deltaBytes is positive,
-** the segment is grown. If deltaBytes is negative, the segment is
-** shrunk. This returns the number of bytes added to the segment if
-** successful, zero otherwise.
-** INPUTS: seg: pointer to a PRSegment
-** OUTPUTS:
-** RETURN: PRUint32: number of bytes added to the memory segment or zero
-***********************************************************************/
-PR_EXTERN(PRUint32) PR_GrowSegment(PRSegment *seg, PRInt32 deltaBytes);
-
-/***********************************************************************
-** FUNCTION: PR_GetSegmentVaddr()
-** DESCRIPTION:
-** PR_Segment member accessor function.
-** Return the virtual address of the memory segment
-**
-** INPUTS: seg: pointer to a PRSegment
-** OUTPUTS: none
-** RETURN: void*: Address where the memory segment is mapped.
-***********************************************************************/
-PR_EXTERN(void*) PR_GetSegmentVaddr(PRSegment *seg);
-
-/***********************************************************************
-** FUNCTION: PR_GetSegmentSize()
-** DESCRIPTION:
-** PR_Segment member accessor function.
-** Return the size of the associated memory segment
-** INPUTS: seg: pointer to a PRSegment
-** OUTPUTS: none
-** RETURN: size_t: size of the associated memory segment
-***********************************************************************/
-PR_EXTERN(size_t) PR_GetSegmentSize(PRSegment *seg);
-
-/***********************************************************************
-** FUNCTION: PR_MapSegment()
-** DESCRIPTION:
-** Change the mapping on a segment.
-** "how" == PR_SEGMENT_NONE: the segment becomes unmapped
-** "how" == PR_SEGMENT_RDONLY: the segment becomes mapped and readable
-** "how" == PR_SEGMENT_RDWR: the segment becomes mapped read/write
-**
-** Note: If a segment can be read then it is also possible to execute
-** code in it.
-** INPUTS: seg: pointer to a PRSegment
-** how: one of PRSegmentAccess enumerated values
-** OUTPUTS: the access for the associated memory segment is changed
-** RETURN: void
-***********************************************************************/
-PR_EXTERN(void) PR_MapSegment(PRSegment *seg, PRSegmentAccess how);
-
-/***********************************************************************
-** FUNCTION: PR_GetSegmentAccess()
-** DESCRIPTION:
-** PR_Segment member accessor function.
-** Return a memory segment's current access rights
-** INPUTS: seg: pointer to a PRSegment
-** OUTPUTS:
-** RETURN: PRSegmentAccess: current access rights
-***********************************************************************/
-PR_EXTERN(PRSegmentAccess) PR_GetSegmentAccess(PRSegment *seg);
-
PR_END_EXTERN_C
#endif /* prmem_h___ */
diff --git a/pr/include/prmwait.h b/pr/include/prmwait.h
index c63398bd..91f44393 100644
--- a/pr/include/prmwait.h
+++ b/pr/include/prmwait.h
@@ -53,7 +53,7 @@ typedef struct PRWaitGroup PRWaitGroup;
** ENUMERATION: PRMWStatus
** DESCRIPTION:
** This enumeration is used to indicate the completion status of
-** a recieve wait object. Generally stated, a positive value indicates
+** a receive wait object. Generally stated, a positive value indicates
** that the operation is not yet complete. A zero value indicates
** success (similar to PR_SUCCESS) and any negative value is an
** indication of failure. The reason for the failure can be retrieved
@@ -94,6 +94,15 @@ typedef struct PRMemoryDescriptor
} PRMemoryDescriptor;
/*
+** STRUCTURE: PRMWaitClientData
+** DESCRIPTION:
+** An opague stucture for which a client MAY give provide a concrete
+** definition and associate with a receive descriptor. The NSPR runtime
+** does not manage this field. It is completely up to the client.
+*/
+typedef struct PRMWaitClientData PRMWaitClientData;
+
+/*
** STRUCTURE: PRRecvWait
** DESCRIPTION:
** A receive wait object contains the file descriptor that is subject
@@ -117,10 +126,22 @@ typedef struct PRRecvWait
PRMWStatus outcome; /* outcome of the current/last operation */
PRIntervalTime timeout; /* time allowed for entire operation */
- PRInt32 bytesRecv; /* number of bytes transferred into buffer */
+ PRInt32 bytesRecv; /* number of bytes transferred into buffer */
PRMemoryDescriptor buffer; /* where to store first segment of input data */
+ PRMWaitClientData *client; /* pointer to arbitrary client defined data */
} PRRecvWait;
+/*
+** STRUCTURE: PRMWaitEnumerator
+** DESCRIPTION:
+** An enumeration object is used to store the state of an existing
+** enumeration over a wait group. The opaque object must be allocated
+** by the client and the reference presented on each call to the
+** pseudo-stateless enumerator. The enumeration objects are sharable
+** only in serial fashion.
+*/
+typedef struct PRMWaitEnumerator PRMWaitEnumerator;
+
/*
** FUNCTION: PR_AddWaitFileDesc
@@ -139,7 +160,7 @@ typedef struct PRRecvWait
** to semantically group various file descriptors by the
** client's application.
** desc A reference to a valid PRRecvWait. The object of the
-** reference must be preserved and treated as read-only
+** reference must be preserved and not be modified
** until its ownership is returned to the client.
** RETURN
** PRStatus An indication of success. If equal to PR_FAILUE details
@@ -295,12 +316,76 @@ PR_EXTERN(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size);
**
** ERRORS
** PR_INVALID_ARGUMENT_ERROR
- The 'group' argument does not reference a known object.
+** The 'group' argument does not reference a known object.
** PR_INVALID_STATE_ERROR
** The group still contains receive wait objects.
*/
PR_EXTERN(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group);
+/*
+** FUNCTION: PR_CreateMWaitEnumerator
+** DESCRIPTION:
+** The PR_CreateMWaitEnumerator() function returns a reference to an
+** opaque PRMWaitEnumerator object. The enumerator object is required
+** as an argument for each successive call in the stateless enumeration
+** of the indicated wait group.
+**
+** group The wait group that the enumeration is intended to
+** process. It may be be the default wait group (NULL).
+** RETURN
+** PRMWaitEnumerator* group
+** A reference to an object that will be used to store
+** intermediate state of enumerations.
+** ERRORS
+** Errors are indicated by the function returning a NULL.
+** PR_INVALID_ARGUMENT_ERROR
+** The 'group' argument does not reference a known object.
+** PR_OUT_OF_MEMORY_ERROR
+*/
+PR_EXTERN(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group);
+
+/*
+** FUNCTION: PR_DestroyMWaitEnumerator
+** DESCRIPTION:
+** Destroys the object created by PR_CreateMWaitEnumerator(). The reference
+** used as an argument becomes invalid.
+**
+** INPUT
+** PRMWaitEnumerator* enumerator
+** The PRMWaitEnumerator object to destroy.
+** RETURN
+** PRStatus
+** PR_SUCCESS if successful, PR_FAILURE otherwise.
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** The enumerator is invalid.
+*/
+PR_EXTERN(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator);
+
+/*
+** FUNCTION: PR_EnumerateWaitGroup
+** DESCRIPTION:
+** PR_EnumerateWaitGroup is a thread safe enumerator over a wait group.
+** Each call to the enumerator must present a valid PRMWaitEnumerator
+** rererence and a pointer to the "previous" element returned from the
+** enumeration process or a NULL.
+**
+** An enumeration is started by passing a NULL as the "previous" value.
+** Subsequent calls to the enumerator must pass in the result of the
+** previous call. The enumeration end is signaled by the runtime returning
+** a NULL as the result.
+**
+** Modifications to the content of the wait group are allowed during
+** an enumeration. The effect is that the enumeration may have to be
+** "reset" and that may result in duplicates being returned from the
+** enumeration.
+**
+** An enumeration may be abandoned at any time. The runtime is not
+** keeping any state, so there are no issues in that regard.
+*/
+PR_EXTERN(PRRecvWait*) PR_EnumerateWaitGroup(
+ PRMWaitEnumerator *enumerator, const PRRecvWait *previous);
+
PR_END_EXTERN_C
#endif /* defined(_PRMWAIT_H) */
diff --git a/pr/include/prolock.h b/pr/include/prolock.h
new file mode 100644
index 00000000..b9dcd9f9
--- /dev/null
+++ b/pr/include/prolock.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef prolock_h___
+#define prolock_h___
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+
+/*
+** A locking mechanism, built on the existing PRLock definiion,
+** is provided that will permit applications to define a Lock
+** Hierarchy (or Lock Ordering) schema. An application designed
+** using the Ordered Lock functions will terminate with a
+** diagnostic message when a lock inversion condition is
+** detected.
+**
+** The lock ordering detection is complile-time enabled only. in
+** optimized builds of NSPR, the Ordered Lock functions map
+** directly to PRLock functions, providing no lock order
+** detection.
+**
+** The Ordered Lock Facility is compiled in when DEBUG is defined at
+** compile time. Ordered Lock can be forced on in optimized builds by
+** defining FORCE_NSPR_ORDERED_LOCK at compile time. Both the
+** application using Ordered Lock and NSPR must be compiled with the
+** facility enabled to achieve the desired results.
+**
+** Application designers should use the macro interfaces to the Ordered
+** Lock facility to ensure that it is compiled out in optimized builds.
+**
+** Application designers are responsible for defining their own
+** lock hierarchy.
+**
+** Ordered Lock is thread-safe and SMP safe.
+**
+** See Also: prlock.h
+**
+** /lth. 10-Jun-1998.
+**
+*/
+
+/*
+** Opaque type for ordered lock.
+** ... Don't even think of looking in here.
+**
+*/
+
+typedef void * PROrderedLock;
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateOrderedLock() -- Create an Ordered Lock
+**
+** DESCRIPTION: PR_CreateOrderedLock() creates an ordered lock.
+**
+** INPUTS:
+** order: user defined order of this lock.
+** name: name of the lock. For debugging purposes.
+**
+** OUTPUTS: returned
+**
+** RETURNS: PR_OrderedLock pointer
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_CREATE_ORDERED_LOCK(order,name)\
+ PR_CreateOrderedLock((order),(name))
+
+PR_EXTERN(PROrderedLock *)
+ PR_CreateOrderedLock(
+ PRInt32 order,
+ const char *name
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyOrderedLock() -- Destroy an Ordered Lock
+**
+** DESCRIPTION: PR_DestroyOrderedLock() destroys the ordered lock
+** referenced by lock.
+**
+** INPUTS: lock: pointer to a PROrderedLock
+**
+** OUTPUTS: the lock is destroyed
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyOrderedLock((lock))
+
+PR_EXTERN(void)
+ PR_DestroyOrderedLock(
+ PROrderedLock *lock
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_LockOrderedLock() -- Lock an ordered lock
+**
+** DESCRIPTION: PR_LockOrderedLock() locks the ordered lock
+** referenced by lock. If the order of lock is less than or equal
+** to the order of the highest lock held by the locking thread,
+** the function asserts.
+**
+** INPUTS: lock: a pointer to a PROrderedLock
+**
+** OUTPUTS: The lock is held or the fucntion asserts.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_LOCK_ORDERED_LOCK(lock) PR_LockOrderedLock((lock))
+
+PR_EXTERN(void)
+ PR_LockOrderedLock(
+ PROrderedLock *lock
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_UnlockOrderedLock() -- unlock and Ordered Lock
+**
+** DESCRIPTION: PR_UnlockOrderedLock() unlocks the lock referenced
+** by lock.
+**
+** INPUTS: lock: a pointer to a PROrderedLock
+**
+** OUTPUTS: the lock is unlocked
+**
+** RETURNS:
+** PR_SUCCESS
+** PR_FAILURE
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_UNLOCK_ORDERED_LOCK(lock) PR_UnlockOrderedLock((lock))
+
+PR_EXTERN(PRStatus)
+ PR_UnlockOrderedLock(
+ PROrderedLock *lock
+);
+
+#else /* !(defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)) */
+/*
+** Map PROrderedLock and methods onto PRLock when ordered locking
+** is not compiled in.
+**
+*/
+#include <prlock.h>
+
+typedef PRLock PROrderedLock;
+
+#define PR_CREATE_ORDERED_LOCK(order) PR_NewLock()
+#define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyLock((lock))
+#define PR_LOCK_ORDERED_LOCK(lock) PR_Lock((lock))
+#define PR_UNLOCK_ORDERED_LOCK(lock) PR_Unlock((lock))
+
+#endif /* !(defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)) */
+
+PR_END_EXTERN_C
+
+#endif /* prolock_h___ */
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pr/include/prpdce.h b/pr/include/prpdce.h
index 32a5cf58..b0bc7853 100644
--- a/pr/include/prpdce.h
+++ b/pr/include/prpdce.h
@@ -31,6 +31,8 @@
#include "prtypes.h"
#include "prinrval.h"
+PR_BEGIN_EXTERN_C
+
#define _PR_NAKED_CV_LOCK (PRLock*)0xdce1dce1
/*
@@ -92,4 +94,6 @@ PR_EXTERN(PRStatus) PRP_NakedNotify(PRCondVar *cvar);
*/
PR_EXTERN(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar);
+PR_END_EXTERN_C
+
#endif /* PRPDCE_H */
diff --git a/pr/include/prtrace.h b/pr/include/prtrace.h
new file mode 100644
index 00000000..807d4e45
--- /dev/null
+++ b/pr/include/prtrace.h
@@ -0,0 +1,635 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#ifndef prtrace_h___
+#define prtrace_h___
+/*
+** prtrace.h -- NSPR's Trace Facility.
+**
+** The Trace Facility provides a means to trace application
+** program events within a process. When implementing an
+** application program an engineer may insert a "Trace" function
+** call, passing arguments to be traced. The "Trace" function
+** combines the user trace data with identifying data and
+** writes this data in time ordered sequence into a circular
+** in-memory buffer; when the buffer fills, it wraps.
+**
+** Functions are provided to set and/or re-configure the size of
+** the trace buffer, control what events are recorded in the
+** buffer, enable and disable tracing based on specific user
+** supplied data and other control functions. Methods are provided
+** to record the trace entries in the in-memory trace buffer to
+** a file.
+**
+** Tracing may cause a performance degredation to the application
+** depending on the number and placement of calls to the tracing
+** facility. When tracing is compiled in and all tracing is
+** disabled via the runtime controls, the overhead should be
+** minimal. ... Famous last words, eh?
+**
+** When DEBUG is defined at compile time, the Trace Facility is
+** compiled as part of NSPR and any application using NSPR's
+** header files will have tracing compiled in. When DEBUG is not
+** defined, the Trace Facility is not compiled into NSPR nor
+** exported in its header files. If the Trace Facility is
+** desired in a non-debug build, then FORCE_NSPR_TRACE may be
+** defined at compile time for both the optimized build of NSPR
+** and the application. NSPR and any application using NSPR's
+** Trace Facility must be compiled with the same level of trace
+** conditioning or unresolved references may be realized at link
+** time.
+**
+** For any of the Trace Facility methods that requires a trace
+** handle as an input argument, the caller must ensure that the
+** trace handle argument is valid. An invalid trace handle
+** argument may cause unpredictable results.
+**
+** Trace Facility methods are thread-safe and SMP safe.
+**
+** Users of the Trace Facility should use the defined macros to
+** invoke trace methods, not the function calls directly. e.g.
+** PR_TRACE( h1,0,1,2, ...); not PR_Trace(h1,0,1,2, ...);
+**
+** Application designers should be aware of the effects of
+** debug and optimized build differences when using result of the
+** Trace Facility macros in expressions.
+**
+** See Also: prcountr.h
+**
+** /lth. 08-Jun-1998.
+*/
+
+#include "prtypes.h"
+#include "prthread.h"
+#include "prtime.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Opaque type for the trace handle
+** ... Don't even think about looking in here.
+**
+*/
+typedef void * PRTraceHandle;
+
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+/*
+** PRTraceEntry -- A trace entry in the in-memory trace buffer
+** looks like this.
+**
+*/
+typedef struct PRTraceEntry
+{
+ PRThread *thread; /* The thread creating the trace entry */
+ PRTraceHandle handle; /* PRTraceHandle creating the trace entry */
+ PRTime time; /* Value of PR_Now() at time of trace entry */
+ PRUint32 userData[8]; /* user supplied trace data */
+} PRTraceEntry;
+
+/*
+** PRTraceOption -- command operands to
+** PR_[Set|Get]TraceOption(). See descriptive meanings there.
+**
+*/
+typedef enum PRTraceOption
+{
+ PRTraceBufSize,
+ PRTraceEnable,
+ PRTraceDisable,
+ PRTraceSuspend,
+ PRTraceResume,
+ PRTraceSuspendRecording,
+ PRTraceResumeRecording,
+ PRTraceLockHandles,
+ PRTraceUnLockHandles,
+ PRTraceStopRecording
+} PRTraceOption;
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DEFINE_TRACE() -- Define a PRTraceHandle
+**
+** DESCRIPTION: PR_DEFINE_TRACE() is used to define a trace
+** handle.
+**
+*/
+#define PR_DEFINE_TRACE(name) PRTraceHandle name
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_INIT_TRACE_HANDLE() -- Set the value of a PRTraceHandle
+**
+** DESCRIPTION:
+** PR_INIT_TRACE_HANDLE() sets the value of a PRTraceHandle
+** to value. e.g. PR_INIT_TRACE_HANDLE( myHandle, NULL );
+**
+*/
+#define PR_INIT_TRACE_HANDLE(handle,value)\
+ (handle) = (PRCounterHandle)(value)
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateTrace() -- Create a trace handle
+**
+** DESCRIPTION:
+** PR_CreateTrace() creates a new trace handle. Tracing is
+** enabled for this handle when it is created. The trace handle
+** is intended for use in other Trace Facility calls.
+**
+** PR_CreateTrace() registers the QName, RName and description
+** data so that this data can be retrieved later.
+**
+** INPUTS:
+** qName: pointer to string. QName for this trace handle.
+**
+** rName: pointer to string. RName for this trace handle.
+**
+** description: pointer to string. Descriptive data about this
+** trace handle.
+**
+** OUTPUTS:
+** Creates the trace handle.
+** Registers the QName and RName with the trace facility.
+**
+** RETURNS:
+** PRTraceHandle
+**
+** RESTRICTIONS:
+** qName is limited to 31 characters.
+** rName is limited to 31 characters.
+** description is limited to 255 characters.
+**
+*/
+#define PRTRACE_NAME_MAX 31
+#define PRTRACE_DESC_MAX 255
+
+#define PR_CREATE_TRACE(handle,qName,rName,description)\
+ (handle) = PR_CreateTrace((qName),(rName),(description))
+
+PR_EXTERN(PRTraceHandle)
+ PR_CreateTrace(
+ const char *qName, /* QName for this trace handle */
+ const char *rName, /* RName for this trace handle */
+ const char *description /* description for this trace handle */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyTrace() -- Destroy a trace handle
+**
+** DESCRIPTION:
+** PR_DestroyTrace() removes the referenced trace handle and
+** associated QName, RName and description data from the Trace
+** Facility.
+**
+** INPUTS: handle. A PRTraceHandle
+**
+** OUTPUTS:
+** The trace handle is unregistered.
+** The QName, RName and description are removed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_DESTROY_TRACE(handle)\
+ PR_DestroyTrace((handle))
+
+PR_EXTERN(void)
+ PR_DestroyTrace(
+ PRTraceHandle handle /* Handle to be destroyed */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_Trace() -- Make a trace entry in the in-memory trace
+**
+** DESCRIPTION:
+** PR_Trace() makes an entry in the in-memory trace buffer for
+** the referenced trace handle. The next logically available
+** PRTraceEntry is used; when the next trace entry would overflow
+** the trace table, the table wraps.
+**
+** PR_Trace() for a specific trace handle may be disabled by
+** calling PR_SetTraceOption() specifying PRTraceDisable for the
+** trace handle to be disabled.
+**
+** INPUTS:
+** handle: PRTraceHandle. The trace handle for this trace.
+**
+** userData[0..7]: unsigned 32bit integers. user supplied data
+** that is copied into the PRTraceEntry
+**
+** OUTPUTS:
+** A PRTraceEntry is (conditionally) formatted in the in-memory
+** trace buffer.
+**
+** RETURNS: void.
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)\
+ PR_Trace((handle),(ud0),(ud1),(ud2),(ud3),(ud4),(ud5),(ud6),(ud7))
+
+PR_EXTERN(void)
+ PR_Trace(
+ PRTraceHandle handle, /* use this trace handle */
+ PRUint32 userData0, /* User supplied data word 0 */
+ PRUint32 userData1, /* User supplied data word 1 */
+ PRUint32 userData2, /* User supplied data word 2 */
+ PRUint32 userData3, /* User supplied data word 3 */
+ PRUint32 userData4, /* User supplied data word 4 */
+ PRUint32 userData5, /* User supplied data word 5 */
+ PRUint32 userData6, /* User supplied data word 6 */
+ PRUint32 userData7 /* User supplied data word 7 */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SetTraceOption() -- Control the Trace Facility
+**
+** DESCRIPTION:
+** PR_SetTraceOption() controls the Trace Facility. Depending on
+** command and value, attributes of the Trace Facility may be
+** changed.
+**
+** INPUTS:
+** command: An enumerated value in the set of PRTraceOption.
+** value: pointer to the data to be set. Type of the data is
+** dependent on command; for each value of command, the type
+** and meaning of dereferenced value is shown.
+**
+** PRTraceBufSize: unsigned long: the size of the trace buffer,
+** in bytes.
+**
+** PRTraceEnable: PRTraceHandle. The trace handle to be
+** enabled.
+**
+** PRTraceDisable: PRTraceHandle. The trace handle to be
+** disabled.
+**
+** PRTraceSuspend: void. value must be NULL. All tracing is
+** suspended.
+**
+** PRTraceResume: void. value must be NULL. Tracing for all
+** previously enabled, prior to a PRTraceSuspend, is resumed.
+**
+** PRTraceStopRecording: void. value must be NULL. If recording
+** (see: ** PR_RecordTraceEntries()) is being done,
+** PRTraceStopRecording causes PR_RecordTraceEntries() to return
+** to its caller. If recording is not being done, this function
+** has no effect.
+**
+** PRTraceSuspendRecording: void. Must be NULL. If recording is
+** being done, PRTraceSuspendRecording causes further writes to
+** the trace file to be suspended. Data in the in-memory
+** trace buffer that would ordinarily be written to the
+** trace file will not be written. Trace entries will continue
+** to be entered in the in-memory buffer. If the Trace Facility
+** recording is already in a suspended state, the call has no
+** effect.
+**
+** PRTraceResumeRecording: void. value must be NULL. If
+** recording for the Trace Facility has been previously been
+** suspended, this causes recording to resume. Recording resumes
+** with the next in-memory buffer segment that would be written
+** if trace recording had not been suspended. If recording is
+** not currently suspended, the call has no effect.
+**
+** PRTraceLockHandles: void. value must be NULL. Locks the
+** trace handle lock. While the trace handle lock is held,
+** calls to PR_CreateTrace() will block until the lock is
+** released.
+**
+** PRTraceUnlockHandles: void. value must be NULL. Unlocks the
+** trace handle lock.
+**
+** OUTPUTS:
+** The operation of the Trace Facility may be changed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_SET_TRACE_OPTION(command,value)\
+ PR_SetTraceOption((command),(value))
+
+PR_EXTERN(void)
+ PR_SetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceOption() -- Retrieve settings from the Trace Facility
+**
+** DESCRIPTION:
+** PR_GetTraceOption() retrieves the current setting of the
+** Trace Facility control depending on command.
+**
+**
+** PRTraceBufSize: unsigned long: the size of the trace buffer,
+** in bytes.
+**
+**
+** INPUTS:
+** command: one of the enumerated values in PRTraceOptions
+** valid for PR_GetTraceOption().
+**
+** OUTPUTS:
+** dependent on command.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_TRACE_OPTION(command,value)\
+ PR_GetTraceOption((command),(value))
+
+PR_EXTERN(void)
+ PR_GetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceHandleFromName() -- Retrieve an existing
+** handle by name.
+**
+** DESCRIPTION:
+** PR_GetTraceHandleFromName() retreives an existing tracehandle
+** using the name specified by qName and rName.
+**
+** INPUTS:
+** qName: pointer to string. QName for this trace handle.
+**
+** rName: pointer to string. RName for this trace handle.
+**
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle associated with qName and rName or NULL when
+** there is no match.
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)\
+ (handle) = PR_GetTraceHandleFromName((qName),(rName))
+
+PR_EXTERN(PRTraceHandle)
+ PR_GetTraceHandleFromName(
+ const char *qName, /* QName search argument */
+ const char *rName /* RName search argument */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceNameFromHandle() -- Retreive trace name
+** by bandle.
+**
+** DESCRIPTION:
+** PR_GetTraceNameFromHandle() retreives the existing qName,
+** rName, and description for the referenced trace handle.
+**
+** INPUTS: handle: PRTraceHandle.
+**
+** OUTPUTS: pointers to the Trace Facility's copy of qName,
+** rName and description. ... Don't mess with these values.
+** They're mine.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)\
+ PR_GetTraceNameFromHandle((handle),(qName),(rName),(description))
+
+PR_EXTERN(void)
+ PR_GetTraceNameFromHandle(
+ PRTraceHandle handle, /* handle as search argument */
+ const char **qName, /* pointer to associated QName */
+ const char **rName, /* pointer to associated RName */
+ const char **description /* pointer to associated description */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextTraceQname() -- Retrieive a QName handle
+** iterator.
+**
+** DESCRIPTION:
+** PR_FindNextTraceQname() retreives the first or next trace
+** QName handle, depending on the value of handle, from the trace
+** database. The PRTraceHandle returned can be used as an
+** iterator to traverse the QName handles in the Trace database.
+**
+** INPUTS:
+** handle: When NULL, PR_FindNextQname() returns the first QName
+** handle. When a handle is a valid PRTraceHandle previously
+** retreived using PR_FindNextQname() the next QName handle is
+** retreived.
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle or NULL when there are no trace handles.
+**
+** RESTRICTIONS:
+** Iterating thru the trace handles via FindFirst/FindNext
+** should be done under protection of the trace handle lock.
+** See: PR_SetTraceOption( PRLockTraceHandles ).
+**
+*/
+#define PR_FIND_NEXT_TRACE_QNAME(next,handle)\
+ (next) = PR_FindNextTraceQname((handle))
+
+PR_EXTERN(PRTraceHandle)
+ PR_FindNextTraceQname(
+ PRTraceHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextTraceRname() -- Retrieive an RName handle
+** iterator.
+**
+** DESCRIPTION:
+** PR_FindNextTraceRname() retreives the first or next trace
+** RName handle, depending on the value of handle, from the trace
+** database. The PRTraceHandle returned can be used as an
+** iterator to traverse the RName handles in the Trace database.
+**
+** INPUTS:
+** rhandle: When NULL, PR_FindNextRname() returns the first
+** RName handle. When a handle is a valid PRTraceHandle
+** previously retreived using PR_FindNextRname() the next RName
+** handle is retreived.
+** qhandle: A valid PRTraceHandle retruned from a previous call
+** to PR_FIND_NEXT_TRACE_QNAME().
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle or NULL when there are no trace handles.
+**
+** RESTRICTIONS:
+** Iterating thru the trace handles via FindNext should be done
+** under protection of the trace handle lock. See: (
+** PR_SetTraceOption( PRLockTraceHandles ).
+**
+*/
+#define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)\
+ (next) = PR_FindNextTraceRname((rhandle),(qhandle))
+
+PR_EXTERN(PRTraceHandle)
+ PR_FindNextTraceRname(
+ PRTraceHandle rhandle,
+ PRTraceHandle qhandle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_RecordTraceEntries() -- Write trace entries to external media
+**
+** DESCRIPTION:
+** PR_RecordTraceEntries() causes entries in the in-memory trace
+** buffer to be written to external media.
+**
+** When PR_RecordTraceEntries() is called from an application
+** thread, the function appears to block until another thread
+** calls PR_SetTraceOption() with the PRTraceStopRecording
+** option. This suggests that PR_RecordTraceEntries() should be
+** called from a user supplied thread whose only job is to
+** record trace entries.
+**
+** The environment variable NSPR_TRACE_LOG controls the operation
+** of this function. When NSPR_TRACE_LOG is not defined in the
+** environment, no recording of trace entries occurs. When
+** NSPR_TRACE_LOG is defined, the value of its definition must be
+** the filename of the file to receive the trace entry buffer.
+**
+** PR_RecordTraceEntries() attempts to record the in-memory
+** buffer to a file, subject to the setting of the environment
+** variable NSPR_TRACE_LOG. It is possible because of system
+** load, the thread priority of the recording thread, number of
+** active trace records being written over time, and other
+** variables that some trace records can be lost. ... In other
+** words: don't bet the farm on getting everything.
+**
+** INPUTS: none
+**
+** OUTPUTS: none
+**
+** RETURNS: PR_STATUS
+** PR_SUCCESS no errors were found.
+** PR_FAILURE errors were found.
+**
+** RESTRICTIONS:
+** Only one thread can call PR_RecordTraceEntries() within a
+** process.
+**
+** On error, PR_RecordTraceEntries() may return prematurely.
+**
+*/
+#define PR_RECORD_TRACE_ENTRIES()\
+ PR_RecordTraceEntries()
+
+PR_EXTERN(void)
+ PR_RecordTraceEntries(
+ void
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceEntries() -- Retreive trace entries from
+** the Trace Facility
+**
+** DESCRIPTION:
+** PR_GetTraceEntries() retreives trace entries from the Trace
+** Facility. Up to count trace entries are copied from the Trace
+** Facility into buffer. Only those trace entries that have not
+** been copied via a previous call to PR_GetTraceEntries() are
+** copied. The actual number copied is placed in the PRInt32
+** variable pointed to by found.
+**
+** If more than count trace entries have entered the Trace
+** Facility since the last call to PR_GetTraceEntries()
+** a lost data condition is returned. In this case, the most
+** recent count trace entries are copied into buffer and found is
+** set to count.
+**
+** INPUTS:
+** count. The number of trace entries to be copied into buffer.
+**
+**
+** OUTPUTS:
+** buffer. An array of PRTraceEntries. The buffer is supplied
+** by the caller.
+**
+** found: 32bit signed integer. The number of PRTraceEntries
+** actually copied. found is always less than or equal to count.
+**
+** RETURNS:
+** zero when there is no lost data.
+** non-zero when some PRTraceEntries have been lost.
+**
+** RESTRICTIONS:
+** This is a real performance pig. The copy out operation is bad
+** enough, but depending on then frequency of calls to the
+** function, serious performance impact to the operating
+** application may be realized. ... YMMV.
+**
+*/
+#define PR_GET_TRACE_ENTRIES(buffer,count,found)\
+ PR_GetTraceEntries((buffer),(count),(found))
+
+
+PR_EXTERN(PRIntn)
+ PR_GetTraceEntries(
+ PRTraceEntry *buffer, /* where to write output */
+ PRInt32 count, /* number to get */
+ PRInt32 *found /* number you got */
+);
+
+#else /* !(defined (DEBUG) || defined (FORCE_NSPR_TRACE)) */
+/*
+** Define the Trace Facility macros as No-Ops for when the trace
+** facility is to be compiled-out of the application.
+**
+*/
+#define PR_DEFINE_TRACE(name) PRTraceHandle name
+#define PR_INIT_TRACE_HANDLE(handle,value)
+#define PR_CREATE_TRACE(handle,qName,rName,description)
+#define PR_DESTROY_TRACE(handle)
+#define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)
+#define PR_SET_TRACE_OPTION(command,value)
+#define PR_GET_TRACE_OPTION(command,value)
+#define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)
+#define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)
+#define PR_FIND_NEXT_TRACE_QNAME(next,handle)
+#define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)
+#define PR_GET_TRACE_ENTRIES(buffer,count,found)
+#define PR_RECORD_TRACE_ENTRIES()
+
+#endif /* !(defined (DEBUG) || defined (FORCE_NSPR_TRACE)) */
+
+PR_END_EXTERN_C
+
+#endif /* prtrace_h___ */
+
diff --git a/pr/include/prtypes.h b/pr/include/prtypes.h
index 16112b13..8e10743c 100644
--- a/pr/include/prtypes.h
+++ b/pr/include/prtypes.h
@@ -120,10 +120,6 @@
#endif
-#if !defined(NO_NSPR_10_SUPPORT)
-#define PR_PUBLIC_API PR_IMPLEMENT
-#endif
-
/***********************************************************************
** MACROS: PR_BEGIN_MACRO
** PR_END_MACRO
@@ -179,7 +175,21 @@ PR_BEGIN_EXTERN_C
************************************************************************/
#if PR_BYTES_PER_BYTE == 1
typedef unsigned char PRUint8;
+/*
+** Some cfront-based C++ compilers do not like 'signed char' and
+** issue the warning message:
+** warning: "signed" not implemented (ignored)
+** For these compilers, we have to define PRInt8 as plain 'char'.
+** Make sure that plain 'char' is indeed signed under these compilers.
+*/
+#if (defined(HPUX) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus < 199707L) \
+ || (defined(SCO) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus == 1L)
+typedef char PRInt8;
+#else
typedef signed char PRInt8;
+#endif
#else
#error No suitable type for PRInt8/PRUint8
#endif
@@ -333,6 +343,8 @@ typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
** Fundamental NSPR macros, used nearly everywhere.
*/
+#define PR_PUBLIC_API PR_IMPLEMENT
+
/*
** Macro body brackets so that macros with compound statement definitions
** behave syntactically more like functions when called.
diff --git a/pr/include/prvrsion.h b/pr/include/prvrsion.h
new file mode 100755
index 00000000..a8a0bf3c
--- /dev/null
+++ b/pr/include/prvrsion.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+
+/* author: jstewart */
+
+#if defined(_PRVERSION_H)
+#else
+#define _PRVERSION_H
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+/* All components participating in the PR version protocol must expose
+ * a structure and a function. The structure is defined below and named
+ * according to the naming conventions outlined further below. The function
+ * is called libVersionPoint and returns a pointer to this structure.
+ */
+
+/* on NT, always pack the structure the same. */
+#ifdef _WIN32
+#pragma pack(push, 8)
+#endif
+
+typedef struct {
+ /*
+ * The first field defines which version of this structure is in use.
+ * At this time, only version 2 is specified. If this value is not
+ * 2, you must read no further into the structure.
+ */
+ PRInt32 version;
+
+ /* for Version 2, this is the body format. */
+ PRInt64 buildTime; /* 64 bits - usecs since midnight, 1/1/1970 */
+ char * buildTimeString;/* a human readable version of the time */
+
+ PRUint8 vMajor; /* Major version of this component */
+ PRUint8 vMinor; /* Minor version of this component */
+ PRUint8 vPatch; /* Patch level of this component */
+
+ PRBool beta; /* true if this is a beta component */
+ PRBool debug; /* true if this is a debug component */
+ PRBool special; /* true if this component is a special build */
+
+ char * filename; /* The original filename */
+ char * description; /* description of this component */
+ char * security; /* level of security in this component */
+ char * copyright; /* The copyright for this file */
+ char * comment; /* free form field for misc usage */
+ char * specialString; /* the special variant for this build */
+} PRVersionDescription;
+
+/* on NT, restore the previous packing */
+#ifdef _WIN32
+#pragma pack(pop)
+#endif
+
+/*
+ * All components must define an entrypoint named libVersionPoint which
+ * is of type versionEntryPointType.
+ */
+PR_EXTERN(const PRVersionDescription *) libVersionPoint(void);
+
+typedef const PRVersionDescription *(*versionEntryPointType)(void);
+
+/*
+ * Where you declare your libVersionPoint, do it like this:
+ * PR_IMPLEMENT(const PRVersionDescription *) libVersionPoint(void) {
+ * fill it in...
+ * }
+ */
+
+/*
+ * NAMING CONVENTION FOR struct
+ *
+ * all components should also expose a static PRVersionDescription
+ * The name of the struct should be calculated as follows:
+ * Take the value of filename. (If filename is not specified, calculate
+ * a short, unique string.) Convert all non-alphanumeric characters
+ * to '_'. To this, prepend "PRVersionDescription_". Thus for libfoo.so,
+ * the symbol name is "PRVersionDescription_libfoo_so".
+ * so the file should have
+ * PRVersionDescription PRVersionDescription_libfoo_so { fill it in };
+ * on NT, this file should be declspec export.
+ */
+
+PR_END_EXTERN_C
+
+#endif /* defined(_PRVERSION_H) */
+
+/* prvrsion.h */
+
diff --git a/pr/src/Makefile b/pr/src/Makefile
index e479b0f8..e799af79 100644
--- a/pr/src/Makefile
+++ b/pr/src/Makefile
@@ -21,10 +21,10 @@ MOD_DEPTH = ../..
include $(MOD_DEPTH)/config/config.mk
-ifdef USE_PTHREADS
- DIRS = io linking malloc md memory misc pthreads threads
-else
- DIRS = io linking malloc md memory misc threads
+DIRS = io linking malloc md memory misc threads
+
+ifeq ($(USE_PTHREADS), 1)
+ DIRS += pthreads
endif
#
@@ -52,22 +52,22 @@ endif # SunOS
ifeq ($(OS_ARCH), IRIX)
ifeq ($(USE_PTHREADS), 1)
-OS_LIBS += -lpthread
+OS_LIBS = -lpthread
endif
endif
ifeq ($(OS_ARCH),AIX)
ifeq ($(CLASSIC_NSPR),1)
ifeq ($(OS_RELEASE),4.1)
-OS_LIBS += -lsvld -lc
+OS_LIBS = -lsvld -lc
else
-OS_LIBS += -ldl -lc
+OS_LIBS = -ldl -lc
endif
else
ifeq ($(OS_RELEASE),4.1)
-OS_LIBS += -lsvld -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a
+OS_LIBS = -lpthreads -lsvld -lC_r -lC -lc_r -lm /usr/lib/libc.a
else
-OS_LIBS += -ldl -lC_r -lC -lpthreads -lc_r -lm /usr/lib/libc.a
+OS_LIBS = -lpthreads -ldl -lC_r -lC -lc_r -lm /usr/lib/libc.a
endif
endif
endif
@@ -84,11 +84,11 @@ endif
endif
ifeq ($(OS_ARCH),OSF1)
-ifneq ($(OS_RELEASE),V2.0)
-OS_LIBS = -lc_r
-endif
ifeq ($(USE_PTHREADS), 1)
-OS_LIBS += -lpthread -lrt
+OS_LIBS = -lpthread -lrt
+endif
+ifneq ($(OS_RELEASE),V2.0)
+OS_LIBS += -lc_r
endif
ifeq ($(USE_IPV6), 1)
OS_LIBS += -lip6
@@ -104,16 +104,20 @@ endif
endif
ifeq ($(OS_ARCH),HP-UX)
-ifeq ($(basename $(OS_RELEASE)),A.09)
-OS_LIBS = -ldld -L/lib/pa1.1 -lm
+ifeq ($(USE_PTHREADS), 1)
+ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
+OS_LIBS = -ldce
else
-OS_LIBS = -ldld -lm -lc
+OS_LIBS = -lpthread
endif
-ifeq ($(USE_PTHREADS), 1)
-OS_LIBS += -lpthread
endif
ifeq ($(PTHREADS_USER), 1)
-OS_LIBS += -lpthread
+OS_LIBS = -lpthread
+endif
+ifeq ($(basename $(OS_RELEASE)),A.09)
+OS_LIBS += -ldld -L/lib/pa1.1 -lm
+else
+OS_LIBS += -ldld -lm -lc
endif
endif
@@ -140,16 +144,20 @@ endif
#
OBJS = \
+ $(OBJDIR)/prvrsion.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prfdcach.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \
io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prpolevt.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prprf.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prscanf.$(OBJ_SUFFIX) \
io/$(OBJDIR)/prstdio.$(OBJ_SUFFIX) \
threads/$(OBJDIR)/prcmon.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prtpd.$(OBJ_SUFFIX) \
linking/$(OBJDIR)/prlink.$(OBJ_SUFFIX) \
malloc/$(OBJDIR)/prmalloc.$(OBJ_SUFFIX) \
malloc/$(OBJDIR)/prmem.$(OBJ_SUFFIX) \
@@ -157,6 +165,7 @@ OBJS = \
memory/$(OBJDIR)/prseg.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/pralarm.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/pratom.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prcountr.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prdtoa.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prenv.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prerror.$(OBJ_SUFFIX) \
@@ -165,8 +174,10 @@ OBJS = \
misc/$(OBJDIR)/prlog2.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prlong.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prnetdb.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prolock.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prsystem.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prthinfo.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prtrace.$(OBJ_SUFFIX) \
misc/$(OBJDIR)/prtime.$(OBJ_SUFFIX)
ifdef USE_PTHREADS
@@ -185,7 +196,6 @@ OBJS += \
threads/$(OBJDIR)/prdump.$(OBJ_SUFFIX) \
threads/$(OBJDIR)/prmon.$(OBJ_SUFFIX) \
threads/$(OBJDIR)/prsem.$(OBJ_SUFFIX) \
- threads/$(OBJDIR)/prtpd.$(OBJ_SUFFIX) \
threads/combined/$(OBJDIR)/prucpu.$(OBJ_SUFFIX) \
threads/combined/$(OBJDIR)/prucv.$(OBJ_SUFFIX) \
threads/combined/$(OBJDIR)/prulock.$(OBJ_SUFFIX) \
@@ -193,6 +203,7 @@ OBJS += \
threads/combined/$(OBJDIR)/pruthr.$(OBJ_SUFFIX)
endif
+
ifeq ($(USE_IPV6), 1)
OBJS += io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX)
endif
@@ -202,6 +213,11 @@ ifneq (,$(filter-out WIN16 OS2,$(OS_TARGET)))
DLLBASE=/BASE:0x30000000
RES=$(OBJDIR)/nspr.res
RESNAME=nspr.rc
+ifdef MOZ_DEBUG
+ifdef GLOWCODE
+EXTRA_LIBS += $(GLOWDIR)/glowcode.lib
+endif
+endif
endif
ifeq ($(OS_TARGET), WIN16)
@@ -238,14 +254,8 @@ OBJS += md/windows/$(OBJDIR)/w95io.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/ntinrval.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/ntsem.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/win32_errors.$(OBJ_SUFFIX) \
- md/windows/$(OBJDIR)/w32poll.$(OBJ_SUFFIX)
-ifeq ($(MOZ_BITS),32)
-ifdef MOZ_DEBUG
-ifdef GLOWCODE
- EXTRA_LIBS += $(GLOWDIR)/glowcode.lib
-endif
-endif
-endif
+ md/windows/$(OBJDIR)/w32poll.$(OBJ_SUFFIX) \
+ md/windows/$(OBJDIR)/w95dllmain.$(OBJ_SUFFIX)
else
ifeq ($(OS_TARGET), OS2)
OBJS += md/os2/$(OBJDIR)/os2io.$(OBJ_SUFFIX) \
@@ -259,7 +269,8 @@ OBJS += md/os2/$(OBJDIR)/os2io.$(OBJ_SUFFIX) \
md/os2/$(OBJDIR)/os2_errors.$(OBJ_SUFFIX) \
md/os2/$(OBJDIR)/os2poll.$(OBJ_SUFFIX)
else
-OBJS += md/windows/$(OBJDIR)/ntio.$(OBJ_SUFFIX) \
+OBJS += md/windows/$(OBJDIR)/ntdllmn.$(OBJ_SUFFIX) \
+ md/windows/$(OBJDIR)/ntio.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/ntgc.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/ntthread.$(OBJ_SUFFIX) \
md/windows/$(OBJDIR)/ntmisc.$(OBJ_SUFFIX) \
@@ -297,13 +308,53 @@ TARGETS += $(AIX_RTL_LIBC)
endif
#
+# Version information generation (begin)
+#
+RM = rm
+ECHO = echo
+INCLUDES = -I$(DIST)/include
+TINC = $(OBJDIR)/_pr_bld.h
+PROD = libnspr$(MOD_VERSION).$(DLL_SUFFIX)
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date)
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(OS_ARCH), WINNT)
+ SUF = i64
+ SH_QUOTE =
+else
+ SUF = LL
+ SH_QUOTE = "
+endif
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) $(SH_QUOTE)#define _BUILD_STRING \"$(SH_DATE)\"$(SH_QUOTE) > $(TINC)
+ @$(ECHO) $(SH_QUOTE)#define _BUILD_TIME $(SH_NOW)$(SUF)$(SH_QUOTE) >> $(TINC)
+ @$(ECHO) $(SH_QUOTE)#define _PRODUCTION \"$(PROD)\"$(SH_QUOTE) >> $(TINC)
+
+
+$(OBJDIR)/prvrsion.$(OBJ_SUFFIX): $(TINC)
+ifeq ($(OS_ARCH), WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) prvrsion.c
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) prvrsion.c
+endif
+#
+# Version information generation (end)
+#
+
+
+#
# The Client build wants the shared libraries in $(DIST)/bin,
# so we also install them there.
#
export:: $(TARGETS)
$(INSTALL) -m 444 $(TARGETS) $(DIST)/lib
+ifdef SHARED_LIBRARY
$(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/bin
+endif
ifeq ($(MOZ_BITS),16)
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
$(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
diff --git a/pr/src/io/Makefile b/pr/src/io/Makefile
index 68dda471..a3574793 100644
--- a/pr/src/io/Makefile
+++ b/pr/src/io/Makefile
@@ -29,12 +29,14 @@ endif
endif
CSRCS = \
+ prfdcach.c \
prmwait.c \
priometh.c \
prmapopt.c \
prlayer.c \
prlog.c \
prmmap.c \
+ prpolevt.c \
prprf.c \
prscanf.c \
prstdio.c \
@@ -45,11 +47,7 @@ ifndef USE_PTHREADS
prdir.c \
prfile.c \
prio.c \
- prlog.c \
- prmmap.c \
- prprf.c \
prsocket.c \
- prstdio.c \
$(NULL)
endif
diff --git a/pr/src/io/prfdcach.c b/pr/src/io/prfdcach.c
new file mode 100644
index 00000000..9c7c8ea7
--- /dev/null
+++ b/pr/src/io/prfdcach.c
@@ -0,0 +1,287 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "primpl.h"
+#include "pratom.h"
+
+#include <string.h>
+
+/*****************************************************************************/
+/*****************************************************************************/
+/************************** File descriptor caching **************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+/*
+** This code is built into debuggable versions of NSPR to assist in
+** finding misused file descriptors. Since file descritors (PRFileDesc)
+** are identified by a pointer to their structure, they can be the
+** target of dangling references. Furthermore, NSPR caches and tries
+** to aggressively reuse file descriptors, leading to more ambiguity.
+** The following code will allow a debugging client to set environment
+** variables and control the number of file descriptors that will be
+** preserved before they are recycled. The environment variables are
+** NSPR_FD_CACHE_SIZE_LOW and NSPR_FD_CACHE_SIZE_HIGH. The former sets
+** the number of descriptors NSPR will allocate before beginning to
+** recycle. The latter is the maximum number permitted in the cache
+** (exclusive of those in use) at a time.
+*/
+typedef struct _PR_Fd_Cache
+{
+ PRLock *ml;
+ PRIntn count;
+ PRStack *stack;
+ PRFileDesc *head, *tail;
+ PRIntn limit_low, limit_high;
+} _PR_Fd_Cache;
+
+static _PR_Fd_Cache _pr_fd_cache;
+static PRFileDesc **stack2fd = &(((PRFileDesc*)NULL)->higher);
+
+
+/*
+** Get a FileDescriptor from the cache if one exists. If not allocate
+** a new one from the heap.
+*/
+PRFileDesc *_PR_Getfd()
+{
+ PRFileDesc *fd;
+ /*
+ ** $$$
+ ** This may look a little wasteful. We'll see. Right now I want to
+ ** be able to toggle between caching and not at runtime to measure
+ ** the differences. If it isn't too annoying, I'll leave it in.
+ ** $$$$
+ **
+ ** The test is against _pr_fd_cache.limit_high. If that's zero,
+ ** we're not doing the extended cache but going for performance.
+ */
+ if (0 == _pr_fd_cache.limit_high)
+ {
+ PRStackElem *pop;
+ PR_ASSERT(NULL != _pr_fd_cache.stack);
+ pop = PR_StackPop(_pr_fd_cache.stack);
+ if (NULL == pop) goto allocate;
+ fd = (PRFileDesc*)((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ }
+ else
+ {
+ do
+ {
+ if (NULL == _pr_fd_cache.head) goto allocate; /* nothing there */
+ if (_pr_fd_cache.count < _pr_fd_cache.limit_low) goto allocate;
+
+ /* we "should" be able to extract an fd from the cache */
+ PR_Lock(_pr_fd_cache.ml); /* need the lock to do this safely */
+ fd = _pr_fd_cache.head; /* protected extraction */
+ if (NULL == fd) /* unexpected, but not fatal */
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ PR_ASSERT(NULL == _pr_fd_cache.tail);
+ }
+ else
+ {
+ _pr_fd_cache.count -= 1;
+ _pr_fd_cache.head = fd->higher;
+ if (NULL == _pr_fd_cache.head)
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ _pr_fd_cache.tail = NULL;
+ }
+ PR_ASSERT(_PR_FILEDESC_FREED == fd->secret->state);
+ }
+ PR_Unlock(_pr_fd_cache.ml);
+
+ } while (NULL == fd); /* then go around and allocate a new one */
+ }
+
+finished:
+ fd->dtor = NULL;
+ fd->lower = fd->higher = NULL;
+ fd->identity = PR_NSPR_IO_LAYER;
+ memset(fd->secret, 0, sizeof(PRFilePrivate));
+ return fd;
+
+allocate:
+ fd = PR_NEW(PRFileDesc);
+ if (NULL != fd)
+ {
+ fd->secret = PR_NEW(PRFilePrivate);
+ if (NULL == fd->secret) PR_DELETE(fd);
+ }
+ if (NULL != fd) goto finished;
+ else return NULL;
+
+} /* _PR_Getfd */
+
+/*
+** Return a file descriptor to the cache unless there are too many in
+** there already. If put in cache, clear the fields first.
+*/
+void _PR_Putfd(PRFileDesc *fd)
+{
+ PR_ASSERT(PR_NSPR_IO_LAYER == fd->identity);
+ fd->methods = &_pr_faulty_methods;
+ fd->identity = PR_INVALID_IO_LAYER;
+ fd->secret->state = _PR_FILEDESC_FREED;
+
+ if (0 == _pr_fd_cache.limit_high)
+ {
+ PR_StackPush(_pr_fd_cache.stack, (PRStackElem*)(&fd->higher));
+ }
+ else
+ {
+ if (_pr_fd_cache.count > _pr_fd_cache.limit_high)
+ {
+ PR_Free(fd->secret);
+ PR_Free(fd);
+ }
+ else
+ {
+ PR_Lock(_pr_fd_cache.ml);
+ if (NULL == _pr_fd_cache.tail)
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ PR_ASSERT(NULL == _pr_fd_cache.head);
+ _pr_fd_cache.head = _pr_fd_cache.tail = fd;
+ }
+ else
+ {
+ PR_ASSERT(NULL == _pr_fd_cache.tail->higher);
+ _pr_fd_cache.tail->higher = fd;
+ _pr_fd_cache.tail = fd; /* new value */
+ }
+ fd->higher = NULL; /* always so */
+ _pr_fd_cache.count += 1; /* count the new entry */
+ PR_Unlock(_pr_fd_cache.ml);
+ }
+ }
+} /* _PR_Putfd */
+
+PR_IMPLEMENT(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high)
+{
+ /*
+ ** This can be called at any time, may adjust the cache sizes,
+ ** turn the caches off, or turn them on. It is not dependent
+ ** on the compilation setting of DEBUG.
+ */
+ if (low > high) low = high; /* sanity check the params */
+
+ PR_Lock(_pr_fd_cache.ml);
+ if (0 == high) /* shutting down or staying down */
+ {
+ if (0 != _pr_fd_cache.limit_high) /* shutting down */
+ {
+ _pr_fd_cache.limit_high = 0; /* stop use */
+ /*
+ ** Hold the lock throughout - nobody's going to want it
+ ** other than another caller to this routine. Just don't
+ ** let that happen.
+ **
+ ** Put all the cached fds onto the new cache.
+ */
+ while (NULL != _pr_fd_cache.head)
+ {
+ PRFileDesc *fd = _pr_fd_cache.head;
+ _pr_fd_cache.head = fd->higher;
+ fd->identity = PR_NSPR_IO_LAYER;
+ _PR_Putfd(fd);
+ }
+ _pr_fd_cache.limit_low = 0;
+ _pr_fd_cache.tail = NULL;
+ _pr_fd_cache.count = 0;
+ }
+ }
+ else /* starting up or just adjusting parameters */
+ {
+ PRBool was_using_cache = (0 != _pr_fd_cache.limit_high);
+ _pr_fd_cache.limit_low = low;
+ _pr_fd_cache.limit_high = high;
+ if (was_using_cache) /* was using stack - feed into cache */
+ {
+ PRStackElem *pop;
+ while (NULL != (pop = PR_StackPop(_pr_fd_cache.stack)))
+ {
+ PRFileDesc *fd = (PRFileDesc*)
+ ((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ fd->identity = PR_NSPR_IO_LAYER;
+ _PR_Putfd(fd);
+ }
+ }
+ }
+ PR_Unlock(_pr_fd_cache.ml);
+ return PR_SUCCESS;
+} /* PR_SetFDCacheSize */
+
+void _PR_InitFdCache()
+{
+ /*
+ ** The fd caching is enabled by default for DEBUG builds,
+ ** disabled by default for OPT builds. That default can
+ ** be overridden at runtime using environment variables
+ ** or a super-wiz-bang API.
+ */
+ const char *low = PR_GetEnv("NSPR_FD_CACHE_SIZE_LOW");
+ const char *high = PR_GetEnv("NSPR_FD_CACHE_SIZE_HIGH");
+
+ _pr_fd_cache.limit_low = _pr_fd_cache.limit_high = 0;
+ if (NULL != low) _pr_fd_cache.limit_low = atoi(low);
+ if (NULL != high) _pr_fd_cache.limit_high = atoi(high);
+
+ /*
+ **_low is allowed to be zero, _high is not.
+ ** IF _high is zero, we're not doing the caching.
+ */
+
+#if defined(DEBUG)
+ if (0 == _pr_fd_cache.limit_high)
+ _pr_fd_cache.limit_high = FD_SETSIZE;
+#endif /* defined(DEBUG) */
+
+ if (_pr_fd_cache.limit_high < _pr_fd_cache.limit_low)
+ _pr_fd_cache.limit_high = _pr_fd_cache.limit_low;
+
+ _pr_fd_cache.ml = PR_NewLock();
+ PR_ASSERT(NULL != _pr_fd_cache.ml);
+ _pr_fd_cache.stack = PR_CreateStack("FD");
+ PR_ASSERT(NULL != _pr_fd_cache.stack);
+
+} /* _PR_InitFdCache */
+
+void _PR_CleanupFdCache(void)
+{
+ PRFileDesc *fd, *next;
+ PRStackElem *pop;
+
+ for (fd = _pr_fd_cache.head; fd != NULL; fd = next)
+ {
+ next = fd->higher;
+ PR_DELETE(fd->secret);
+ PR_DELETE(fd);
+ }
+ PR_DestroyLock(_pr_fd_cache.ml);
+ while ((pop = PR_StackPop(_pr_fd_cache.stack)) != NULL)
+ {
+ fd = (PRFileDesc*)((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ PR_DELETE(fd->secret);
+ PR_DELETE(fd);
+ }
+ PR_DestroyStack(_pr_fd_cache.stack);
+} /* _PR_CleanupFdCache */
+
+/* prfdcach.c */
diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c
index 95210eae..bb9730f1 100644
--- a/pr/src/io/prfile.c
+++ b/pr/src/io/prfile.c
@@ -182,22 +182,21 @@ static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd)
static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd)
{
- PRInt32 rv;
-
- if (!fd || fd->secret->state != _PR_FILEDESC_OPEN) {
+ if (!fd || !fd->secret
+ || (fd->secret->state != _PR_FILEDESC_OPEN
+ && fd->secret->state != _PR_FILEDESC_CLOSED)) {
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
return PR_FAILURE;
}
- fd->secret->state = _PR_FILEDESC_CLOSED;
-
- rv = _PR_MD_CLOSE_FILE(fd->secret->md.osfd);
- PR_FreeFileDesc(fd);
- if (rv < 0) {
- return PR_FAILURE;
- } else {
- return PR_SUCCESS;
+ if (fd->secret->state == _PR_FILEDESC_OPEN) {
+ if (_PR_MD_CLOSE_FILE(fd->secret->md.osfd) < 0) {
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
}
+ PR_FreeFileDesc(fd);
+ return PR_SUCCESS;
}
static PRInt16 PR_CALLBACK FilePoll(
@@ -207,7 +206,7 @@ static PRInt16 PR_CALLBACK FilePoll(
return in_flags;
} /* FilePoll */
-PRIOMethods _pr_fileMethods = {
+static PRIOMethods _pr_fileMethods = {
PR_DESC_FILE,
FileClose,
FileRead,
@@ -357,6 +356,7 @@ PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
{
PRInt32 rv;
+ if (!_pr_initialized) _PR_ImplicitInitialization();
rv = _PR_MD_GETFILEINFO64(fn, info);
if (rv < 0) {
return PR_FAILURE;
diff --git a/pr/src/io/prio.c b/pr/src/io/prio.c
index fc8f005f..97987b92 100644
--- a/pr/src/io/prio.c
+++ b/pr/src/io/prio.c
@@ -25,15 +25,12 @@
PRLock *_pr_flock_lock;
-PRFileDesc *_pr_filedesc_freelist;
-PRLock *_pr_filedesc_freelist_lock;
-
void _PR_InitIO(void)
{
const PRIOMethods *methods = PR_GetFileMethods();
- _pr_filedesc_freelist = NULL;
- _pr_filedesc_freelist_lock = PR_NewLock();
+ _PR_InitFdCache();
+
_pr_flock_lock = PR_NewLock();
#ifdef WIN32
@@ -87,26 +84,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
*/
PR_ASSERT(osfd < FD_SETSIZE);
#endif
- if (_pr_filedesc_freelist) {
- PR_Lock(_pr_filedesc_freelist_lock);
- if (_pr_filedesc_freelist) {
- PRFilePrivate *secretSave;
- fd = _pr_filedesc_freelist;
- _pr_filedesc_freelist = _pr_filedesc_freelist->secret->next;
- PR_Unlock(_pr_filedesc_freelist_lock);
- secretSave = fd->secret;
- memset(fd, 0, sizeof(PRFileDesc));
- memset(secretSave, 0, sizeof(PRFilePrivate));
- fd->secret = secretSave;
- } else {
- PR_Unlock(_pr_filedesc_freelist_lock);
- fd = PR_NEWZAP(PRFileDesc);
- fd->secret = PR_NEWZAP(PRFilePrivate);
- }
- } else {
- fd = PR_NEWZAP(PRFileDesc);
- fd->secret = PR_NEWZAP(PRFilePrivate);
- }
+ fd = _PR_Getfd();
if (fd) {
/* Initialize the members of PRFileDesc and PRFilePrivate */
fd->methods = methods;
@@ -122,64 +100,13 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc *fd)
{
PR_ASSERT(fd);
- PR_ASSERT(fd->secret->state == _PR_FILEDESC_CLOSED);
-
- fd->secret->state = _PR_FILEDESC_FREED;
-
- PR_Lock(_pr_filedesc_freelist_lock);
-
- /* Add to head of list- this is a LIFO structure to avoid constantly
- * using different structs
- */
- fd->secret->next = _pr_filedesc_freelist;
- _pr_filedesc_freelist = fd;
-
- PR_Unlock(_pr_filedesc_freelist_lock);
+ _PR_Putfd(fd);
}
-#ifdef XP_UNIX
-#include <fcntl.h> /* to pick up F_GETFL */
-#endif
-
/*
** Wait for some i/o to finish on one or more more poll descriptors.
*/
-PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds,
- PRIntervalTime timeout)
+PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
- PRPollDesc *pd, *epd;
- PRInt32 ready;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- return -1;
- }
- /*
- ** Before we do the poll operation, check each descriptor and see if
- ** it needs special poll handling. If it does, use the method poll
- ** proc to check for data before blocking.
- */
- pd = pds;
- ready = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRFileDesc *fd = pd->fd;
- PRInt16 in_flags = pd->in_flags;
- if (NULL != fd)
- {
- if (in_flags && fd->methods->poll) {
- PRInt16 out_flags;
- in_flags = (*fd->methods->poll)(fd, in_flags, &out_flags);
- if (0 != (in_flags & out_flags)) {
- pd->out_flags = out_flags; /* ready already */
- ready++;
- }
- }
- }
- }
- if (ready != 0) {
- return ready; /* don't need to block */
- }
return(_PR_MD_PR_POLL(pds, npds, timeout));
}
diff --git a/pr/src/io/priometh.c b/pr/src/io/priometh.c
index a65b5c53..e9e4847c 100644
--- a/pr/src/io/priometh.c
+++ b/pr/src/io/priometh.c
@@ -18,19 +18,61 @@
#include "primpl.h"
-/*
- * An invalid method that returns an integer
- */
+/*****************************************************************************/
+/************************** Invalid I/O method object ************************/
+/*****************************************************************************/
+PRIOMethods _pr_faulty_methods = {
+ (PRDescType)0,
+ (PRCloseFN)_PR_InvalidStatus,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ (PRPollFN)_PR_InvalidInt16,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRGetsockoptFN)_PR_InvalidStatus,
+ (PRSetsockoptFN)_PR_InvalidStatus,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus
+};
PRIntn _PR_InvalidInt()
{
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return -1;
+} /* _PR_InvalidInt */
+
+PRInt16 _PR_InvalidInt16()
+{
+ PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return -1;
} /* _PR_InvalidInt */
PRInt64 _PR_InvalidInt64()
{
- PRInt64 rv = LL_INIT( 0xffffffff, 0xffffffff );
+ PRInt64 rv;
+ LL_I2L(rv, -1);
+ PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return rv;
} /* _PR_InvalidInt */
@@ -41,6 +83,7 @@ PRInt64 _PR_InvalidInt64()
PRStatus _PR_InvalidStatus()
{
+ PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return PR_FAILURE;
} /* _PR_InvalidDesc */
@@ -51,6 +94,7 @@ PRStatus _PR_InvalidStatus()
PRFileDesc *_PR_InvalidDesc()
{
+ PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return NULL;
} /* _PR_InvalidDesc */
diff --git a/pr/src/io/prlayer.c b/pr/src/io/prlayer.c
index 1ca15962..f6e1828f 100644
--- a/pr/src/io/prlayer.c
+++ b/pr/src/io/prlayer.c
@@ -50,6 +50,7 @@ static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd)
PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED);
status = (fd->lower->methods->close)(fd->lower);
+ fd->lower = fd->higher = NULL;
fd->dtor(fd);
return status;
diff --git a/pr/src/io/prlog.c b/pr/src/io/prlog.c
index 98c7e639..723cb699 100644
--- a/pr/src/io/prlog.c
+++ b/pr/src/io/prlog.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
@@ -68,6 +68,14 @@ static PRLock *_pr_logLock;
#define _PR_USE_STDIO_FOR_LOGGING
#endif
+/*
+** Coerce Win32 log output to use OutputDebugString() when
+** NSPR_LOG_FILE is set to "WinDebug".
+*/
+#if defined(XP_PC)
+#define WIN32_DEBUG_FILE (FILE*)-2
+#endif
+
/* Macros used to reduce #ifdef pollution */
#if defined(_PR_USE_STDIO_FOR_LOGGING)
@@ -279,7 +287,7 @@ static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
lm->level = (PRLogModuleLevel)level;
else if (strcasecmp(module, lm->name) == 0)
{
- lm->level = level;
+ lm->level = (PRLogModuleLevel)level;
break;
}
lm = lm->next;
@@ -310,33 +318,19 @@ PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name)
return lm;
}
-PR_IMPLEMENT(void) PR_DestroyLogModule(PRLogModuleInfo* lm)
-{
- PR_LogFlush();
-
- /* unlink this log module from the list */
- if (lm == logModules) {
- logModules = logModules->next;
- }
- else {
- PRLogModuleInfo* chain = logModules;
- while (chain && chain->next != lm)
- chain = chain->next;
- PR_ASSERT(chain && chain->next);
- chain->next = chain->next->next;
- }
-
- /* and free it */
- free((void*)lm->name);
- PR_Free(lm);
-}
-
PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
{
#ifdef PR_LOGGING
#ifdef _PR_USE_STDIO_FOR_LOGGING
FILE *newLogFile;
+#ifdef XP_PC
+ if ( strcmp( file, "WinDebug") == 0)
+ {
+ logFile = WIN32_DEBUG_FILE;
+ return(PR_TRUE);
+ }
+#endif
newLogFile = fopen(file, "w");
if (newLogFile) {
/* We do buffering ourselves. */
@@ -427,7 +421,14 @@ PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
_PR_LOCK_LOG();
if (logBuf == 0) {
+#ifdef XP_PC
+ if ( logFile == WIN32_DEBUG_FILE)
+ OutputDebugString( line );
+ else
+ _PUT_LOG(logFile, line, nb);
+#else
_PUT_LOG(logFile, line, nb);
+#endif
} else {
if (logp + nb > logEndp) {
_PUT_LOG(logFile, logBuf, logp - logBuf);
diff --git a/pr/src/io/prmwait.c b/pr/src/io/prmwait.c
index c29628ea..5f6e9a72 100644
--- a/pr/src/io/prmwait.c
+++ b/pr/src/io/prmwait.c
@@ -16,48 +16,216 @@
* Reserved.
*/
-#include "prlog.h"
-#include "prmem.h"
#include "primpl.h"
-#include "prmwait.h"
-#include "prerror.h"
#include "pprmwait.h"
+#define _MW_REHASH_MAX 11
+
static PRLock *mw_lock = NULL;
static _PRGlobalState *mw_state = NULL;
static PRIntervalTime max_polling_interval;
-/******************************************************************/
-/******************************************************************/
-/************************ The private portion *********************/
-/******************************************************************/
-/******************************************************************/
-static PRStatus MW_Init(void)
+#ifdef WINNT
+
+typedef struct TimerEvent {
+ PRIntervalTime absolute;
+ void (*func)(void *);
+ void *arg;
+ LONG ref_count;
+ PRCList links;
+} TimerEvent;
+
+#define TIMER_EVENT_PTR(_qp) \
+ ((TimerEvent *) ((char *) (_qp) - offsetof(TimerEvent, links)))
+
+struct {
+ PRLock *ml;
+ PRCondVar *new_timer;
+ PRCondVar *cancel_timer;
+ PRThread *manager_thread;
+ PRCList timer_queue;
+} tm_vars;
+
+static PRStatus TimerInit(void);
+static void TimerManager(void *arg);
+static TimerEvent *CreateTimer(PRIntervalTime timeout,
+ void (*func)(void *), void *arg);
+static PRBool CancelTimer(TimerEvent *timer);
+
+static void TimerManager(void *arg)
{
- if (NULL != mw_lock) return PR_SUCCESS;
- if (NULL != (mw_lock = PR_NewLock()))
+ PRIntervalTime now;
+ PRIntervalTime timeout;
+ PRCList *head;
+ TimerEvent *timer;
+
+ PR_Lock(tm_vars.ml);
+ while (1)
{
- _PRGlobalState *state = PR_NEWZAP(_PRGlobalState);
- if (state == NULL) goto failed;
+ if (PR_CLIST_IS_EMPTY(&tm_vars.timer_queue))
+ {
+ PR_WaitCondVar(tm_vars.new_timer, PR_INTERVAL_NO_TIMEOUT);
+ }
+ else
+ {
+ now = PR_IntervalNow();
+ head = PR_LIST_HEAD(&tm_vars.timer_queue);
+ timer = TIMER_EVENT_PTR(head);
+ if ((PRInt32) (now - timer->absolute) >= 0)
+ {
+ PR_REMOVE_LINK(head);
+ /*
+ * make its prev and next point to itself so that
+ * it's obvious that it's not on the timer_queue.
+ */
+ PR_INIT_CLIST(head);
+ PR_ASSERT(2 == timer->ref_count);
+ PR_Unlock(tm_vars.ml);
+ timer->func(timer->arg);
+ PR_Lock(tm_vars.ml);
+ timer->ref_count -= 1;
+ if (0 == timer->ref_count)
+ {
+ PR_NotifyAllCondVar(tm_vars.cancel_timer);
+ }
+ }
+ else
+ {
+ timeout = (PRIntervalTime)(timer->absolute - now);
+ PR_WaitCondVar(tm_vars.new_timer, timeout);
+ }
+ }
+ }
+ PR_Unlock(tm_vars.ml);
+}
- PR_INIT_CLIST(&state->group_list);
+static TimerEvent *CreateTimer(
+ PRIntervalTime timeout,
+ void (*func)(void *),
+ void *arg)
+{
+ TimerEvent *timer;
+ PRCList *links, *tail;
+ TimerEvent *elem;
- PR_Lock(mw_lock);
- if (NULL == mw_state) /* is it still NULL? */
+ timer = PR_NEW(TimerEvent);
+ if (NULL == timer)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return timer;
+ }
+ timer->absolute = PR_IntervalNow() + timeout;
+ timer->func = func;
+ timer->arg = arg;
+ timer->ref_count = 2;
+ PR_Lock(tm_vars.ml);
+ tail = links = PR_LIST_TAIL(&tm_vars.timer_queue);
+ while (links->prev != tail)
+ {
+ elem = TIMER_EVENT_PTR(links);
+ if ((PRInt32)(timer->absolute - elem->absolute) >= 0)
{
- mw_state = state; /* if yes, set our value */
- state = NULL; /* and indicate we've done the job */
- max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL);
+ break;
}
- PR_Unlock(mw_lock);
- if (NULL != state) PR_DELETE(state);
- return PR_SUCCESS;
+ links = links->prev;
}
+ PR_INSERT_AFTER(&timer->links, links);
+ PR_NotifyCondVar(tm_vars.new_timer);
+ PR_Unlock(tm_vars.ml);
+ return timer;
+}
+
+static PRBool CancelTimer(TimerEvent *timer)
+{
+ PRBool canceled = PR_FALSE;
+
+ PR_Lock(tm_vars.ml);
+ timer->ref_count -= 1;
+ if (timer->links.prev == &timer->links)
+ {
+ while (timer->ref_count == 1)
+ {
+ PR_WaitCondVar(tm_vars.cancel_timer, PR_INTERVAL_NO_TIMEOUT);
+ }
+ }
+ else
+ {
+ PR_REMOVE_LINK(&timer->links);
+ canceled = PR_TRUE;
+ }
+ PR_Unlock(tm_vars.ml);
+ PR_DELETE(timer);
+ return canceled;
+}
+
+static PRStatus TimerInit(void)
+{
+ tm_vars.ml = PR_NewLock();
+ if (NULL == tm_vars.ml)
+ {
+ goto failed;
+ }
+ tm_vars.new_timer = PR_NewCondVar(tm_vars.ml);
+ if (NULL == tm_vars.new_timer)
+ {
+ goto failed;
+ }
+ tm_vars.cancel_timer = PR_NewCondVar(tm_vars.ml);
+ if (NULL == tm_vars.cancel_timer)
+ {
+ goto failed;
+ }
+ tm_vars.manager_thread = PR_CreateThread(
+ PR_SYSTEM_THREAD, TimerManager, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ if (NULL == tm_vars.manager_thread)
+ {
+ goto failed;
+ }
+ PR_INIT_CLIST(&tm_vars.timer_queue);
+ return PR_SUCCESS;
failed:
+ if (NULL != tm_vars.cancel_timer)
+ {
+ PR_DestroyCondVar(tm_vars.cancel_timer);
+ }
+ if (NULL != tm_vars.new_timer)
+ {
+ PR_DestroyCondVar(tm_vars.new_timer);
+ }
+ if (NULL != tm_vars.ml)
+ {
+ PR_DestroyLock(tm_vars.ml);
+ }
return PR_FAILURE;
-} /* MW_Init */
+}
+
+#endif /* WINNT */
+
+/******************************************************************/
+/******************************************************************/
+/************************ The private portion *********************/
+/******************************************************************/
+/******************************************************************/
+void _PR_InitMW(void)
+{
+#ifdef WINNT
+ /*
+ * We use NT 4's InterlockedCompareExchange() to operate
+ * on PRMWStatus variables.
+ */
+ PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus));
+ TimerInit();
+#endif
+ mw_lock = PR_NewLock();
+ PR_ASSERT(NULL != mw_lock);
+ mw_state = PR_NEWZAP(_PRGlobalState);
+ PR_ASSERT(NULL != mw_state);
+ PR_INIT_CLIST(&mw_state->group_list);
+ max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL);
+} /* _PR_InitMW */
static PRWaitGroup *MW_Init2(void)
{
@@ -92,15 +260,15 @@ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
** will have at least that many zeros in the low order bits.
** This may not be a good assuption.
**
- ** We try to put the entry in by rehashing three times. After
+ ** We try to put the entry in by rehashing _MW_REHASH_MAX times. After
** that we declare defeat and force the table to be reconstructed.
** Since some fds might be added more than once, won't that cause
** collisions even in an empty table?
*/
- PRIntn rehash = 11;
+ PRIntn rehash = _MW_REHASH_MAX;
PRRecvWait **waiter;
PRUintn hidx = _MW_HASH(desc->fd, hash->length);
- do
+ while (rehash-- > 0)
{
waiter = &hash->recv_wait;
if (NULL == waiter[hidx])
@@ -127,7 +295,7 @@ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd);
#endif
hidx = _MW_REHASH(desc->fd, hidx, hash->length);
- } while (--rehash > 0);
+ }
return _prmw_rehash;
} /* MW_AddHashInternal */
@@ -161,6 +329,11 @@ static _PR_HashStory MW_ExpandHashInternal(PRWaitGroup *group)
/* allocate the new hash table and fill it in with the old */
newHash = (_PRWaiterHash*)PR_CALLOC(
sizeof(_PRWaiterHash) + (length * sizeof(PRRecvWait*)));
+ if (NULL == newHash)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return _prmw_error;
+ }
newHash->length = length;
for (desc = &oldHash->recv_wait; newHash->count < oldHash->count; ++desc)
@@ -177,9 +350,11 @@ static _PR_HashStory MW_ExpandHashInternal(PRWaitGroup *group)
}
PR_DELETE(group->waiter);
group->waiter = newHash;
+ group->p_timestamp += 1;
return _prmw_success;
} /* MW_ExpandHashInternal */
+#ifndef WINNT
static void _MW_DoneInternal(
PRWaitGroup *group, PRRecvWait **waiter, PRMWStatus outcome)
{
@@ -200,6 +375,7 @@ static void _MW_DoneInternal(
group->waiter->count -= 1;
*waiter = NULL;
} /* _MW_DoneInternal */
+#endif /* WINNT */
static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd)
{
@@ -208,7 +384,7 @@ static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd)
** Only search the wait group specified.
*/
PRRecvWait **desc;
- PRIntn rehash = 11;
+ PRIntn rehash = _MW_REHASH_MAX;
_PRWaiterHash *hash = group->waiter;
PRUintn hidx = _MW_HASH(fd, hash->length);
@@ -221,6 +397,7 @@ static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd)
return NULL;
} /* _MW_LookupInternal */
+#ifndef WINNT
static PRStatus _MW_PollInternal(PRWaitGroup *group)
{
PRRecvWait **waiter;
@@ -230,12 +407,23 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
group->poller = PR_GetCurrentThread();
- PR_Unlock(group->ml);
-
while (PR_TRUE)
{
PRIntervalTime now, since_last_poll;
- PRPollDesc *poll_list = group->polling_list;
+ PRPollDesc *poll_list;
+
+ while (0 == group->waiter->count)
+ {
+ PRStatus st;
+ st = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (_MW_ABORTED(st)) goto aborted;
+ }
+
/*
** There's something to do. See if our existing polling list
** is large enough for what we have to do?
@@ -246,10 +434,24 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
PRUint32 old_count = group->waiter->count;
PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE);
PRSize new_size = sizeof(PRPollDesc) * new_count;
+ PRPollDesc *old_polling_list = group->polling_list;
+
+ PR_Unlock(group->ml);
poll_list = (PRPollDesc*)PR_CALLOC(new_size);
- if (NULL == poll_list) goto failed_alloc;
- if (NULL != group->polling_list)
- PR_DELETE(group->polling_list);
+ if (NULL == poll_list)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ PR_Lock(group->ml);
+ goto failed_alloc;
+ }
+ if (NULL != old_polling_list)
+ PR_DELETE(old_polling_list);
+ PR_Lock(group->ml);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
group->polling_list = poll_list;
group->polling_count = new_count;
}
@@ -257,14 +459,17 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
now = PR_IntervalNow();
polling_interval = max_polling_interval;
since_last_poll = now - group->last_poll;
- PR_Lock(group->ml);
- waiter = &group->waiter->recv_wait;
+ waiter = &group->waiter->recv_wait;
+ poll_list = group->polling_list;
for (count = 0; count < group->waiter->count; ++waiter)
{
+ PR_ASSERT(waiter < &group->waiter->recv_wait
+ + group->waiter->length);
if (NULL != *waiter) /* a live one! */
{
- if (since_last_poll >= (*waiter)->timeout)
+ if ((PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout)
+ && (since_last_poll >= (*waiter)->timeout))
_MW_DoneInternal(group, waiter, PR_MW_TIMEOUT);
else
{
@@ -274,6 +479,8 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
if ((*waiter)->timeout < polling_interval)
polling_interval = (*waiter)->timeout;
}
+ PR_ASSERT(poll_list < group->polling_list
+ + group->polling_count);
poll_list->fd = (*waiter)->fd;
poll_list->in_flags = PR_POLL_READ;
poll_list->out_flags = 0;
@@ -289,7 +496,15 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
}
PR_ASSERT(count == group->waiter->count);
- if (0 == count) break;
+
+ /*
+ ** If there are no more threads waiting for completion,
+ ** we need to return.
+ */
+ if ((!PR_CLIST_IS_EMPTY(&group->io_ready))
+ && (1 == group->waiting_threads)) break;
+
+ if (0 == count) continue; /* wait for new business */
group->last_poll = now;
@@ -299,14 +514,32 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
PR_Lock(group->ml);
- if (-1 == count_ready) goto failed_poll; /* that's a shame */
- for (poll_list = group->polling_list; count > 0; poll_list++, count--)
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (-1 == count_ready)
+ {
+ goto failed_poll; /* that's a shame */
+ }
+ else if (0 < count_ready)
{
- if (poll_list->out_flags != 0)
+ for (poll_list = group->polling_list; count > 0;
+ poll_list++, count--)
{
- waiter = _MW_LookupInternal(group, poll_list->fd);
- if (NULL != waiter)
- _MW_DoneInternal(group, waiter, PR_MW_SUCCESS);
+ PR_ASSERT(
+ poll_list < group->polling_list + group->polling_count);
+ if (poll_list->out_flags != 0)
+ {
+ waiter = _MW_LookupInternal(group, poll_list->fd);
+ /*
+ ** If 'waiter' is NULL, that means the wait receive
+ ** descriptor has been canceled.
+ */
+ if (NULL != waiter)
+ _MW_DoneInternal(group, waiter, PR_MW_SUCCESS);
+ }
}
}
/*
@@ -315,18 +548,24 @@ static PRStatus _MW_PollInternal(PRWaitGroup *group)
** This thread was "borrowed" to do the polling, but it really
** belongs to the client.
*/
- if ((_prmw_running != group->state)
- || (0 == group->waiting_threads)) break;
- PR_Unlock(group->ml);
+ if ((!PR_CLIST_IS_EMPTY(&group->io_ready))
+ && (1 == group->waiting_threads)) break;
}
rv = PR_SUCCESS;
+aborted:
failed_poll:
failed_alloc:
group->poller = NULL; /* we were that, not we ain't */
+ if ((_prmw_running == group->state) && (group->waiting_threads > 1))
+ {
+ /* Wake up one thread to become the new poller. */
+ PR_NotifyCondVar(group->io_complete);
+ }
return rv; /* we return with the lock held */
} /* _MW_PollInternal */
+#endif /* !WINNT */
static PRMWGroupState MW_TestForShutdownInternal(PRWaitGroup *group)
{
@@ -338,9 +577,7 @@ static PRMWGroupState MW_TestForShutdownInternal(PRWaitGroup *group)
** to make sure no more threads are made to wait.
*/
if ((_prmw_stopping == rv)
- && (0 == group->waiting_threads)
- && PR_CLIST_IS_EMPTY(&group->io_ready)
- && (0 == group->waiter->count))
+ && (0 == group->waiting_threads))
{
rv = group->state = _prmw_stopped;
PR_NotifyCondVar(group->mw_manage);
@@ -348,6 +585,7 @@ static PRMWGroupState MW_TestForShutdownInternal(PRWaitGroup *group)
return rv;
} /* MW_TestForShutdownInternal */
+#ifndef WINNT
static void _MW_InitialRecv(PRCList *io_ready)
{
PRRecvWait *desc = (PRRecvWait*)io_ready;
@@ -363,6 +601,71 @@ static void _MW_InitialRecv(PRCList *io_ready)
desc->outcome = PR_MW_FAILURE;
}
} /* _MW_InitialRecv */
+#endif
+
+#ifdef WINNT
+static void NT_TimeProc(void *arg)
+{
+ _MDOverlapped *overlapped = (_MDOverlapped *)arg;
+ PRRecvWait *desc = overlapped->data.mw.desc;
+ PRFileDesc *bottom;
+
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_TIMEOUT, (PVOID)PR_MW_PENDING) != (PVOID)PR_MW_PENDING)
+ {
+ /* This wait recv descriptor has already completed. */
+ return;
+ }
+
+ /* close the osfd to abort the outstanding async io request */
+ /* $$$$
+ ** Little late to be checking if NSPR's on the bottom of stack,
+ ** but if we don't check, we can't assert that the private data
+ ** is what we think it is.
+ ** $$$$
+ */
+ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL != bottom) /* now what!?!?! */
+ {
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError());
+ PR_ASSERT(!"What shall I do?");
+ }
+ }
+ return;
+} /* NT_TimeProc */
+
+static PRStatus NT_HashRemove(PRWaitGroup *group, PRFileDesc *fd)
+{
+ PRRecvWait **waiter;
+
+ _PR_MD_LOCK(&group->mdlock);
+ waiter = _MW_LookupInternal(group, fd);
+ if (NULL != waiter)
+ {
+ group->waiter->count -= 1;
+ *waiter = NULL;
+ }
+ _PR_MD_UNLOCK(&group->mdlock);
+ return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE;
+}
+
+PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd)
+{
+ PRRecvWait **waiter;
+
+ waiter = _MW_LookupInternal(group, fd);
+ if (NULL != waiter)
+ {
+ group->waiter->count -= 1;
+ *waiter = NULL;
+ }
+ return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE;
+}
+#endif /* WINNT */
/******************************************************************/
/******************************************************************/
@@ -374,8 +677,19 @@ PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc(
{
_PR_HashStory hrv;
PRStatus rv = PR_FAILURE;
- if (PR_FAILURE == MW_Init()) goto failed_init;
- if ((NULL == group) && (NULL == (group = MW_Init2()))) goto failed_init;
+#ifdef WINNT
+ _MDOverlapped *overlapped;
+ HANDLE hFile;
+ BOOL bResult;
+ DWORD dwError;
+ PRFileDesc *bottom;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if ((NULL == group) && (NULL == (group = MW_Init2())))
+ {
+ return rv;
+ }
PR_ASSERT(NULL != desc->fd);
@@ -389,9 +703,14 @@ PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc(
/* Not allowed to add after cancelling the group */
desc->outcome = PR_MW_INTERRUPT;
PR_SetError(PR_INVALID_STATE_ERROR, 0);
- goto invalid_state;
+ PR_Unlock(group->ml);
+ return rv;
}
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+#endif
+
/*
** If the waiter count is zero at this point, there's no telling
** how long we've been idle. Therefore, initialize the beginning
@@ -400,6 +719,7 @@ PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc(
*/
if (0 == group->waiter->count)
group->last_poll = PR_IntervalNow();
+
do
{
hrv = MW_AddHashInternal(desc, group->waiter);
@@ -408,20 +728,95 @@ PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc(
if (_prmw_success != hrv) break;
} while (PR_TRUE);
+#ifdef WINNT
+ _PR_MD_UNLOCK(&group->mdlock);
+#endif
+
PR_NotifyCondVar(group->new_business); /* tell the world */
rv = (_prmw_success == hrv) ? PR_SUCCESS : PR_FAILURE;
-
-failed_init:
-invalid_state:
PR_Unlock(group->ml);
+
+#ifdef WINNT
+ overlapped = PR_NEWZAP(_MDOverlapped);
+ if (NULL == overlapped)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ NT_HashRemove(group, desc->fd);
+ return rv;
+ }
+ overlapped->ioModel = _MD_MultiWaitIO;
+ overlapped->data.mw.desc = desc;
+ overlapped->data.mw.group = group;
+ if (desc->timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ overlapped->data.mw.timer = CreateTimer(
+ desc->timeout,
+ NT_TimeProc,
+ overlapped);
+ if (0 == overlapped->data.mw.timer)
+ {
+ NT_HashRemove(group, desc->fd);
+ PR_DELETE(overlapped);
+ /*
+ * XXX It appears that a maximum of 16 timer events can
+ * be outstanding. GetLastError() returns 0 when I try it.
+ */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ }
+
+ /* Reach to the bottom layer to get the OS fd */
+ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ hFile = (HANDLE)bottom->secret->md.osfd;
+ if (!bottom->secret->md.io_model_committed)
+ {
+ PRInt32 st;
+ st = _md_Associate(hFile);
+ PR_ASSERT(0 != st);
+ bottom->secret->md.io_model_committed = PR_TRUE;
+ }
+ bResult = ReadFile(hFile,
+ desc->buffer.start,
+ (DWORD)desc->buffer.length,
+ NULL,
+ &overlapped->overlapped);
+ if (FALSE == bResult && (dwError = GetLastError()) != ERROR_IO_PENDING)
+ {
+ if (desc->timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_FAILURE, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING)
+ {
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ NT_HashRemove(group, desc->fd);
+ PR_DELETE(overlapped);
+ }
+ _PR_MD_MAP_READ_ERROR(dwError);
+ rv = PR_FAILURE;
+ }
+#endif
+
return rv;
} /* PR_AddWaitFileDesc */
PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
{
- PRStatus rv = PR_SUCCESS;
PRCList *io_ready = NULL;
- if (PR_FAILURE == MW_Init()) goto failed_init;
+#ifdef WINNT
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ _MDOverlapped *overlapped;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
if ((NULL == group) && (NULL == (group = MW_Init2()))) goto failed_init;
PR_Lock(group->ml);
@@ -434,6 +829,35 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
group->waiting_threads += 1; /* the polling thread is counted */
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+ while (PR_CLIST_IS_EMPTY(&group->io_ready))
+ {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_IO_WAIT;
+ PR_APPEND_LINK(&me->waitQLinks, &group->wait_list);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ {
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT);
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ }
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_UNLOCK(&group->mdlock);
+ PR_Unlock(group->ml);
+ _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ me->state = _PR_RUNNING;
+ PR_Lock(group->ml);
+ _PR_MD_LOCK(&group->mdlock);
+ }
+ io_ready = PR_LIST_HEAD(&group->io_ready);
+ PR_ASSERT(io_ready != NULL);
+ PR_REMOVE_LINK(io_ready);
+ _PR_MD_UNLOCK(&group->mdlock);
+ overlapped = (_MDOverlapped *)
+ ((char *)io_ready - offsetof(_MDOverlapped, data));
+ io_ready = &overlapped->data.mw.desc->internal;
+#else
do
{
/*
@@ -442,13 +866,6 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
*/
if (PR_CLIST_IS_EMPTY(&group->io_ready))
{
- while ((NULL == group->waiter) || (0 == group->waiter->count))
- {
- if (_prmw_running != group->state) goto aborted;
- rv = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT);
- if (_MW_ABORTED(rv)) goto aborted;
- }
-
/*
** Is there a polling thread yet? If not, grab this thread
** and use it.
@@ -464,31 +881,102 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
** with some I/O ready.
*/
if (PR_FAILURE == _MW_PollInternal(group)) goto failed_poll;
- if (PR_CLIST_IS_EMPTY(&group->io_ready)) continue; /* timeout */
}
else
{
+ /*
+ ** There are four reasons a thread can be awakened from
+ ** a wait on the io_complete condition variable.
+ ** 1. Some I/O has completed, i.e., the io_ready list
+ ** is nonempty.
+ ** 2. The wait group is canceled.
+ ** 3. The thread is interrupted.
+ ** 4. The current polling thread has to leave and needs
+ ** a replacement.
+ ** The logic to find a new polling thread is made more
+ ** complicated by all the other possible events.
+ ** I tried my best to write the logic clearly, but
+ ** it is still full of if's with continue and goto.
+ */
+ PRStatus st;
while (PR_CLIST_IS_EMPTY(&group->io_ready))
{
- rv = PR_WaitCondVar(group->io_complete, PR_INTERVAL_NO_TIMEOUT);
- if (_MW_ABORTED(rv)) goto aborted;
+ st = PR_WaitCondVar(group->io_complete, PR_INTERVAL_NO_TIMEOUT);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (_MW_ABORTED(st) || (NULL == group->poller)) break;
+ }
+
+ /*
+ ** The thread is interrupted and has to leave. It might
+ ** have also been awakened to process ready i/o or be the
+ ** new poller. To be safe, if either condition is true,
+ ** we awaken another thread to take its place.
+ */
+ if (_MW_ABORTED(st))
+ {
+ if ((NULL == group->poller
+ || !PR_CLIST_IS_EMPTY(&group->io_ready))
+ && group->waiting_threads > 1)
+ PR_NotifyCondVar(group->io_complete);
+ goto aborted;
+ }
+
+ /*
+ ** A new poller is needed, but can I be the new poller?
+ ** If there is no i/o ready, sure. But if there is any
+ ** i/o ready, it has a higher priority. I want to
+ ** process the ready i/o first and wake up another
+ ** thread to be the new poller.
+ */
+ if (NULL == group->poller)
+ {
+ if (PR_CLIST_IS_EMPTY(&group->io_ready))
+ continue;
+ if (group->waiting_threads > 1)
+ PR_NotifyCondVar(group->io_complete);
}
}
+ PR_ASSERT(!PR_CLIST_IS_EMPTY(&group->io_ready));
}
io_ready = PR_LIST_HEAD(&group->io_ready);
PR_NotifyCondVar(group->io_taken);
PR_ASSERT(io_ready != NULL);
PR_REMOVE_LINK(io_ready);
+ } while (NULL == io_ready);
+
+aborted:
+failed_poll:
+#endif
+
+ group->waiting_threads -= 1;
+invalid_state:
+ (void)MW_TestForShutdownInternal(group);
+ PR_Unlock(group->ml);
+
+failed_init:
+ if (NULL != io_ready)
+ {
/* If the operation failed, record the reason why */
switch (((PRRecvWait*)io_ready)->outcome)
{
case PR_MW_PENDING:
- PR_ASSERT(PR_MW_PENDING != ((PRRecvWait*)io_ready)->outcome);
+ PR_ASSERT(0);
break;
case PR_MW_SUCCESS:
+#ifndef WINNT
_MW_InitialRecv(io_ready);
+#endif
break;
+#ifdef WINNT
+ case PR_MW_FAILURE:
+ _PR_MD_MAP_READ_ERROR(overlapped->data.mw.error);
+ break;
+#endif
case PR_MW_TIMEOUT:
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
break;
@@ -497,25 +985,30 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
break;
default: break;
}
- } while (NULL == io_ready);
-
-aborted:
-failed_poll:
- group->waiting_threads -= 1;
-invalid_state:
- (void)MW_TestForShutdownInternal(group);
- PR_Unlock(group->ml);
-
-failed_init:
-
+#ifdef WINNT
+ if (NULL != overlapped->data.mw.timer)
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ != overlapped->data.mw.desc->timeout);
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ else
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ == overlapped->data.mw.desc->timeout);
+ }
+ PR_DELETE(overlapped);
+#endif
+ }
return (PRRecvWait*)io_ready;
} /* PR_WaitRecvReady */
PR_IMPLEMENT(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc)
{
+#if !defined(WINNT)
PRRecvWait **recv_wait;
+#endif
PRStatus rv = PR_SUCCESS;
- if (PR_FAILURE == MW_Init()) return rv;
if (NULL == group) group = mw_state->group;
PR_ASSERT(NULL != group);
if (NULL == group)
@@ -533,6 +1026,28 @@ PR_IMPLEMENT(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *des
goto stopping;
}
+#ifdef WINNT
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_INTERRUPT, (PVOID)PR_MW_PENDING) == (PVOID)PR_MW_PENDING)
+ {
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ goto invalid_arg;
+ }
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+#if 0
+ fprintf(stderr, "cancel wait recv: closing socket\n");
+#endif
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError());
+ exit(1);
+ }
+ }
+#else
if (NULL != (recv_wait = _MW_LookupInternal(group, desc->fd)))
{
/* it was in the wait table */
@@ -554,7 +1069,9 @@ PR_IMPLEMENT(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *des
rv = PR_FAILURE;
found:
+#endif
stopping:
+invalid_arg:
PR_Unlock(group->ml);
return rv;
} /* PR_CancelWaitFileDesc */
@@ -563,11 +1080,12 @@ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
{
PRRecvWait **desc;
PRRecvWait *recv_wait = NULL;
- if (PR_FAILURE == MW_Init())
- {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return NULL;
- }
+#ifdef WINNT
+ _MDOverlapped *overlapped;
+ PRRecvWait **end;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#endif
+
if (NULL == group) group = mw_state->group;
PR_ASSERT(NULL != group);
if (NULL == group)
@@ -583,18 +1101,77 @@ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
group->state = _prmw_stopping; /* so nothing new comes in */
if (0 == group->waiting_threads) /* is there anybody else? */
group->state = _prmw_stopped; /* we can stop right now */
+ else
+ {
+ PR_NotifyAllCondVar(group->new_business);
+ PR_NotifyAllCondVar(group->io_complete);
+ }
while (_prmw_stopped != group->state)
(void)PR_WaitCondVar(group->mw_manage, PR_INTERVAL_NO_TIMEOUT);
+ }
- /* make all the existing descriptors look done/interrupted */
- for (desc = &group->waiter->recv_wait; group->waiter->count > 0; ++desc)
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+#endif
+ /* make all the existing descriptors look done/interrupted */
+#ifdef WINNT
+ end = &group->waiter->recv_wait + group->waiter->length;
+ for (desc = &group->waiter->recv_wait; desc < end; ++desc)
+ {
+ if (NULL != *desc)
{
- if (NULL != *desc)
- _MW_DoneInternal(group, desc, PR_MW_INTERRUPT);
+ if (InterlockedCompareExchange((PVOID *)&(*desc)->outcome,
+ (PVOID)PR_MW_INTERRUPT, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING)
+ {
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(
+ (*desc)->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ goto invalid_arg;
+ }
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+#if 0
+ fprintf(stderr, "cancel wait group: closing socket\n");
+#endif
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n",
+ WSAGetLastError());
+ exit(1);
+ }
+ }
}
-
- PR_NotifyAllCondVar(group->new_business);
}
+ while (group->waiter->count > 0)
+ {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_IO_WAIT;
+ PR_APPEND_LINK(&me->waitQLinks, &group->wait_list);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ {
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT);
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ }
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_UNLOCK(&group->mdlock);
+ PR_Unlock(group->ml);
+ _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ me->state = _PR_RUNNING;
+ PR_Lock(group->ml);
+ _PR_MD_LOCK(&group->mdlock);
+ }
+#else
+ for (desc = &group->waiter->recv_wait; group->waiter->count > 0; ++desc)
+ {
+ PR_ASSERT(desc < &group->waiter->recv_wait + group->waiter->length);
+ if (NULL != *desc)
+ _MW_DoneInternal(group, desc, PR_MW_INTERRUPT);
+ }
+#endif
/* take first element of finished list and return it or NULL */
if (PR_CLIST_IS_EMPTY(&group->io_ready))
@@ -603,8 +1180,17 @@ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
{
PRCList *head = PR_LIST_HEAD(&group->io_ready);
PR_REMOVE_AND_INIT_LINK(head);
+#ifdef WINNT
+ overlapped = (_MDOverlapped *)
+ ((char *)head - offsetof(_MDOverlapped, data));
+ head = &overlapped->data.mw.desc->internal;
+#endif
recv_wait = (PRRecvWait*)head;
}
+#ifdef WINNT
+invalid_arg:
+ _PR_MD_UNLOCK(&group->mdlock);
+#endif
PR_Unlock(group->ml);
return recv_wait;
@@ -612,10 +1198,13 @@ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */)
{
- PRWaitGroup *wg = NULL;
- if (PR_FAILURE == MW_Init()) goto failed;
+ PRWaitGroup *wg;
- if (NULL == (wg = PR_NEWZAP(PRWaitGroup))) goto failed;
+ if (NULL == (wg = PR_NEWZAP(PRWaitGroup)))
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto failed;
+ }
/* the wait group itself */
wg->ml = PR_NewLock();
if (NULL == wg->ml) goto failed_lock;
@@ -635,10 +1224,19 @@ PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */)
wg->waiter = (_PRWaiterHash*)PR_CALLOC(
sizeof(_PRWaiterHash) +
(_PR_DEFAULT_HASH_LENGTH * sizeof(PRRecvWait*)));
- if (NULL == wg->waiter) goto failed_waiter;
+ if (NULL == wg->waiter)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto failed_waiter;
+ }
wg->waiter->count = 0;
wg->waiter->length = _PR_DEFAULT_HASH_LENGTH;
+#ifdef WINNT
+ _PR_MD_NEW_LOCK(&wg->mdlock);
+ PR_INIT_CLIST(&wg->wait_list);
+#endif /* WINNT */
+
PR_Lock(mw_lock);
PR_APPEND_LINK(&wg->group_link, &mw_state->group_list);
PR_Unlock(mw_lock);
@@ -649,13 +1247,14 @@ failed_waiter:
failed_cvar3:
PR_DestroyCondVar(wg->new_business);
failed_cvar2:
- PR_DestroyCondVar(wg->io_taken);
-failed_cvar1:
PR_DestroyCondVar(wg->io_complete);
+failed_cvar1:
+ PR_DestroyCondVar(wg->io_taken);
failed_cvar0:
PR_DestroyLock(wg->ml);
failed_lock:
PR_DELETE(wg);
+ wg = NULL;
failed:
return wg;
@@ -668,27 +1267,36 @@ PR_IMPLEMENT(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group)
PR_ASSERT(NULL != group);
if (NULL != group)
{
- if (_prmw_stopped != group->state) /* quick, unsafe test */
+ PR_Lock(group->ml);
+ if ((group->waiting_threads == 0)
+ && (group->waiter->count == 0)
+ && PR_CLIST_IS_EMPTY(&group->io_ready))
{
- PRMWGroupState mws;
- /* One shot to correct the situation */
- PR_Lock(group->ml);
- if (group->state < _prmw_stopped) /* safer test */
- group->state = _prmw_stopping;
- mws = MW_TestForShutdownInternal(group);
- PR_Unlock(group->ml);
- if (_prmw_stopped != mws) /* quick test again */
- {
- PR_SetError(PR_INVALID_STATE_ERROR, 0);
- return PR_FAILURE;
- }
+ group->state = _prmw_stopped;
}
+ else
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ PR_Unlock(group->ml);
+ if (PR_FAILURE == rv) return rv;
PR_Lock(mw_lock);
PR_REMOVE_LINK(&group->group_link);
PR_Unlock(mw_lock);
+#ifdef WINNT
+ /*
+ * XXX make sure wait_list is empty and waiter is empty.
+ * These must be checked while holding mdlock.
+ */
+ _PR_MD_FREE_LOCK(&group->mdlock);
+#endif
+
PR_DELETE(group->waiter);
+ PR_DELETE(group->polling_list);
+ PR_DestroyCondVar(group->mw_manage);
PR_DestroyCondVar(group->new_business);
PR_DestroyCondVar(group->io_complete);
PR_DestroyCondVar(group->io_taken);
@@ -696,7 +1304,108 @@ PR_IMPLEMENT(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group)
if (group == mw_state->group) mw_state->group = NULL;
PR_DELETE(group);
}
+ else
+ {
+ /* The default wait group is not created yet. */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
return rv;
} /* PR_DestroyWaitGroup */
+/**********************************************************************
+***********************************************************************
+******************** Wait group enumerations **************************
+***********************************************************************
+**********************************************************************/
+
+PR_IMPLEMENT(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group)
+{
+ PRMWaitEnumerator *enumerator = PR_NEWZAP(PRMWaitEnumerator);
+ if (NULL == enumerator) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ enumerator->group = group;
+ enumerator->seal = _PR_ENUM_SEALED;
+ }
+ return enumerator;
+} /* PR_CreateMWaitEnumerator */
+
+PR_IMPLEMENT(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator)
+{
+ PR_ASSERT(NULL != enumerator);
+ PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal);
+ if ((NULL == enumerator) || (_PR_ENUM_SEALED != enumerator->seal))
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ enumerator->seal = _PR_ENUM_UNSEALED;
+ PR_Free(enumerator);
+ return PR_SUCCESS;
+} /* PR_DestroyMWaitEnumerator */
+
+PR_IMPLEMENT(PRRecvWait*) PR_EnumerateWaitGroup(
+ PRMWaitEnumerator *enumerator, const PRRecvWait *previous)
+{
+ PRRecvWait *result = NULL;
+
+ /* entry point sanity checking */
+ PR_ASSERT(NULL != enumerator);
+ PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal);
+ if ((NULL == enumerator)
+ || (_PR_ENUM_SEALED != enumerator->seal)) goto bad_argument;
+
+ /* beginning of enumeration */
+ if (NULL == previous)
+ {
+ if (NULL == enumerator->group)
+ {
+ enumerator->group = mw_state->group;
+ if (NULL == enumerator->group)
+ {
+ PR_SetError(PR_GROUP_EMPTY_ERROR, 0);
+ return NULL;
+ }
+ }
+ enumerator->waiter = &enumerator->group->waiter->recv_wait;
+ enumerator->p_timestamp = enumerator->group->p_timestamp;
+ enumerator->thread = PR_GetCurrentThread();
+ enumerator->index = 0;
+ }
+ /* continuing an enumeration */
+ else
+ {
+ PRThread *me = PR_GetCurrentThread();
+ PR_ASSERT(me == enumerator->thread);
+ if (me != enumerator->thread) goto bad_argument;
+
+ /* need to restart the enumeration */
+ if (enumerator->p_timestamp != enumerator->group->p_timestamp)
+ return PR_EnumerateWaitGroup(enumerator, NULL);
+ }
+
+ /* actually progress the enumeration */
+#if defined(WINNT)
+ _PR_MD_LOCK(&enumerator->group->mdlock);
+#else
+ PR_Lock(enumerator->group->ml);
+#endif
+ while (enumerator->index++ < enumerator->group->waiter->length)
+ {
+ if (NULL != (result = *(enumerator->waiter)++)) break;
+ }
+#if defined(WINNT)
+ _PR_MD_UNLOCK(&enumerator->group->mdlock);
+#else
+ PR_Unlock(enumerator->group->ml);
+#endif
+
+ return result; /* what we live for */
+
+bad_argument:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL; /* probably ambiguous */
+} /* PR_EnumerateWaitGroup */
+
/* prmwait.c */
diff --git a/pr/src/io/prpolevt.c b/pr/src/io/prpolevt.c
new file mode 100644
index 00000000..a1ca3760
--- /dev/null
+++ b/pr/src/io/prpolevt.c
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ *********************************************************************
+ *
+ * Pollable events
+ *
+ *********************************************************************
+ */
+
+#include "primpl.h"
+
+typedef struct MyFilePrivate {
+ PRFilePrivate copy;
+ PRFileDesc *writeEnd;
+ PRFilePrivate *oldSecret;
+} MyFilePrivate;
+
+#ifndef XP_UNIX
+#define USE_TCP_SOCKETPAIR
+#endif
+
+PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
+{
+ PRFileDesc *fd[2]; /* fd[0] is the read end; fd[1] is the write end */
+ MyFilePrivate *secret;
+
+ secret = PR_NEW(MyFilePrivate);
+ if (secret == NULL) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+#ifndef USE_TCP_SOCKETPAIR
+ if (PR_CreatePipe(&fd[0], &fd[1]) == PR_FAILURE) {
+ goto errorExit;
+ }
+#else
+ if (PR_NewTCPSocketPair(fd) == PR_FAILURE) {
+ goto errorExit;
+ }
+#endif
+
+ secret->copy = *fd[0]->secret;
+ secret->oldSecret = fd[0]->secret;
+ secret->writeEnd = fd[1];
+ fd[0]->secret = (PRFilePrivate *) secret;
+
+ return fd[0];
+
+errorExit:
+ PR_DELETE(secret);
+ return NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
+{
+ MyFilePrivate *secret;
+
+ secret = (MyFilePrivate *) event->secret;
+ event->secret = secret->oldSecret;
+ PR_Close(event);
+ PR_Close(secret->writeEnd);
+ PR_DELETE(secret);
+ return PR_SUCCESS;
+}
+
+static const char magicChar = '\x38';
+
+PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
+{
+ MyFilePrivate *secret;
+
+ secret = (MyFilePrivate *) event->secret;
+ if (PR_Write(secret->writeEnd, &magicChar, 1) != 1) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
+{
+ char buf[1024];
+ PRInt32 nBytes;
+#ifdef DEBUG
+ PRIntn i;
+#endif
+
+ nBytes = PR_Read(event, buf, sizeof(buf));
+ if (nBytes == -1) {
+ return PR_FAILURE;
+ }
+
+#ifdef DEBUG
+ /*
+ * Make sure people do not write to the pollable event fd
+ * directly.
+ */
+ for (i = 0; i < nBytes; i++) {
+ PR_ASSERT(buf[i] == magicChar);
+ }
+#endif
+
+ return PR_SUCCESS;
+}
diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c
index d0fbcf82..11611cfa 100644
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -221,14 +221,16 @@ PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
#elif defined(WIN32) || defined(WIN16)
- if (pd->out_flags & PR_POLL_EXCEPT) {
- int len = sizeof(err);
#if defined(WIN32)
-/* Note: There is a bug in Win32 WinSock. The sleep circumvents the
-** bug. See wtc. /s lth.
-*/
- Sleep(0);
+ /*
+ * The sleep circumvents a bug in Win32 WinSock.
+ * See Microsoft Knowledge Base article ID: Q165989.
+ */
+ Sleep(0);
#endif /* WIN32 */
+
+ if (pd->out_flags & PR_POLL_EXCEPT) {
+ int len = sizeof(err);
if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len)
== SOCKET_ERROR) {
_PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
@@ -517,20 +519,21 @@ static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32
static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd)
{
- PRInt32 rv;
-
- if (!fd || fd->secret->state != _PR_FILEDESC_OPEN) {
+ if (!fd || !fd->secret
+ || (fd->secret->state != _PR_FILEDESC_OPEN
+ && fd->secret->state != _PR_FILEDESC_CLOSED)) {
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
return PR_FAILURE;
}
- fd->secret->state = _PR_FILEDESC_CLOSED;
+ if (fd->secret->state == _PR_FILEDESC_OPEN) {
+ if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) {
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ }
- rv = _PR_MD_CLOSE_SOCKET(fd->secret->md.osfd);
PR_FreeFileDesc(fd);
- if (rv < 0) {
- return PR_FAILURE;
- }
return PR_SUCCESS;
}
@@ -632,6 +635,11 @@ PRIntervalTime timeout)
PR_SetError(PR_IO_PENDING_ERROR, 0);
return -1;
}
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
*nd = NULL;
#if defined(WINNT)
@@ -784,6 +792,11 @@ PRIntervalTime timeout)
PR_SetError(PR_IO_PENDING_ERROR, 0);
return -1;
}
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
#if defined(WINNT)
rv = _PR_MD_TRANSMITFILE(
sd, fd,
@@ -797,7 +810,6 @@ PRIntervalTime timeout)
* that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should
* not be called because the socket will be recycled.
*/
- sd->secret->state = _PR_FILEDESC_CLOSED;
PR_FreeFileDesc(sd);
}
#else
@@ -885,7 +897,7 @@ static PRStatus PR_CALLBACK SocketGetSockOpt(
else
{
rv = _PR_MD_GETSOCKOPT(
- fd, level, name, optval, optlen);
+ fd, level, name, (char*)optval, optlen);
}
}
return rv;
@@ -940,7 +952,7 @@ static PRStatus PR_CALLBACK SocketSetSockOpt(
else
{
rv = _PR_MD_SETSOCKOPT(
- fd, level, name, optval, optlen);
+ fd, level, name, (const char*)optval, optlen);
}
}
return rv;
@@ -1126,20 +1138,62 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
_PR_MD_MAKE_NONBLOCK(f[0]);
_PR_MD_MAKE_NONBLOCK(f[1]);
return PR_SUCCESS;
-#endif
-
- /* XXX: this needs to be implemented for MAC and NT */
-#ifdef XP_MAC
-#pragma unused (f)
+#else /* XP_UNIX */
+ PRFileDesc *listenSock;
+ PRNetAddr selfAddr;
+ PRUint16 port;
+
+ f[0] = f[1] = NULL;
+ listenSock = PR_NewTCPSocket();
+ if (listenSock == NULL) {
+ goto failed;
+ }
+ PR_InitializeNetAddr(PR_IpAddrAny, 0, &selfAddr);
+ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ port = ntohs(selfAddr.inet.port);
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ goto failed;
+ }
+ f[0] = PR_NewTCPSocket();
+ if (f[0] == NULL) {
+ goto failed;
+ }
+ PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
- return PR_FAILURE;
-#endif
+ /*
+ * Only a thread is used to do the connect and accept.
+ * I am relying on the fact that PR_Connect returns
+ * successfully as soon as the connect request is put
+ * into the listen queue (but before PR_Accept is called).
+ * This is the behavior of the BSD socket code. If
+ * connect does not return until accept is called, we
+ * will need to create another thread to call connect.
+ */
+ if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT)
+ == PR_FAILURE) {
+ goto failed;
+ }
+ f[1] = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (f[1] == NULL) {
+ goto failed;
+ }
+ PR_Close(listenSock);
+ return PR_SUCCESS;
-#ifdef XP_PC
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FAILURE;
-#endif
+failed:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ if (f[0]) {
+ PR_Close(f[0]);
+ }
+ return PR_FAILURE;
+#endif /* XP_UNIX */
}
PR_IMPLEMENT(PRInt32)
@@ -1196,7 +1250,7 @@ PRIntervalTime timeout)
return -1;
}
- buf = PR_MALLOC(_TRANSMITFILE_BUFSIZE);
+ buf = (char*)PR_MALLOC(_TRANSMITFILE_BUFSIZE);
if (buf == NULL) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return -1;
@@ -1262,47 +1316,49 @@ done:
* newly accepted socket, read 'amount' bytes from the accepted
* socket.
*
- * buf is a buffer of length = (amount + sizeof(PRNetAddr))
+ * buf is a buffer of length = (amount + 2 * sizeof(PRNetAddr))
* *raddr points to the PRNetAddr of the accepted connection upon
* return
*
* return number of bytes read or -1 on error
*
*/
-PRInt32 _PR_EmulateAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
-PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
+PRInt32 _PR_EmulateAcceptRead(
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
{
- PRInt32 rv;
- PRFileDesc *newsockfd;
- PRIntervalTime start, elapsed;
+ PRInt32 rv = -1;
+ PRNetAddr remote;
+ PRFileDesc *accepted = NULL;
- if (PR_INTERVAL_NO_TIMEOUT != timeout) {
- start = PR_IntervalNow();
- }
- *raddr = (PRNetAddr *) ((char *) buf + amount);
- if ((newsockfd = PR_Accept(sd, *raddr, timeout)) == NULL) {
- return -1;
- }
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return rv;
+ }
- if (PR_INTERVAL_NO_TIMEOUT != timeout) {
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto failed;
- } else {
- timeout = timeout - elapsed;
- }
- }
+ /*
+ ** The timeout does not apply to the accept portion of the
+ ** operation - it waits indefinitely.
+ */
+ accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == accepted) return rv;
- rv = PR_Recv(newsockfd, buf, amount, 0, timeout);
- if (rv >= 0) {
- *nd = newsockfd;
- return rv;
- }
+ rv = PR_Recv(accepted, buf, amount, 0, timeout);
+ if (rv >= 0)
+ {
+ /* copy the new info out where caller can see it */
+ PRPtrdiff aligned = (PRPtrdiff)buf + amount + sizeof(void*) - 1;
+ *raddr = (PRNetAddr*)(aligned & ~(sizeof(void*) - 1));
+ memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
+ *nd = accepted;
+ return rv;
+ }
failed:
- PR_Close(newsockfd);
- return -1;
+ PR_Close(accepted);
+ return rv;
}
/*
@@ -1403,7 +1459,7 @@ static PRPollDesc *_pr_setfd(
if ((PRFileDesc*)-1 == poll[pdidx].fd)
{
/* our vector is full - extend and condition it */
- poll = PR_Realloc(
+ poll = (PRPollDesc*)PR_Realloc(
poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc));
if (NULL == poll) goto out_of_memory;
memset(
@@ -1495,7 +1551,7 @@ PR_IMPLEMENT(PRInt32) PR_Select(
return 0;
}
- copy = poll = PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc));
+ copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc));
if (NULL == poll) goto out_of_memory;
poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1;
diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c
index 93f0b45a..ff06b33d 100644
--- a/pr/src/linking/prlink.c
+++ b/pr/src/linking/prlink.c
@@ -32,7 +32,7 @@
#include <dlfcn.h>
#elif defined(USE_HPSHL)
#include <dl.h>
-#elif defined(USE_RLD)
+#elif defined(RHAPSODY)
#include <mach-o/dyld.h>
#endif
@@ -42,6 +42,13 @@
#endif
#endif /* XP_UNIX */
+/*
+ * On these platforms, symbols have a leading '_'.
+ */
+#if defined(SUNOS4) || defined(RHAPSODY) || defined(WIN16)
+#define NEED_LEADING_UNDERSCORE
+#endif
+
#ifdef XP_PC
typedef PRStaticLinkTable *NODL_PROC(void);
#endif
@@ -49,25 +56,25 @@ typedef PRStaticLinkTable *NODL_PROC(void);
/************************************************************************/
struct PRLibrary {
- char* name; /* Our own copy of the name string */
- PRLibrary* next;
- int refCount;
- const PRStaticLinkTable* staticTable;
+ char* name; /* Our own copy of the name string */
+ PRLibrary* next;
+ int refCount;
+ const PRStaticLinkTable* staticTable;
#ifdef XP_PC
- HINSTANCE dlh;
+ HINSTANCE dlh;
#endif
#ifdef XP_MAC
- CFragConnectionID dlh;
+ CFragConnectionID dlh;
#endif
#ifdef XP_UNIX
#if defined(USE_HPSHL)
- shl_t dlh;
-#elif defined(USE_RLD)
- NSModule dlh;
+ shl_t dlh;
+#elif defined(RHAPSODY)
+ NSModule dlh;
#else
- void* dlh;
+ void* dlh;
#endif
#endif
};
@@ -81,11 +88,11 @@ static char* _pr_currentLibPath = NULL;
#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR)
static char* errStrBuf = NULL;
-#define ERR_STR_BUF_LENGTH 20
+#define ERR_STR_BUF_LENGTH 20
static char* errno_string(PRIntn oserr)
{
if (errStrBuf == NULL)
- errStrBuf = PR_MALLOC(ERR_STR_BUF_LENGTH);
+ errStrBuf = PR_MALLOC(ERR_STR_BUF_LENGTH);
PR_snprintf(errStrBuf, ERR_STR_BUF_LENGTH, "error %d", oserr);
return errStrBuf;
}
@@ -140,31 +147,31 @@ void _PR_InitLinker(void)
lm->dlh = (HINSTANCE)NULL;
#endif /* ! _WIN32 */
- lm->refCount = 1;
+ lm->refCount = 1;
lm->staticTable = NULL;
- pr_exe_loadmap = lm;
- pr_loadmap = lm;
+ pr_exe_loadmap = lm;
+ pr_loadmap = lm;
#elif defined(XP_UNIX)
#ifdef HAVE_DLL
#ifdef USE_DLFCN
h = dlopen(0, RTLD_LAZY);
- if (!h) {
- char *error;
-
- DLLErrorInternal(_MD_ERRNO());
- error = (char*)PR_MALLOC(PR_GetErrorTextLength());
- (void) PR_GetErrorText(error);
- fprintf(stderr, "failed to initialize shared libraries [%s]\n",
- error);
- PR_DELETE(error);
- abort();/* XXX */
- }
+ if (!h) {
+ char *error;
+
+ DLLErrorInternal(_MD_ERRNO());
+ error = (char*)PR_MALLOC(PR_GetErrorTextLength());
+ (void) PR_GetErrorText(error);
+ fprintf(stderr, "failed to initialize shared libraries [%s]\n",
+ error);
+ PR_DELETE(error);
+ abort();/* XXX */
+ }
#elif defined(USE_HPSHL)
- h = NULL;
- /* don't abort with this NULL */
-#elif defined(USE_RLD)
- h = NULL; /* XXXX toshok */
+ h = NULL;
+ /* don't abort with this NULL */
+#elif defined(RHAPSODY)
+ h = NULL; /* XXXX toshok */
#else
#error no dll strategy
#endif /* USE_DLFCN */
@@ -172,7 +179,7 @@ void _PR_InitLinker(void)
lm = PR_NEWZAP(PRLibrary);
if (lm) {
lm->name = strdup("a.out");
- lm->refCount = 1;
+ lm->refCount = 1;
lm->dlh = h;
lm->staticTable = NULL;
}
@@ -194,14 +201,14 @@ void _PR_ShutdownLinker(void)
PR_EnterMonitor(pr_linker_lock);
while (pr_loadmap) {
- if (pr_loadmap->refCount > 1) {
+ if (pr_loadmap->refCount > 1) {
#ifdef DEBUG
- fprintf(stderr, "# Forcing library to unload: %s (%d outstanding references)\n",
- pr_loadmap->name, pr_loadmap->refCount);
+ fprintf(stderr, "# Forcing library to unload: %s (%d outstanding references)\n",
+ pr_loadmap->name, pr_loadmap->refCount);
#endif
- pr_loadmap->refCount = 1;
- }
- PR_UnloadLibrary(pr_loadmap);
+ pr_loadmap->refCount = 1;
+ }
+ PR_UnloadLibrary(pr_loadmap);
}
PR_ExitMonitor(pr_linker_lock);
@@ -223,7 +230,7 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
_pr_currentLibPath = strdup(path);
if (!_pr_currentLibPath) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- rv = PR_FAILURE;
+ rv = PR_FAILURE;
}
} else {
_pr_currentLibPath = 0;
@@ -251,78 +258,78 @@ PR_GetLibraryPath()
#ifdef XP_PC
ev = getenv("LD_LIBRARY_PATH");
if (!ev) {
- ev = ".;\\lib";
+ ev = ".;\\lib";
}
ev = strdup(ev);
#endif
#ifdef XP_MAC
- {
- char *p;
- int len;
+ {
+ char *p;
+ int len;
ev = getenv("LD_LIBRARY_PATH");
/* if we couldn't find something make up a default */
- if (!ev)
- ev = "/usr/local/netscape;/usr/local/netscape/java/bin"; /* do we put the classes in here too? */
-
- len = strlen(ev) + 1; /* +1 for the null */
- p = (char*) PR_MALLOC(len);
- if (p) {
- strcpy(p, ev);
- }
- ev = p;
- }
+ if (!ev)
+ ev = "/usr/local/netscape;/usr/local/netscape/java/bin"; /* do we put the classes in here too? */
+
+ len = strlen(ev) + 1; /* +1 for the null */
+ p = (char*) PR_MALLOC(len);
+ if (p) {
+ strcpy(p, ev);
+ }
+ ev = p;
+ }
#endif
#ifdef XP_UNIX
-#if defined USE_DLFCN || defined USE_RLD
+#if defined USE_DLFCN || defined RHAPSODY
{
- char *home;
- char *local;
- char *p=NULL;
+ char *home;
+ char *local;
+ char *p=NULL;
char * mozilla_home=NULL;
- int len;
-
- ev = getenv("LD_LIBRARY_PATH");
- if (!ev) {
- ev = "/usr/lib:/lib";
- }
- home = getenv("HOME");
-
- /*
- ** Augment the path automatically by adding in ~/.netscape and
- ** /usr/local/netscape
- */
- len = strlen(ev) + 1; /* +1 for the null */
- if (home && home[0]) {
- len += strlen(home) + 1; /* +1 for the colon */
- }
-
- mozilla_home = getenv("MOZILLA_HOME");
- if (mozilla_home && mozilla_home[0]) {
- len += strlen(mozilla_home) + 5 ; /* +5 for initial : and trailing "/lib" */
- }
-
- local = ":/usr/local/netscape/lib/" PR_LINKER_ARCH;
- len += strlen(local); /* already got the : */
- p = (char*) PR_MALLOC(len+50);
- if (p) {
- strcpy(p, ev);
- if (home) {
- strcat(p, ":");
- strcat(p, home);
- }
+ int len;
+
+ ev = getenv("LD_LIBRARY_PATH");
+ if (!ev) {
+ ev = "/usr/lib:/lib";
+ }
+ home = getenv("HOME");
+
+ /*
+ ** Augment the path automatically by adding in ~/.netscape and
+ ** /usr/local/netscape
+ */
+ len = strlen(ev) + 1; /* +1 for the null */
+ if (home && home[0]) {
+ len += strlen(home) + 1; /* +1 for the colon */
+ }
+
+ mozilla_home = getenv("MOZILLA_HOME");
+ if (mozilla_home && mozilla_home[0]) {
+ len += strlen(mozilla_home) + 5 ; /* +5 for initial : and trailing "/lib" */
+ }
+
+ local = ":/usr/local/netscape/lib/" PR_LINKER_ARCH;
+ len += strlen(local); /* already got the : */
+ p = (char*) PR_MALLOC(len+50);
+ if (p) {
+ strcpy(p, ev);
+ if (home) {
+ strcat(p, ":");
+ strcat(p, home);
+ }
if (mozilla_home && mozilla_home[0]) {
strcat(p, ":");
strcat(p, mozilla_home);
strcat(p, "/lib");
}
- strcat(p, local);
- } /* if (p) */
- ev = p;
- PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev));
+ strcat(p, local);
+ } /* if (p) */
+ ev = p;
+ PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev));
printf("linker_path = %s\n", ev);
@@ -360,7 +367,7 @@ PR_GetLibraryName(const char *path, const char *lib)
#ifdef XP_PC
if (strstr(lib, PR_DLL_SUFFIX) == NULL)
{
- fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
+ fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
} else {
fullname = PR_smprintf("%s\\%s", path, lib);
}
@@ -395,23 +402,23 @@ pr_UnlockedFindLibrary(const char *name)
const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
np = np ? np + 1 : name;
while (lm) {
- const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
- cp = cp ? cp + 1 : lm->name;
+ const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
+ cp = cp ? cp + 1 : lm->name;
#ifdef XP_PC
/* Windows DLL names are case insensitive... */
- if (strcmpi(np, cp) == 0)
+ if (strcmpi(np, cp) == 0)
#else
- if (strcmp(np, cp) == 0)
-#endif
- {
- /* found */
- lm->refCount++;
- PR_LOG(_pr_linker_lm, PR_LOG_MIN,
- ("%s incr => %d (find lib)",
- lm->name, lm->refCount));
- return lm;
- }
- lm = lm->next;
+ if (strcmp(np, cp) == 0)
+#endif
+ {
+ /* found */
+ lm->refCount++;
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s incr => %d (find lib)",
+ lm->name, lm->refCount));
+ return lm;
+ }
+ lm = lm->next;
}
return NULL;
}
@@ -448,31 +455,31 @@ PR_LoadLibrary(const char *name)
retry:
ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h);
- if (ulRc != NO_ERROR) {
- PR_DELETE(lm);
- goto unlock;
- }
- lm->name = strdup(name);
- lm->dlh = h;
- lm->next = pr_loadmap;
- pr_loadmap = lm;
+ if (ulRc != NO_ERROR) {
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
}
#endif /* XP_OS2 */
#if defined(WIN32) || defined(WIN16)
{
- HINSTANCE h;
+ HINSTANCE h;
NODL_PROC *pfn;
- h = LoadLibrary(name);
- if (h < (HINSTANCE)HINSTANCE_ERROR) {
- PR_DELETE(lm);
- goto unlock;
- }
- lm->name = strdup(name);
- lm->dlh = h;
- lm->next = pr_loadmap;
- pr_loadmap = lm;
+ h = LoadLibrary(name);
+ if (h < (HINSTANCE)HINSTANCE_ERROR) {
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
/*
** Try to load a table of "static functions" provided by the DLL
@@ -487,139 +494,139 @@ PR_LoadLibrary(const char *name)
#if defined(XP_MAC) && GENERATINGCFM
{
- OSErr err;
- Ptr main;
- CFragConnectionID connectionID;
- Str255 errName;
- Str255 pName;
- char cName[64];
- const char* libName;
-
- /*
- * Algorithm: The "name" passed in could be either a shared
- * library name that we should look for in the normal library
- * search paths, or a full path name to a specific library on
- * disk. Since the full path will always contain a ":"
- * (shortest possible path is "Volume:File"), and since a
- * library name can not contain a ":", we can test for the
- * presence of a ":" to see which type of library we should load.
- * or its a full UNIX path which we for now assume is Java
- * enumerating all the paths (see below)
- */
- if (strchr(name, PR_PATH_SEPARATOR) == NULL)
- {
- if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL)
- {
- /*
- * The name did not contain a ":", so it must be a
- * library name. Convert the name to a Pascal string
- * and try to find the library.
- */
- }
- else
- {
- /* name contained a "/" which means we need to suck off the last part */
- /* of the path and pass that on the NSGetSharedLibrary */
- /* this may not be what we really want to do .. because Java could */
- /* be iterating through the whole LD path, and we'll find it if it's */
- /* anywhere on that path -- it appears that's what UNIX and the PC do */
- /* too...so we'll emulate but it could be wrong. */
- name = strrchr(name, PR_DIRECTORY_SEPARATOR) + 1;
- }
-
- PStrFromCStr(name, pName);
-
- err = NSGetSharedLibrary(pName, &connectionID, &main);
- if (err != noErr)
- goto unlock;
-
- libName = name;
- }
- else
- {
- /*
- * The name did contain a ":", so it must be a full path name.
- * Now we have to do a lot of work to convert the path name to
- * an FSSpec (silly, since we were probably just called from the
- * MacFE plug-in code that already knew the FSSpec and converted
- * it to a full path just to pass to us). First we copy out the
- * volume name (the text leading up to the first ":"); then we
- * separate the file name (the text following the last ":") from
- * rest of the path. After converting the strings to Pascal
- * format we can call GetCatInfo to get the parent directory ID
- * of the file, and then (finally) make an FSSpec and call
- * GetDiskFragment.
- */
- char* cMacPath = NULL;
- char* cFileName = NULL;
- char* position = NULL;
- CInfoPBRec pb;
- FSSpec fileSpec;
- PRUint32 index;
-
- /* Copy the name: we'll change it */
- cMacPath = strdup(name);
- if (cMacPath == NULL)
- goto unlock;
-
- /* First, get the vRefNum */
- position = strchr(cMacPath, PR_PATH_SEPARATOR);
- if ((position == cMacPath) || (position == NULL))
- fileSpec.vRefNum = 0; /* Use application relative searching */
- else
- {
- char cVolName[32];
- memset(cVolName, 0, sizeof(cVolName));
- strncpy(cVolName, cMacPath, position-cMacPath);
- fileSpec.vRefNum = GetVolumeRefNumFromName(cVolName);
- }
-
- /* Next, break the path and file name apart */
- index = 0;
- while (cMacPath[index] != 0)
- index++;
- while (cMacPath[index] != PR_PATH_SEPARATOR && index > 0)
- index--;
- if (index == 0 || index == strlen(cMacPath))
- {
- PR_DELETE(cMacPath);
- goto unlock;
- }
- cMacPath[index] = 0;
- cFileName = &(cMacPath[index + 1]);
-
- /* Convert the path and name into Pascal strings */
- strcpy((char*) &pName, cMacPath);
- c2pstr((char*) &pName);
- strcpy((char*) &fileSpec.name, cFileName);
- c2pstr((char*) &fileSpec.name);
- strcpy(cName, cFileName);
- PR_DELETE(cMacPath);
- cMacPath = NULL;
-
- /* Now we can look up the path on the volume */
- pb.dirInfo.ioNamePtr = pName;
- pb.dirInfo.ioVRefNum = fileSpec.vRefNum;
- pb.dirInfo.ioDrDirID = 0;
- pb.dirInfo.ioFDirIndex = 0;
- err = PBGetCatInfoSync(&pb);
- if (err != noErr)
- goto unlock;
- fileSpec.parID = pb.dirInfo.ioDrDirID;
-
- /* Finally, try to load the library */
- err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name,
- kLoadCFrag, &connectionID, &main, errName);
-
- libName = cName;
- if (err != noErr)
- goto unlock;
- }
-
- lm->name = strdup(libName);
- lm->dlh = connectionID;
- lm->next = pr_loadmap;
- pr_loadmap = lm;
+ OSErr err;
+ Ptr main;
+ CFragConnectionID connectionID;
+ Str255 errName;
+ Str255 pName;
+ char cName[64];
+ const char* libName;
+
+ /*
+ * Algorithm: The "name" passed in could be either a shared
+ * library name that we should look for in the normal library
+ * search paths, or a full path name to a specific library on
+ * disk. Since the full path will always contain a ":"
+ * (shortest possible path is "Volume:File"), and since a
+ * library name can not contain a ":", we can test for the
+ * presence of a ":" to see which type of library we should load.
+ * or its a full UNIX path which we for now assume is Java
+ * enumerating all the paths (see below)
+ */
+ if (strchr(name, PR_PATH_SEPARATOR) == NULL)
+ {
+ if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL)
+ {
+ /*
+ * The name did not contain a ":", so it must be a
+ * library name. Convert the name to a Pascal string
+ * and try to find the library.
+ */
+ }
+ else
+ {
+ /* name contained a "/" which means we need to suck off the last part */
+ /* of the path and pass that on the NSGetSharedLibrary */
+ /* this may not be what we really want to do .. because Java could */
+ /* be iterating through the whole LD path, and we'll find it if it's */
+ /* anywhere on that path -- it appears that's what UNIX and the PC do */
+ /* too...so we'll emulate but it could be wrong. */
+ name = strrchr(name, PR_DIRECTORY_SEPARATOR) + 1;
+ }
+
+ PStrFromCStr(name, pName);
+
+ err = NSGetSharedLibrary(pName, &connectionID, &main);
+ if (err != noErr)
+ goto unlock;
+
+ libName = name;
+ }
+ else
+ {
+ /*
+ * The name did contain a ":", so it must be a full path name.
+ * Now we have to do a lot of work to convert the path name to
+ * an FSSpec (silly, since we were probably just called from the
+ * MacFE plug-in code that already knew the FSSpec and converted
+ * it to a full path just to pass to us). First we copy out the
+ * volume name (the text leading up to the first ":"); then we
+ * separate the file name (the text following the last ":") from
+ * rest of the path. After converting the strings to Pascal
+ * format we can call GetCatInfo to get the parent directory ID
+ * of the file, and then (finally) make an FSSpec and call
+ * GetDiskFragment.
+ */
+ char* cMacPath = NULL;
+ char* cFileName = NULL;
+ char* position = NULL;
+ CInfoPBRec pb;
+ FSSpec fileSpec;
+ PRUint32 index;
+
+ /* Copy the name: we'll change it */
+ cMacPath = strdup(name);
+ if (cMacPath == NULL)
+ goto unlock;
+
+ /* First, get the vRefNum */
+ position = strchr(cMacPath, PR_PATH_SEPARATOR);
+ if ((position == cMacPath) || (position == NULL))
+ fileSpec.vRefNum = 0; /* Use application relative searching */
+ else
+ {
+ char cVolName[32];
+ memset(cVolName, 0, sizeof(cVolName));
+ strncpy(cVolName, cMacPath, position-cMacPath);
+ fileSpec.vRefNum = GetVolumeRefNumFromName(cVolName);
+ }
+
+ /* Next, break the path and file name apart */
+ index = 0;
+ while (cMacPath[index] != 0)
+ index++;
+ while (cMacPath[index] != PR_PATH_SEPARATOR && index > 0)
+ index--;
+ if (index == 0 || index == strlen(cMacPath))
+ {
+ PR_DELETE(cMacPath);
+ goto unlock;
+ }
+ cMacPath[index] = 0;
+ cFileName = &(cMacPath[index + 1]);
+
+ /* Convert the path and name into Pascal strings */
+ strcpy((char*) &pName, cMacPath);
+ c2pstr((char*) &pName);
+ strcpy((char*) &fileSpec.name, cFileName);
+ c2pstr((char*) &fileSpec.name);
+ strcpy(cName, cFileName);
+ PR_DELETE(cMacPath);
+ cMacPath = NULL;
+
+ /* Now we can look up the path on the volume */
+ pb.dirInfo.ioNamePtr = pName;
+ pb.dirInfo.ioVRefNum = fileSpec.vRefNum;
+ pb.dirInfo.ioDrDirID = 0;
+ pb.dirInfo.ioFDirIndex = 0;
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto unlock;
+ fileSpec.parID = pb.dirInfo.ioDrDirID;
+
+ /* Finally, try to load the library */
+ err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name,
+ kLoadCFrag, &connectionID, &main, errName);
+
+ libName = cName;
+ if (err != noErr)
+ goto unlock;
+ }
+
+ lm->name = strdup(libName);
+ lm->dlh = connectionID;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
}
#elif defined(XP_MAC) && !GENERATINGCFM
{
@@ -631,14 +638,10 @@ PR_LoadLibrary(const char *name)
#ifdef HAVE_DLL
{
#if defined(USE_DLFCN)
- void *h = dlopen(name, RTLD_LAZY);
+ void *h = dlopen(name, RTLD_LAZY);
#elif defined(USE_HPSHL)
- /*
- * Shared libraries built using aCC cannot be dynamically loaded
- * with BIND_DEFERRED, so we have to use the BIND_IMMEDIATE flag.
- */
- shl_t h = shl_load(name, BIND_IMMEDIATE | DYNAMIC_PATH, 0L);
-#elif defined(USE_RLD)
+ shl_t h = shl_load(name, BIND_DEFERRED | DYNAMIC_PATH, 0L);
+#elif defined(RHAPSODY)
NSObjectFileImage ofi;
NSModule h = NULL;
if (NSCreateObjectFileImageFromFile(name, &ofi)
@@ -648,20 +651,20 @@ PR_LoadLibrary(const char *name)
#else
#error Configuration error
#endif
- if (!h) {
- PR_DELETE(lm);
- goto unlock;
- }
- lm->name = strdup(name);
- lm->dlh = h;
- lm->next = pr_loadmap;
- pr_loadmap = lm;
+ if (!h) {
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
}
#endif /* HAVE_DLL */
#endif /* XP_UNIX */
lm->refCount = 1;
- result = lm; /* success */
+ result = lm; /* success */
PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));
unlock:
@@ -700,10 +703,10 @@ PR_UnloadLibrary(PRLibrary *lib)
PR_EnterMonitor(pr_linker_lock);
if (--lib->refCount > 0) {
- PR_LOG(_pr_linker_lm, PR_LOG_MIN,
- ("%s decr => %d",
- lib->name, lib->refCount));
- goto done;
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s decr => %d",
+ lib->name, lib->refCount));
+ goto done;
}
#ifdef XP_UNIX
#ifdef HAVE_DLL
@@ -711,7 +714,7 @@ PR_UnloadLibrary(PRLibrary *lib)
result = dlclose(lib->dlh);
#elif defined(USE_HPSHL)
result = shl_unload(lib->dlh);
-#elif defined(USE_RLD)
+#elif defined(RHAPSODY)
result = NSUnLinkModule(lib->dlh, FALSE);
#else
#error Configuration error
@@ -727,23 +730,23 @@ PR_UnloadLibrary(PRLibrary *lib)
#if defined(XP_MAC) && GENERATINGCFM
/* Close the connection */
- CloseConnection(&(lib->dlh));
+ CloseConnection(&(lib->dlh));
#endif
/* unlink from library search list */
if (pr_loadmap == lib)
- pr_loadmap = pr_loadmap->next;
+ pr_loadmap = pr_loadmap->next;
else if (pr_loadmap != NULL) {
- PRLibrary* prev = pr_loadmap;
- PRLibrary* next = pr_loadmap->next;
- while (next != NULL) {
- if (next == lib) {
- prev->next = next->next;
- goto freeLib;
- }
- prev = next;
- next = next->next;
- }
+ PRLibrary* prev = pr_loadmap;
+ PRLibrary* next = pr_loadmap->next;
+ while (next != NULL) {
+ if (next == lib) {
+ prev->next = next->next;
+ goto freeLib;
+ }
+ prev = next;
+ next = next->next;
+ }
/*
* fail (the library is not on the _pr_loadmap list),
* but don't wipe out an error from dlclose/shl_unload.
@@ -780,12 +783,12 @@ pr_FindSymbolInLib(PRLibrary *lm, const char *name)
void *f = NULL;
if (lm->staticTable != NULL) {
- const PRStaticLinkTable* tp;
- for (tp = lm->staticTable; tp->name; tp++) {
- if (strcmp(name, tp->name) == 0) {
- return (void*) tp->fp;
- }
- }
+ const PRStaticLinkTable* tp;
+ for (tp = lm->staticTable; tp->name; tp++) {
+ if (strcmp(name, tp->name) == 0) {
+ return (void*) tp->fp;
+ }
+ }
/*
** If the symbol was not found in the static table then check if
** the symbol was exported in the DLL... Win16 only!!
@@ -806,14 +809,14 @@ pr_FindSymbolInLib(PRLibrary *lm, const char *name)
#ifdef XP_MAC
{
- Ptr symAddr;
- CFragSymbolClass symClass;
- Str255 pName;
-
- PStrFromCStr(name, pName);
-
- f = (NSFindSymbol(lm->dlh, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
- }
+ Ptr symAddr;
+ CFragSymbolClass symClass;
+ Str255 pName;
+
+ PStrFromCStr(name, pName);
+
+ f = (NSFindSymbol(lm->dlh, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
+ }
#endif /* XP_MAC */
#ifdef XP_UNIX
@@ -821,9 +824,10 @@ pr_FindSymbolInLib(PRLibrary *lm, const char *name)
#ifdef USE_DLFCN
f = dlsym(lm->dlh, name);
#elif defined(USE_HPSHL)
- if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1)
- f = NULL;
-#elif defined(USE_RLD)
+ if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
+ f = NULL;
+ }
+#elif defined(RHAPSODY)
f = NSAddressOfSymbol(NSLookupAndBindSymbol(name));
#endif
#endif /* HAVE_DLL */
@@ -842,7 +846,7 @@ PR_IMPLEMENT(void*)
PR_FindSymbol(PRLibrary *lib, const char *raw_name)
{
void *f = NULL;
-#if defined(SUNOS4) || defined(WIN16)
+#if defined(NEED_LEADING_UNDERSCORE)
char *name;
#else
const char *name;
@@ -850,7 +854,7 @@ PR_FindSymbol(PRLibrary *lib, const char *raw_name)
/*
** Mangle the raw symbol name in any way that is platform specific.
*/
-#if defined(SUNOS4) || defined(RHAPSODY)
+#if defined(NEED_LEADING_UNDERSCORE)
/* Need a leading _ */
name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
@@ -860,11 +864,6 @@ PR_FindSymbol(PRLibrary *lib, const char *raw_name)
** figure.
*/
name = raw_name;
-#elif defined(WIN16)
- /*
- ** Win16. symbols have a leading '_'
- */
- name = PR_smprintf("_%s", raw_name);
#else
name = raw_name;
#endif
@@ -873,7 +872,7 @@ PR_FindSymbol(PRLibrary *lib, const char *raw_name)
PR_ASSERT(lib != NULL);
f = pr_FindSymbolInLib(lib, name);
-#if defined(SUNOS4) || defined(WIN16)
+#if defined(NEED_LEADING_UNDERSCORE)
PR_smprintf_free(name);
#endif
@@ -885,7 +884,7 @@ PR_IMPLEMENT(void*)
PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
{
void *f = NULL;
-#if defined(SUNOS4) || defined(WIN16)
+#if defined(NEED_LEADING_UNDERSCORE)
char *name;
#else
const char *name;
@@ -895,7 +894,7 @@ PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
/*
** Mangle the raw symbol name in any way that is platform specific.
*/
-#if defined(SUNOS4) || defined(RHAPSODY)
+#if defined(NEED_LEADING_UNDERSCORE)
/* Need a leading _ */
name = PR_smprintf("_%s", raw_name);
#elif defined(AIX)
@@ -905,30 +904,25 @@ PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
** figure.
*/
name = raw_name;
-#elif defined(WIN16)
- /*
- ** Win16. symbols have a leading '_'
- */
- name = PR_smprintf("_%s", raw_name);
#else
name = raw_name;
#endif
PR_EnterMonitor(pr_linker_lock);
- /* search all libraries */
- for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
- f = pr_FindSymbolInLib(lm, name);
- if (f != NULL) {
- *lib = lm;
- lm->refCount++;
- PR_LOG(_pr_linker_lm, PR_LOG_MIN,
- ("%s incr => %d (for %s)",
- lm->name, lm->refCount, name));
- break;
- }
- }
-#if defined(SUNOS4) || defined(WIN16)
+ /* search all libraries */
+ for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
+ f = pr_FindSymbolInLib(lm, name);
+ if (f != NULL) {
+ *lib = lm;
+ lm->refCount++;
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s incr => %d (for %s)",
+ lm->name, lm->refCount, name));
+ break;
+ }
+ }
+#if defined(NEED_LEADING_UNDERSCORE)
PR_smprintf_free(name);
#endif
@@ -970,7 +964,7 @@ PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt)
lm->next = pr_loadmap;
pr_loadmap = lm;
- result = lm; /* success */
+ result = lm; /* success */
PR_ASSERT(lm->refCount == 1);
unlock:
PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name));
diff --git a/pr/src/malloc/prmalloc.c b/pr/src/malloc/prmalloc.c
index dc3b3983..61f50023 100644
--- a/pr/src/malloc/prmalloc.c
+++ b/pr/src/malloc/prmalloc.c
@@ -366,7 +366,7 @@ map_pages(int pages, int update)
static int
extend_page_directory(u_long index)
{
- struct pginfo **new,**old;
+ struct pginfo **young, **old;
int i;
TRACE(("%6d E %lu\n",malloc_event++,index));
@@ -377,13 +377,13 @@ extend_page_directory(u_long index)
i += 2;
/* Get new pages, if you used this much mem you don't care :-) */
- new = (struct pginfo**) map_pages(i,0);
- if (!new)
+ young = (struct pginfo**) map_pages(i,0);
+ if (!young)
return 0;
/* Copy the old stuff */
- memset(new, 0, i * malloc_pagesize);
- memcpy(new, page_dir,
+ memset(young, 0, i * malloc_pagesize);
+ memcpy(young, page_dir,
malloc_ninfo * sizeof *page_dir);
/* register the new size */
@@ -391,10 +391,10 @@ extend_page_directory(u_long index)
/* swap the pointers */
old = page_dir;
- page_dir = new;
+ page_dir = young;
/* Mark the pages */
- index = ((u_long)new >> malloc_pageshift) - malloc_origo;
+ index = ((u_long)young >> malloc_pageshift) - malloc_origo;
page_dir[index] = MALLOC_FIRST;
while (--i) {
page_dir[++index] = MALLOC_FOLLOW;
@@ -590,7 +590,7 @@ static void *malloc_pages(size_t size)
}
if (delay_free) {
if (!px)
- px = delay_free;
+ px = (struct pgfree*)delay_free;
else
_PR_UnlockedFree(delay_free);
}
@@ -626,7 +626,7 @@ malloc_make_chunks(int bits)
bp->shift = bits;
bp->total = bp->free = malloc_pagesize >> bits;
bp->next = page_dir[bits];
- bp->page = pp;
+ bp->page = (char*)pp;
i = set_pgdir(pp,bp);
if (!i)
return 0;
@@ -944,7 +944,7 @@ free_pages(char *ptr, u_long page, int index, struct pginfo *info)
/* add to free-list */
if (!px)
- px = _PR_UnlockedMalloc(sizeof *pt);
+ px = (struct pgfree*)_PR_UnlockedMalloc(sizeof *pt);
/* XXX check success */
px->page = ptr;
px->end = tail;
@@ -1148,7 +1148,7 @@ void _PR_UnlockedFree(void *ptr)
/* handle as page-allocation or chunk allocation */
info = page_dir[index];
if (info < MALLOC_MAGIC)
- free_pages(ptr,page,index,info);
+ free_pages((char*)ptr, page, index, info);
else
free_bytes(ptr,page,index,info);
return;
diff --git a/pr/src/malloc/prmem.c b/pr/src/malloc/prmem.c
index c9319216..c3fdcebc 100644
--- a/pr/src/malloc/prmem.c
+++ b/pr/src/malloc/prmem.c
@@ -116,6 +116,26 @@ static pthread_mutex_t _PR_MD_malloc_crustylock;
#else /* _PR_PTHREADS */
static _MDLock _PR_MD_malloc_crustylock;
+#ifdef IRIX
+#define _PR_Lock_Malloc() { \
+ PRIntn _is; \
+ if(PR_TRUE == _PR_malloc_initialised) { \
+ if (_PR_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSOFF(_is); \
+ _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
+ }
+
+#define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \
+ _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
+ if (_PR_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSON(_is); \
+ } \
+ }
+#else /* IRIX */
#define _PR_Lock_Malloc() { \
PRIntn _is; \
if(PR_TRUE == _PR_malloc_initialised) { \
@@ -134,6 +154,7 @@ static _MDLock _PR_MD_malloc_crustylock;
_PR_INTSON(_is); \
} \
}
+#endif /* IRIX */
#endif /* _PR_PTHREADS */
PR_IMPLEMENT(PRStatus) _PR_MallocInit(void)
diff --git a/pr/src/md/mac/macio.c b/pr/src/md/mac/macio.c
index ae5aa2ff..8a1474f4 100644
--- a/pr/src/md/mac/macio.c
+++ b/pr/src/md/mac/macio.c
@@ -55,12 +55,12 @@ static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr)
thread->md.notifyPending = PR_TRUE;
return;
}
- _PR_SET_INTSOFF(1);
+ _PR_MD_SET_INTSOFF(1);
thread->md.osErrCode = noErr;
DoneWaitingOnThisThread(thread);
- _PR_SET_INTSOFF(0);
+ _PR_MD_SET_INTSOFF(0);
}
@@ -393,7 +393,7 @@ ErrorExit:
/* _MD_CLOSE_FILE, _MD_READ, _MD_WRITE, _MD_GET_FILE_ERROR are defined in _macos.h */
-PRInt32 _MD_LSeek(PRFileDesc *fd, PRInt32 offset, int how)
+PRInt32 _MD_LSeek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
{
PRInt32 refNum = fd->secret->md.osfd;
OSErr err = noErr;
diff --git a/pr/src/md/mac/macsockclient.c b/pr/src/md/mac/macsockclient.c
index 3ae9b0e5..93d3b100 100644
--- a/pr/src/md/mac/macsockclient.c
+++ b/pr/src/md/mac/macsockclient.c
@@ -457,90 +457,75 @@ ErrorExit:
PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
- PRPollDesc *pd, *epd;
- PRInt32 n;
-
+ PRInt32 osfd;
fd_set rd, wt, ex;
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRInt32 ready, maxfd = -1;
+ PRInt16 in_flags, out_flags;
struct timeval tv, *tvp = NULL;
- int maxfd = -1;
FD_ZERO(&rd);
FD_ZERO(&wt);
FD_ZERO(&ex);
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
-
- if (NULL == bottom) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
-
- if (osfd > maxfd) {
- maxfd = osfd;
- }
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &rd);
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &wt);
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &ex);
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ if (NULL == pd->fd) continue;
+
+ in_flags = (bottom->methods->poll)(pd->fd, pd->in_flags, &pd->out_flags);
+ if (0 != (in_flags & pd->out_flags)) ready += 1;
+ else
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ osfd = bottom->secret->md.osfd;
+
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags & PR_POLL_READ) FD_SET(osfd, &rd);
+ if (in_flags & PR_POLL_WRITE) FD_SET(osfd, &wt);
+ if (in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
}
}
- if (timeout != PR_INTERVAL_NO_TIMEOUT) {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
- tvp = &tv;
- }
+
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = timeout / ticksPerSecond;
+ tv.tv_usec = timeout - (ticksPerSecond * tv.tv_sec);
+ tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond;
+ tvp = &tv;
+ }
- n = select(maxfd + 1, &rd, &wt, &ex, tvp);
+ ready = select(maxfd + 1, &rd, &wt, &ex, tvp);
- if (n > 0) {
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRInt16 out_flags = 0;
- PRFileDesc *bottom = pd->fd;
-
- if (NULL == bottom) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ out_flags = 0;
+ in_flags = pd->in_flags;
+
+ if ((NULL == pd->fd) || (0 == in_flags)) continue;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
osfd = bottom->secret->md.osfd;
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pd->out_flags = out_flags;
- if (out_flags) {
- n++;
- }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+ else if (FD_ISSET(osfd, &rd) || FD_ISSET(osfd, &wt))
+ out_flags = pd->in_flags & (PR_POLL_READ | PR_POLL_WRITE);
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
}
/*
Can't do this assert because MacSock returns write fds even if we did not
set it in the original write fd set.
*/
- /*PR_ASSERT(n > 0);*/
- } else
- PR_ASSERT(n == 0);
+ /*PR_ASSERT(ready > 0);*/
+ }
+ else PR_ASSERT(ready == 0);
- return n;
+ return ready;
}
int _MD_mac_get_nonblocking_connect_error(int osfd)
diff --git a/pr/src/md/mac/macsockotpt.c b/pr/src/md/mac/macsockotpt.c
index 04217a74..4af516cc 100644
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -22,28 +22,28 @@
#include <Gestalt.h>
/*
- Since Apple put out new headers without
- putting in a way to test for them, we found some random symbol which
- isn't defined in the "1.1" headers.
+ Since Apple put out new headers without
+ putting in a way to test for them, we found some random symbol which
+ isn't defined in the "1.1" headers.
*/
#include <OpenTransport.h>
#ifdef kOTInvalidStreamRef
/* old */
-#define GESTALT_OPEN_TPT_PRESENT gestaltOpenTptPresent
-#define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresent
+#define GESTALT_OPEN_TPT_PRESENT gestaltOpenTptPresent
+#define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresent
#else
/* new */
-#define GESTALT_OPEN_TPT_PRESENT gestaltOpenTptPresentMask
-#define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresentMask
+#define GESTALT_OPEN_TPT_PRESENT gestaltOpenTptPresentMask
+#define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresentMask
#endif
-#include <OpenTptInternet.h> // All the internet typedefs
+#include <OpenTptInternet.h> // All the internet typedefs
#include "macsocket.h"
#include "primpl.h"
typedef enum SndRcvOpCode {
kSTREAM_SEND,
- kSTREAM_RECEIVE ,
+ kSTREAM_RECEIVE ,
kDGRAM_SEND,
kDGRAM_RECEIVE
} SndRcvOpCode;
@@ -52,7 +52,7 @@ typedef enum SndRcvOpCode {
static InetSvcRef sSvcRef;
static pascal void NotifierRoutine(void * contextPtr, OTEventCode code,
- OTResult result, void * cookie);
+ OTResult result, void * cookie);
static PRBool GetState(EndpointRef endpoint, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
@@ -61,130 +61,130 @@ extern void DoneWaitingOnThisThread(PRThread *thread);
void _MD_InitNetAccess()
{
- OSErr err;
- OSStatus errOT;
- PRBool hasOTTCPIP = PR_FALSE;
- PRBool hasOT = PR_FALSE;
- long gestaltResult;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- err = Gestalt(gestaltOpenTpt, &gestaltResult);
- if (err == noErr)
- if (gestaltResult & GESTALT_OPEN_TPT_PRESENT)
- hasOT = PR_TRUE;
-
- if (hasOT)
- if (gestaltResult & GESTALT_OPEN_TPT_TCP_PRESENT)
- hasOTTCPIP = PR_TRUE;
-
- PR_ASSERT(hasOTTCPIP == PR_TRUE);
-
- errOT = InitOpenTransport();
- PR_ASSERT(err == kOTNoError);
-
- sSvcRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &errOT);
- if (errOT != kOTNoError) return; /* no network -- oh well */
- PR_ASSERT((sSvcRef != NULL) && (errOT == kOTNoError));
+ OSErr err;
+ OSStatus errOT;
+ PRBool hasOTTCPIP = PR_FALSE;
+ PRBool hasOT = PR_FALSE;
+ long gestaltResult;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ err = Gestalt(gestaltOpenTpt, &gestaltResult);
+ if (err == noErr)
+ if (gestaltResult & GESTALT_OPEN_TPT_PRESENT)
+ hasOT = PR_TRUE;
+
+ if (hasOT)
+ if (gestaltResult & GESTALT_OPEN_TPT_TCP_PRESENT)
+ hasOTTCPIP = PR_TRUE;
+
+ PR_ASSERT(hasOTTCPIP == PR_TRUE);
+
+ errOT = InitOpenTransport();
+ PR_ASSERT(err == kOTNoError);
+
+ sSvcRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &errOT);
+ if (errOT != kOTNoError) return; /* no network -- oh well */
+ PR_ASSERT((sSvcRef != NULL) && (errOT == kOTNoError));
/* Install notify function for DNR Address To String completion */
- errOT = OTInstallNotifier(sSvcRef, NotifierRoutine, me);
- PR_ASSERT(errOT == kOTNoError);
+ errOT = OTInstallNotifier(sSvcRef, NotifierRoutine, me);
+ PR_ASSERT(errOT == kOTNoError);
/* Put us into async mode */
- errOT = OTSetAsynchronous(sSvcRef);
- PR_ASSERT(errOT == kOTNoError);
+ errOT = OTSetAsynchronous(sSvcRef);
+ PR_ASSERT(errOT == kOTNoError);
/* XXX Does not handle absence of open tpt and tcp yet! */
}
static void macsock_map_error(OSStatus err)
{
- _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
-
- if (IsEError(err) || (err >= EPERM && err <= ELASTERRNO)) {
- switch (IsEError(err) ? OSStatus2E(err) : err) {
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case EADDRNOTAVAIL:
- PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
- break;
- case EINPROGRESS:
- PR_SetError(PR_IN_PROGRESS_ERROR, err);
- break;
- case EWOULDBLOCK:
- case EAGAIN:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- case ENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case ETIMEDOUT:
- PR_SetError(PR_IO_TIMEOUT_ERROR, err);
- break;
- case ECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case ENETUNREACH:
- PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
- break;
- case EADDRINUSE:
- PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
- break;
- case EFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
- case EINTR:
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
- break;
- case EINVAL:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
- break;
- case EIO:
- PR_SetError(PR_IO_ERROR, err);
- break;
- case ENOENT:
- PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
- break;
- case ENXIO:
- PR_SetError(PR_IO_ERROR, err);
- break;
- case EPROTOTYPE:
- PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
- break;
- case EOPNOTSUPP:
- PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
- } else {
- PR_ASSERT(IsXTIError(err));
- switch (err) {
- case kOTNoDataErr:
- case kOTFlowErr:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- default:
- PR_ASSERT(0);
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
- }
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+
+ if (IsEError(err) || (err >= EPERM && err <= ELASTERRNO)) {
+ switch (IsEError(err) ? OSStatus2E(err) : err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EINPROGRESS:
+ PR_SetError(PR_IN_PROGRESS_ERROR, err);
+ break;
+ case EWOULDBLOCK:
+ case EAGAIN:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case ENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EPROTOTYPE:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+ } else {
+ PR_ASSERT(IsXTIError(err));
+ switch (err) {
+ case kOTNoDataErr:
+ case kOTFlowErr:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ default:
+ PR_ASSERT(0);
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+ }
}
static void PrepareThreadForAsyncIO(PRThread *thread, EndpointRef endpoint, PRInt32 osfd)
{
- OSStatus err;
+ OSStatus err;
thread->io_pending = PR_TRUE;
thread->io_fd = osfd;
thread->md.osErrCode = noErr;
- OTRemoveNotifier(endpoint);
- err = OTInstallNotifier(endpoint, NotifierRoutine, thread);
- PR_ASSERT(err == kOTNoError);
+ OTRemoveNotifier(endpoint);
+ err = OTInstallNotifier(endpoint, NotifierRoutine, thread);
+ PR_ASSERT(err == kOTNoError);
}
// Notification routine
@@ -192,96 +192,96 @@ static void PrepareThreadForAsyncIO(PRThread *thread, EndpointRef endpoint, PRIn
// A5 is OK. Cannot allocate memory here
pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
{
- PRThread * thread = (PRThread *) contextPtr;
- _PRCPU *cpu = _PR_MD_CURRENT_CPU();
-
- switch (code)
- {
+ PRThread * thread = (PRThread *) contextPtr;
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+
+ switch (code)
+ {
// Async Completion Event
- case T_OPENCOMPLETE:
- case T_BINDCOMPLETE:
- case T_UNBINDCOMPLETE:
- case T_GETPROTADDRCOMPLETE:
- case T_ACCEPTCOMPLETE:
+ case T_OPENCOMPLETE:
+ case T_BINDCOMPLETE:
+ case T_UNBINDCOMPLETE:
+ case T_GETPROTADDRCOMPLETE:
+ case T_ACCEPTCOMPLETE:
// Connect callback
- case T_CONNECT:
+ case T_CONNECT:
// Standard or expedited data is available
- case T_DATA:
- case T_EXDATA:
+ case T_DATA:
+ case T_EXDATA:
// Standard or expedited data Flow control lifted
- case T_GODATA:
- case T_GOEXDATA:
+ case T_GODATA:
+ case T_GOEXDATA:
// Asynchronous Listen Event
- case T_LISTEN:
+ case T_LISTEN:
// DNR String To Address Complete Event
- case T_DNRSTRINGTOADDRCOMPLETE:
+ case T_DNRSTRINGTOADDRCOMPLETE:
// Option Management Request Complete Event
- case T_OPTMGMTCOMPLETE:
- thread->md.osErrCode = result;
- thread->md.cookie = cookie;
- if (_PR_MD_GET_INTSOFF()) {
- cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- thread->md.notifyPending = PR_TRUE;
- return;
- }
- DoneWaitingOnThisThread(thread);
- break;
+ case T_OPTMGMTCOMPLETE:
+ thread->md.osErrCode = result;
+ thread->md.cookie = cookie;
+ if (_PR_MD_GET_INTSOFF()) {
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ thread->md.notifyPending = PR_TRUE;
+ return;
+ }
+ DoneWaitingOnThisThread(thread);
+ break;
// T_ORDREL orderly release is available; nothing to do
- case T_ORDREL:
- break;
+ case T_ORDREL:
+ break;
// T_PASSCON; nothing to do
- case T_PASSCON:
- break;
+ case T_PASSCON:
+ break;
// T_DISCONNECT; disconnect is available; nothing to do
- case T_DISCONNECT:
- break;
+ case T_DISCONNECT:
+ break;
// UDP Send error; clear the error
- case T_UDERR:
- (void) OTRcvUDErr((EndpointRef) cookie, NULL);
- break;
-
- default:
- PR_ASSERT(0);
- break;
- }
+ case T_UDERR:
+ (void) OTRcvUDErr((EndpointRef) cookie, NULL);
+ break;
+
+ default:
+ PR_ASSERT(0);
+ break;
+ }
}
static OSErr CreateSocket(int type, EndpointRef *endpoint)
{
- OSStatus err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- switch (type){
- case SOCK_STREAM:
- err = OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL,
- NotifierRoutine, me);
- break;
- case SOCK_DGRAM:
- err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL,
- NotifierRoutine, me);
- break;
- }
- if (err != kOTNoError)
- goto ErrorExit;
+ OSStatus err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ switch (type){
+ case SOCK_STREAM:
+ err = OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL,
+ NotifierRoutine, me);
+ break;
+ case SOCK_DGRAM:
+ err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL,
+ NotifierRoutine, me);
+ break;
+ }
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- *endpoint = me->md.cookie;
- PR_ASSERT(*endpoint != NULL);
+ *endpoint = me->md.cookie;
+ PR_ASSERT(*endpoint != NULL);
- return kOTNoError;
+ return kOTNoError;
ErrorExit:
- return err;
+ return err;
}
@@ -291,52 +291,52 @@ ErrorExit:
// ENOBUFS - not enough space for another socket, or failure in socket creation routine
PRInt32 _MD_socket(int domain, int type, int protocol)
{
- OSStatus err;
- EndpointRef endpoint;
-
- // We only deal with internet domain
- if (domain != AF_INET) {
- err = kEPROTONOSUPPORTErr;
- goto ErrorExit;
- }
-
- // We only know about tcp & udp
- if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) {
- err = kEPROTONOSUPPORTErr;
- goto ErrorExit;
- }
-
- // Convert default types to specific types.
- if (protocol == 0) {
- if (type == SOCK_DGRAM)
- protocol = IPPROTO_UDP;
- else if (type == SOCK_STREAM)
- protocol = IPPROTO_TCP;
- }
-
- // Only support default protocol for tcp
- if ((type == SOCK_STREAM) && (protocol != IPPROTO_TCP)) {
- err = kEPROTONOSUPPORTErr;
- goto ErrorExit;
- }
-
- // Only support default protocol for udp
- if ((type == SOCK_DGRAM) && (protocol != IPPROTO_UDP)) {
- err = kEPROTONOSUPPORTErr;
- goto ErrorExit;
- }
-
- // Create a socket, we might run out of memory
- err = CreateSocket(type, &endpoint);
- if (err != kOTNoError)
- goto ErrorExit;
-
- PR_ASSERT((PRInt32)endpoint != -1);
-
- return ((PRInt32)endpoint);
+ OSStatus err;
+ EndpointRef endpoint;
+
+ // We only deal with internet domain
+ if (domain != AF_INET) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // We only know about tcp & udp
+ if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Convert default types to specific types.
+ if (protocol == 0) {
+ if (type == SOCK_DGRAM)
+ protocol = IPPROTO_UDP;
+ else if (type == SOCK_STREAM)
+ protocol = IPPROTO_TCP;
+ }
+
+ // Only support default protocol for tcp
+ if ((type == SOCK_STREAM) && (protocol != IPPROTO_TCP)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Only support default protocol for udp
+ if ((type == SOCK_DGRAM) && (protocol != IPPROTO_UDP)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Create a socket, we might run out of memory
+ err = CreateSocket(type, &endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT((PRInt32)endpoint != -1);
+
+ return ((PRInt32)endpoint);
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
@@ -345,28 +345,28 @@ ErrorExit:
// EFAULT -- bad address format
PRInt32 _MD_bind(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen)
{
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- TBind bindReq;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRUint32 retryCount = 0;
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (addr == NULL) {
- err = kEFAULTErr;
- goto ErrorExit;
- }
-
- // setup our request
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TBind bindReq;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRUint32 retryCount = 0;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ // setup our request
#if 0
- if ((addr->inet.port == 0) || (addr->inet.ip == 0))
- bindReq.addr.len = 0;
- else
+ if ((addr->inet.port == 0) || (addr->inet.ip == 0))
+ bindReq.addr.len = 0;
+ else
#endif
/*
* There seems to be a bug with OT ralted to OTBind failing with kOTNoAddressErr eventhough
@@ -375,36 +375,36 @@ PRInt32 _MD_bind(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen)
*/
TryAgain:
- bindReq.addr.len = addrlen;
-
- bindReq.addr.maxlen = addrlen;
- bindReq.addr.buf = (UInt8*) addr;
- bindReq.qlen = 1;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
+ bindReq.addr.len = addrlen;
+
+ bindReq.addr.maxlen = addrlen;
+ bindReq.addr.buf = (UInt8*) addr;
+ bindReq.qlen = 1;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
- err = OTBind(endpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- PR_ASSERT(me->md.cookie == NULL);
+ PR_ASSERT(me->md.cookie == NULL);
- return kOTNoError;
+ return kOTNoError;
ErrorExit:
- if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
- long finalTicks;
-
- Delay(100,&finalTicks);
- goto TryAgain;
- }
- macsock_map_error(err);
+ if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
+ long finalTicks;
+
+ Delay(100,&finalTicks);
+ goto TryAgain;
+ }
+ macsock_map_error(err);
return -1;
}
@@ -413,77 +413,77 @@ ErrorExit:
PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
{
#if 0
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- TBind bindReq;
- PRNetAddr addr;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- if (backlog == 0)
- backlog = 1;
-
- if (endpoint == NULL) {
- err = EBADF;
- goto ErrorExit;
- }
-
- addr.inet.port = addr.inet.ip = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TBind bindReq;
+ PRNetAddr addr;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (backlog == 0)
+ backlog = 1;
+
+ if (endpoint == NULL) {
+ err = EBADF;
+ goto ErrorExit;
+ }
+
+ addr.inet.port = addr.inet.ip = 0;
- bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr);
- bindReq.addr.len = 0;
- bindReq.addr.buf = (UInt8*) &addr;
- bindReq.qlen = 0;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &addr;
+ bindReq.qlen = 0;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
- err = OTGetProtAddress(endpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTGetProtAddress(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- PrepareThreadForAsyncIO(me, endpoint, osfd);
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
- err = OTUnbind(endpoint);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTUnbind(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- bindReq.qlen = backlog;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
+ bindReq.qlen = backlog;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
- err = OTBind(endpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- PR_ASSERT(me->md.cookie == NULL);
+ PR_ASSERT(me->md.cookie == NULL);
- return kOTNoError;
+ return kOTNoError;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
#endif
-#pragma unused (fd, backlog)
- return kOTNoError;
+#pragma unused (fd, backlog)
+ return kOTNoError;
}
@@ -491,514 +491,514 @@ ErrorExit:
// EBADF -- bad socket id
PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
{
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- TBind bindReq;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (addr == NULL) {
- err = kEFAULTErr;
- goto ErrorExit;
- }
-
-#if !defined(_PR_INET6)
- addr->inet.family = AF_INET;
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TBind bindReq;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+#if !defined(_PR_INET6)
+ addr->inet.family = AF_INET;
#endif
-
- PR_ASSERT(PR_NETADDR_SIZE(addr) >= (*addrlen));
+
+ PR_ASSERT(PR_NETADDR_SIZE(addr) >= (*addrlen));
- bindReq.addr.len = *addrlen;
- bindReq.addr.maxlen = *addrlen;
- bindReq.addr.buf = (UInt8*) addr;
- bindReq.qlen = 0;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
+ bindReq.addr.len = *addrlen;
+ bindReq.addr.maxlen = *addrlen;
+ bindReq.addr.buf = (UInt8*) addr;
+ bindReq.qlen = 0;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
- err = OTGetProtAddress(endpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTGetProtAddress(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
- PR_ASSERT(me->md.cookie == &bindReq);
+ PR_ASSERT(me->md.cookie == &bindReq);
- return kOTNoError;
+ return kOTNoError;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
{
- OSStatus err;
- PRInt32 osfd = fd->secret->md.osfd;
- EndpointRef endpoint = (EndpointRef) osfd;
- TOptMgmt cmd;
- TOption *opt;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- /*
- OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
- are equated to IP level and TCP level options respectively and hence we need to set
- the level correctly.
- */
- if (level == SOL_SOCKET) {
- if (optname == SO_REUSEADDR)
- level = IPPROTO_IP;
- else if (optname == SO_KEEPALIVE)
- level = INET_TCP;
- }
-
- opt = (TOption *)&optionBuffer[0];
- opt->len = sizeof(TOption);
- opt->level = level;
- opt->name = optname;
- opt->status = 0;
-
- cmd.opt.len = sizeof(TOption);
- cmd.opt.maxlen = sizeof(optionBuffer);
- cmd.opt.buf = (UInt8*)optionBuffer;
- cmd.flags = T_CURRENT;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTOptionManagement(endpoint, &cmd, &cmd);
- if (err != kOTNoError)
- goto ErrorExit;
-
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
- err = kEOPNOTSUPPErr;
- goto ErrorExit;
- }
-
- PR_ASSERT(opt->status == T_SUCCESS);
-
- switch (optname) {
- case SO_LINGER:
- *((t_linger*)optval) = *((t_linger*)&opt->value);
- *optlen = sizeof(t_linger);
- break;
- case SO_REUSEADDR:
- case TCP_NODELAY:
- case SO_KEEPALIVE:
- case SO_RCVBUF:
- case SO_SNDBUF:
- *((PRIntn*)optval) = *((PRIntn*)&opt->value);
- *optlen = sizeof(PRIntn);
- break;
- case IP_MULTICAST_LOOP:
- *((PRUint8*)optval) = *((PRIntn*)&opt->value);
- *optlen = sizeof(PRUint8);
- break;
- case IP_TTL:
- *((PRUintn*)optval) = *((PRUint8*)&opt->value);
- *optlen = sizeof(PRUintn);
- break;
- case IP_MULTICAST_TTL:
- *((PRUint8*)optval) = *((PRUint8*)&opt->value);
- *optlen = sizeof(PRUint8);
- break;
- case IP_ADD_MEMBERSHIP:
- case IP_DROP_MEMBERSHIP:
- {
- /* struct ip_mreq and TIPAddMulticast are the same size and optval
- is pointing to struct ip_mreq */
- *((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
- *optlen = sizeof(struct ip_mreq);
- break;
- }
- case IP_MULTICAST_IF:
- {
- *((PRUint32*)optval) = *((PRUint32*)&opt->value);
- *optlen = sizeof(PRUint32);
- break;
- }
- /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
- case TCP_MAXSEG:
- if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
- *((PRIntn*)optval) = *((PRIntn*)&opt->value);
- *optlen = sizeof(PRIntn);
- } else { /* it is IP_TOS */
- *((PRUintn*)optval) = *((PRUint8*)&opt->value);
- *optlen = sizeof(PRUintn);
- }
- break;
- default:
- PR_ASSERT(0);
- break;
- }
-
- return PR_SUCCESS;
+ OSStatus err;
+ PRInt32 osfd = fd->secret->md.osfd;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TOptMgmt cmd;
+ TOption *opt;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ /*
+ OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
+ are equated to IP level and TCP level options respectively and hence we need to set
+ the level correctly.
+ */
+ if (level == SOL_SOCKET) {
+ if (optname == SO_REUSEADDR)
+ level = IPPROTO_IP;
+ else if (optname == SO_KEEPALIVE)
+ level = INET_TCP;
+ }
+
+ opt = (TOption *)&optionBuffer[0];
+ opt->len = sizeof(TOption);
+ opt->level = level;
+ opt->name = optname;
+ opt->status = 0;
+
+ cmd.opt.len = sizeof(TOption);
+ cmd.opt.maxlen = sizeof(optionBuffer);
+ cmd.opt.buf = (UInt8*)optionBuffer;
+ cmd.flags = T_CURRENT;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTOptionManagement(endpoint, &cmd, &cmd);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ PR_ASSERT(opt->status == T_SUCCESS);
+
+ switch (optname) {
+ case SO_LINGER:
+ *((t_linger*)optval) = *((t_linger*)&opt->value);
+ *optlen = sizeof(t_linger);
+ break;
+ case SO_REUSEADDR:
+ case TCP_NODELAY:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ *((PRIntn*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRIntn);
+ break;
+ case IP_MULTICAST_LOOP:
+ *((PRUint8*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRUint8);
+ break;
+ case IP_TTL:
+ *((PRUintn*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUintn);
+ break;
+ case IP_MULTICAST_TTL:
+ *((PRUint8*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUint8);
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ /* struct ip_mreq and TIPAddMulticast are the same size and optval
+ is pointing to struct ip_mreq */
+ *((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
+ *optlen = sizeof(struct ip_mreq);
+ break;
+ }
+ case IP_MULTICAST_IF:
+ {
+ *((PRUint32*)optval) = *((PRUint32*)&opt->value);
+ *optlen = sizeof(PRUint32);
+ break;
+ }
+ /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
+ case TCP_MAXSEG:
+ if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
+ *((PRIntn*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRIntn);
+ } else { /* it is IP_TOS */
+ *((PRUintn*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUintn);
+ }
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ }
+
+ return PR_SUCCESS;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return PR_FAILURE;
}
PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
{
- OSStatus err;
- PRInt32 osfd = fd->secret->md.osfd;
- EndpointRef endpoint = (EndpointRef) osfd;
- TOptMgmt cmd;
- TOption *opt;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- /*
- OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
- are equated to IP level and TCP level options respectively and hence we need to set
- the level correctly.
- */
- if (level == SOL_SOCKET) {
- if (optname == SO_REUSEADDR)
- level = IPPROTO_IP;
- else if (optname == SO_KEEPALIVE)
- level = INET_TCP;
- }
-
- opt = (TOption *)&optionBuffer[0];
- opt->len = kOTOptionHeaderSize + optlen;
-
- /* special case adjustments for length follow */
- if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
- opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
- if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
- opt->len = kOTOneByteOptionSize;
- if (optname == IP_TOS && level == IPPROTO_IP)
- opt->len = kOTOneByteOptionSize;
-
- opt->level = level;
- opt->name = optname;
- opt->status = 0;
-
- cmd.opt.len = opt->len;
- cmd.opt.maxlen = sizeof(optionBuffer);
- cmd.opt.buf = (UInt8*)optionBuffer;
-
- optionBuffer[opt->len] = 0;
-
- cmd.flags = T_NEGOTIATE;
-
- switch (optname) {
- case SO_LINGER:
- *((t_linger*)&opt->value) = *((t_linger*)optval);
- break;
- case SO_REUSEADDR:
- case TCP_NODELAY:
- case SO_RCVBUF:
- case SO_SNDBUF:
- *((PRIntn*)&opt->value) = *((PRIntn*)optval);
- break;
- case IP_MULTICAST_LOOP:
- if (*optval != 0)
- opt->value[0] = T_YES;
- else
- opt->value[0] = T_NO;
- break;
- case SO_KEEPALIVE:
- {
- t_kpalive *kpalive = (t_kpalive *)&opt->value;
-
- kpalive->kp_onoff = *((long*)optval);
- kpalive->kp_timeout = 10; /* timeout in minutes */
- break;
- }
- case IP_TTL:
- *((unsigned char*)&opt->value) = *((PRUintn*)optval);
- break;
- case IP_MULTICAST_TTL:
- *((unsigned char*)&opt->value) = *optval;
- break;
- case IP_ADD_MEMBERSHIP:
- case IP_DROP_MEMBERSHIP:
- {
- /* struct ip_mreq and TIPAddMulticast are the same size and optval
- is pointing to struct ip_mreq */
- *((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
- break;
- }
- case IP_MULTICAST_IF:
- {
- *((PRUint32*)&opt->value) = *((PRUint32*)optval);
- break;
- }
- /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
- case TCP_MAXSEG:
- if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
- *((PRIntn*)&opt->value) = *((PRIntn*)optval);
- } else { /* it is IP_TOS */
- *((unsigned char*)&opt->value) = *((PRUintn*)optval);
- }
- break;
- default:
- PR_ASSERT(0);
- break;
- }
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTOptionManagement(endpoint, &cmd, &cmd);
- if (err != kOTNoError)
- goto ErrorExit;
-
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
- err = kEOPNOTSUPPErr;
- goto ErrorExit;
- }
-
- if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
- err = kEOPNOTSUPPErr;
- goto ErrorExit;
- }
-
- PR_ASSERT(opt->status == T_SUCCESS);
-
- return PR_SUCCESS;
+ OSStatus err;
+ PRInt32 osfd = fd->secret->md.osfd;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TOptMgmt cmd;
+ TOption *opt;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ /*
+ OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
+ are equated to IP level and TCP level options respectively and hence we need to set
+ the level correctly.
+ */
+ if (level == SOL_SOCKET) {
+ if (optname == SO_REUSEADDR)
+ level = IPPROTO_IP;
+ else if (optname == SO_KEEPALIVE)
+ level = INET_TCP;
+ }
+
+ opt = (TOption *)&optionBuffer[0];
+ opt->len = kOTOptionHeaderSize + optlen;
+
+ /* special case adjustments for length follow */
+ if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
+ opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
+ if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
+ opt->len = kOTOneByteOptionSize;
+ if (optname == IP_TOS && level == IPPROTO_IP)
+ opt->len = kOTOneByteOptionSize;
+
+ opt->level = level;
+ opt->name = optname;
+ opt->status = 0;
+
+ cmd.opt.len = opt->len;
+ cmd.opt.maxlen = sizeof(optionBuffer);
+ cmd.opt.buf = (UInt8*)optionBuffer;
+
+ optionBuffer[opt->len] = 0;
+
+ cmd.flags = T_NEGOTIATE;
+
+ switch (optname) {
+ case SO_LINGER:
+ *((t_linger*)&opt->value) = *((t_linger*)optval);
+ break;
+ case SO_REUSEADDR:
+ case TCP_NODELAY:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ *((PRIntn*)&opt->value) = *((PRIntn*)optval);
+ break;
+ case IP_MULTICAST_LOOP:
+ if (*optval != 0)
+ opt->value[0] = T_YES;
+ else
+ opt->value[0] = T_NO;
+ break;
+ case SO_KEEPALIVE:
+ {
+ t_kpalive *kpalive = (t_kpalive *)&opt->value;
+
+ kpalive->kp_onoff = *((long*)optval);
+ kpalive->kp_timeout = 10; /* timeout in minutes */
+ break;
+ }
+ case IP_TTL:
+ *((unsigned char*)&opt->value) = *((PRUintn*)optval);
+ break;
+ case IP_MULTICAST_TTL:
+ *((unsigned char*)&opt->value) = *optval;
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ /* struct ip_mreq and TIPAddMulticast are the same size and optval
+ is pointing to struct ip_mreq */
+ *((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
+ break;
+ }
+ case IP_MULTICAST_IF:
+ {
+ *((PRUint32*)&opt->value) = *((PRUint32*)optval);
+ break;
+ }
+ /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
+ case TCP_MAXSEG:
+ if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
+ *((PRIntn*)&opt->value) = *((PRIntn*)optval);
+ } else { /* it is IP_TOS */
+ *((unsigned char*)&opt->value) = *((PRUintn*)optval);
+ }
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ }
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTOptionManagement(endpoint, &cmd, &cmd);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ PR_ASSERT(opt->status == T_SUCCESS);
+
+ return PR_SUCCESS;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return PR_FAILURE;
}
PRInt32 _MD_socketavailable(PRFileDesc *fd)
{
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- size_t bytes;
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- bytes = 0;
-
- err = OTCountDataBytes(endpoint, &bytes);
- if ((err == kOTLookErr) || // Not really errors, we just need to do a read,
- (err == kOTNoDataErr)) // or thereÕs nothing there.
- err = kOTNoError;
-
- if (err != kOTNoError)
- goto ErrorExit;
-
- return bytes;
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ size_t bytes;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ bytes = 0;
+
+ err = OTCountDataBytes(endpoint, &bytes);
+ if ((err == kOTLookErr) || // Not really errors, we just need to do a read,
+ (err == kOTNoDataErr)) // or thereÕs nothing there.
+ err = kOTNoError;
+
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ return bytes;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- TBind bindReq;
- PRNetAddr bindAddr;
- PRInt32 newosfd = -1;
- EndpointRef newEndpoint;
- TCall call;
- PRNetAddr callAddr;
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- memset(&call, 0 , sizeof(call));
-
- call.addr.maxlen = PR_NETADDR_SIZE(&callAddr);
- call.addr.len = PR_NETADDR_SIZE(&callAddr);
- call.addr.buf = (UInt8*) &callAddr;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTListen (endpoint, &call);
- if (err != kOTNoError && (err != kOTNoDataErr || fd->secret->nonblocking)) {
- me->io_pending = PR_FALSE;
- goto ErrorExit;
- }
-
- while (err == kOTNoDataErr) {
- WaitOnThisThread(me, timeout);
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTListen (endpoint, &call);
- if (err == kOTNoError)
- break;
-
- PR_ASSERT(err == kOTNoDataErr);
- }
-
- newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0);
- if (newosfd == -1)
- return -1;
-
- newEndpoint = (EndpointRef)newosfd;
-
- // Bind to a local port; let the system assign it.
-
- bindAddr.inet.port = bindAddr.inet.ip = 0;
-
- bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
- bindReq.addr.len = 0;
- bindReq.addr.buf = (UInt8*) &bindAddr;
- bindReq.qlen = 0;
-
- PrepareThreadForAsyncIO(me, newEndpoint, newosfd);
-
- err = OTBind(newEndpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
-
- WaitOnThisThread(me, timeout);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PrepareThreadForAsyncIO(me, endpoint, newosfd);
-
- err = OTAccept (endpoint, newEndpoint, &call);
- if (err != kOTNoError)
- goto ErrorExit;
-
- WaitOnThisThread(me, timeout);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PR_ASSERT(me->md.cookie != NULL);
-
- if (addr != NULL)
- *addr = callAddr;
- if (addrlen != NULL)
- *addrlen = call.addr.len;
-
- return newosfd;
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ TBind bindReq;
+ PRNetAddr bindAddr;
+ PRInt32 newosfd = -1;
+ EndpointRef newEndpoint;
+ TCall call;
+ PRNetAddr callAddr;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ memset(&call, 0 , sizeof(call));
+
+ call.addr.maxlen = PR_NETADDR_SIZE(&callAddr);
+ call.addr.len = PR_NETADDR_SIZE(&callAddr);
+ call.addr.buf = (UInt8*) &callAddr;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTListen (endpoint, &call);
+ if (err != kOTNoError && (err != kOTNoDataErr || fd->secret->nonblocking)) {
+ me->io_pending = PR_FALSE;
+ goto ErrorExit;
+ }
+
+ while (err == kOTNoDataErr) {
+ WaitOnThisThread(me, timeout);
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTListen (endpoint, &call);
+ if (err == kOTNoError)
+ break;
+
+ PR_ASSERT(err == kOTNoDataErr);
+ }
+
+ newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0);
+ if (newosfd == -1)
+ return -1;
+
+ newEndpoint = (EndpointRef)newosfd;
+
+ // Bind to a local port; let the system assign it.
+
+ bindAddr.inet.port = bindAddr.inet.ip = 0;
+
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &bindAddr;
+ bindReq.qlen = 0;
+
+ PrepareThreadForAsyncIO(me, newEndpoint, newosfd);
+
+ err = OTBind(newEndpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PrepareThreadForAsyncIO(me, endpoint, newosfd);
+
+ err = OTAccept (endpoint, newEndpoint, &call);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT(me->md.cookie != NULL);
+
+ if (addr != NULL)
+ *addr = callAddr;
+ if (addrlen != NULL)
+ *addrlen = call.addr.len;
+
+ return newosfd;
ErrorExit:
- if (newosfd != -1)
- _MD_closesocket(newosfd);
- macsock_map_error(err);
+ if (newosfd != -1)
+ _MD_closesocket(newosfd);
+ macsock_map_error(err);
return -1;
}
PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- TCall sndCall;
- TBind bindReq;
- PRNetAddr bindAddr;
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (addr == NULL) {
- err = kEFAULTErr;
- goto ErrorExit;
- }
-
- // Bind to a local port; let the system assign it.
-
- bindAddr.inet.port = bindAddr.inet.ip = 0;
-
- bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
- bindReq.addr.len = 0;
- bindReq.addr.buf = (UInt8*) &bindAddr;
- bindReq.qlen = 0;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTBind(endpoint, &bindReq, NULL);
- if (err != kOTNoError)
- goto ErrorExit;
-
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- memset(&sndCall, 0 , sizeof(sndCall));
-
- sndCall.addr.maxlen = addrlen;
- sndCall.addr.len = addrlen;
- sndCall.addr.buf = (UInt8*) addr;
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- err = OTConnect (endpoint, &sndCall, NULL);
- if (err != kOTNoError && err != kOTNoDataErr)
- goto ErrorExit;
- if (err == kOTNoDataErr && fd->secret->nonblocking) {
- err = kEINPROGRESSErr;
- me->io_pending = PR_FALSE;
- goto ErrorExit;
- }
-
- WaitOnThisThread(me, timeout);
-
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PR_ASSERT(me->md.cookie != NULL);
-
- err = OTRcvConnect(endpoint, NULL);
- PR_ASSERT(err == kOTNoError);
-
- return kOTNoError;
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ TCall sndCall;
+ TBind bindReq;
+ PRNetAddr bindAddr;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ // Bind to a local port; let the system assign it.
+
+ bindAddr.inet.port = bindAddr.inet.ip = 0;
+
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &bindAddr;
+ bindReq.qlen = 0;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ memset(&sndCall, 0 , sizeof(sndCall));
+
+ sndCall.addr.maxlen = addrlen;
+ sndCall.addr.len = addrlen;
+ sndCall.addr.buf = (UInt8*) addr;
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ err = OTConnect (endpoint, &sndCall, NULL);
+ if (err != kOTNoError && err != kOTNoDataErr)
+ goto ErrorExit;
+ if (err == kOTNoDataErr && fd->secret->nonblocking) {
+ err = kEINPROGRESSErr;
+ me->io_pending = PR_FALSE;
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT(me->md.cookie != NULL);
+
+ err = OTRcvConnect(endpoint, NULL);
+ PR_ASSERT(err == kOTNoError);
+
+ return kOTNoError;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
@@ -1008,93 +1008,93 @@ ErrorExit:
static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
PRIntn flags, PRIntervalTime timeout, SndRcvOpCode opCode)
{
- OSStatus err;
- OTResult result;
- PRInt32 osfd = fd->secret->md.osfd;
- EndpointRef endpoint = (EndpointRef) osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 bytesLeft = amount;
-
- PR_ASSERT(flags == 0);
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (buf == NULL) {
- err = kEFAULTErr;
- goto ErrorExit;
- }
-
- if (opCode != kSTREAM_SEND && opCode != kSTREAM_RECEIVE) {
- err = kEINVALErr;
- goto ErrorExit;
- }
-
- while (bytesLeft > 0) {
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- if (opCode == kSTREAM_SEND)
- result = OTSnd(endpoint, buf, bytesLeft, NULL);
- else
- result = OTRcv(endpoint, buf, bytesLeft, NULL);
-
- if (result > 0) {
- buf = (void *) ( (UInt32) buf + (UInt32)result );
- bytesLeft -= result;
- me->io_pending = PR_FALSE;
- if (opCode == kSTREAM_RECEIVE)
- return result;
- } else {
- if (result == kOTOutStateErr) { /* it has been closed */
- me->io_pending = PR_FALSE;
- return 0;
- }
- if (result == kOTLookErr) {
- PRBool readReady,writeReady,exceptReady;
- /* process the event and then continue the operation */
- (void) GetState(endpoint, &readReady, &writeReady, &exceptReady);
- continue;
- }
- if (result != kOTNoDataErr && result != kOTFlowErr &&
- result != kEAGAINErr && result != kEWOULDBLOCKErr) {
- me->io_pending = PR_FALSE;
- err = result;
- goto ErrorExit;
- } else if (fd->secret->nonblocking) {
- me->io_pending = PR_FALSE;
- err = result;
- goto ErrorExit;
- }
- WaitOnThisThread(me, timeout);
- me->io_pending = PR_FALSE;
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PR_ASSERT(me->md.cookie != NULL);
- }
- }
-
- return amount;
+ OSStatus err;
+ OTResult result;
+ PRInt32 osfd = fd->secret->md.osfd;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 bytesLeft = amount;
+
+ PR_ASSERT(flags == 0);
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (buf == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ if (opCode != kSTREAM_SEND && opCode != kSTREAM_RECEIVE) {
+ err = kEINVALErr;
+ goto ErrorExit;
+ }
+
+ while (bytesLeft > 0) {
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ if (opCode == kSTREAM_SEND)
+ result = OTSnd(endpoint, buf, bytesLeft, NULL);
+ else
+ result = OTRcv(endpoint, buf, bytesLeft, NULL);
+
+ if (result > 0) {
+ buf = (void *) ( (UInt32) buf + (UInt32)result );
+ bytesLeft -= result;
+ me->io_pending = PR_FALSE;
+ if (opCode == kSTREAM_RECEIVE)
+ return result;
+ } else {
+ if (result == kOTOutStateErr) { /* it has been closed */
+ me->io_pending = PR_FALSE;
+ return 0;
+ }
+ if (result == kOTLookErr) {
+ PRBool readReady,writeReady,exceptReady;
+ /* process the event and then continue the operation */
+ (void) GetState(endpoint, &readReady, &writeReady, &exceptReady);
+ continue;
+ }
+ if (result != kOTNoDataErr && result != kOTFlowErr &&
+ result != kEAGAINErr && result != kEWOULDBLOCKErr) {
+ me->io_pending = PR_FALSE;
+ err = result;
+ goto ErrorExit;
+ } else if (fd->secret->nonblocking) {
+ me->io_pending = PR_FALSE;
+ err = result;
+ goto ErrorExit;
+ }
+ WaitOnThisThread(me, timeout);
+ me->io_pending = PR_FALSE;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT(me->md.cookie != NULL);
+ }
+ }
+
+ return amount;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
PRIntn flags, PRIntervalTime timeout)
{
- return (SendReceiveStream(fd, buf, amount, flags, timeout, kSTREAM_RECEIVE));
+ return (SendReceiveStream(fd, buf, amount, flags, timeout, kSTREAM_RECEIVE));
}
PRInt32 _MD_send(PRFileDesc *fd,const void *buf, PRInt32 amount,
PRIntn flags, PRIntervalTime timeout)
{
- return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
+ return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
}
@@ -1105,72 +1105,72 @@ static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount,
PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
PRIntervalTime timeout, SndRcvOpCode opCode)
{
- OSStatus err;
- PRInt32 osfd = fd->secret->md.osfd;
- EndpointRef endpoint = (EndpointRef) osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 bytesLeft = amount;
- TUnitData dgram;
-
- PR_ASSERT(flags == 0);
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (buf == NULL || addr == NULL) {
- err = kEFAULTErr;
- goto ErrorExit;
- }
-
- if (opCode != kDGRAM_SEND && opCode != kDGRAM_RECEIVE) {
- err = kEINVALErr;
- goto ErrorExit;
- }
-
- memset(&dgram, 0 , sizeof(dgram));
- dgram.addr.maxlen = *addrlen;
- dgram.addr.len = *addrlen;
- dgram.addr.buf = (UInt8*) addr;
- dgram.udata.maxlen = amount;
- dgram.udata.len = amount;
- dgram.udata.buf = (UInt8*) buf;
-
- while (bytesLeft > 0) {
-
- PrepareThreadForAsyncIO(me, endpoint, osfd);
-
- if (opCode == kDGRAM_SEND)
- err = OTSndUData(endpoint, &dgram);
- else
- err = OTRcvUData(endpoint, &dgram, NULL);
-
- if (err == kOTNoError) {
- buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
- bytesLeft -= dgram.udata.len;
- dgram.udata.buf = (UInt8*) buf;
- me->io_pending = PR_FALSE;
- }
- else {
- PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
- WaitOnThisThread(me, timeout);
- me->io_pending = PR_FALSE;
- err = me->md.osErrCode;
- if (err != kOTNoError)
- goto ErrorExit;
-
- PR_ASSERT(me->md.cookie != NULL);
- }
- }
-
- if (opCode == kDGRAM_RECEIVE)
- *addrlen = dgram.addr.len;
-
- return amount;
+ OSStatus err;
+ PRInt32 osfd = fd->secret->md.osfd;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 bytesLeft = amount;
+ TUnitData dgram;
+
+ PR_ASSERT(flags == 0);
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (buf == NULL || addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ if (opCode != kDGRAM_SEND && opCode != kDGRAM_RECEIVE) {
+ err = kEINVALErr;
+ goto ErrorExit;
+ }
+
+ memset(&dgram, 0 , sizeof(dgram));
+ dgram.addr.maxlen = *addrlen;
+ dgram.addr.len = *addrlen;
+ dgram.addr.buf = (UInt8*) addr;
+ dgram.udata.maxlen = amount;
+ dgram.udata.len = amount;
+ dgram.udata.buf = (UInt8*) buf;
+
+ while (bytesLeft > 0) {
+
+ PrepareThreadForAsyncIO(me, endpoint, osfd);
+
+ if (opCode == kDGRAM_SEND)
+ err = OTSndUData(endpoint, &dgram);
+ else
+ err = OTRcvUData(endpoint, &dgram, NULL);
+
+ if (err == kOTNoError) {
+ buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
+ bytesLeft -= dgram.udata.len;
+ dgram.udata.buf = (UInt8*) buf;
+ me->io_pending = PR_FALSE;
+ }
+ else {
+ PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
+ WaitOnThisThread(me, timeout);
+ me->io_pending = PR_FALSE;
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT(me->md.cookie != NULL);
+ }
+ }
+
+ if (opCode == kDGRAM_RECEIVE)
+ *addrlen = dgram.addr.len;
+
+ return amount;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
@@ -1178,69 +1178,69 @@ PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
PRIntervalTime timeout)
{
- return (SendReceiveDgram(fd, buf, amount, flags, addr, addrlen,
- timeout, kDGRAM_RECEIVE));
+ return (SendReceiveDgram(fd, buf, amount, flags, addr, addrlen,
+ timeout, kDGRAM_RECEIVE));
}
PRInt32 _MD_sendto(PRFileDesc *fd,const void *buf, PRInt32 amount,
PRIntn flags, PRNetAddr *addr, PRUint32 addrlen,
PRIntervalTime timeout)
{
- return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
- timeout, kDGRAM_SEND));
+ return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
+ timeout, kDGRAM_SEND));
}
PRInt32 _MD_closesocket(PRInt32 osfd)
{
- OSStatus err;
- EndpointRef endpoint = (EndpointRef) osfd;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- if (endpoint == NULL) {
- err = kEBADFErr;
- goto ErrorExit;
- }
-
- if (me->io_pending && me->io_fd == osfd)
- me->io_pending = PR_FALSE;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (me->io_pending && me->io_fd == osfd)
+ me->io_pending = PR_FALSE;
#if 0
- {
- OTResult state;
- state = OTGetEndpointState(endpoint);
-
- err = OTSndOrderlyDisconnect(endpoint);
- if (err != kOTNoError && err != kOTOutStateErr)
- goto ErrorExit;
-
- state = OTGetEndpointState(endpoint);
-
- err = OTUnbind(endpoint);
- if (err != kOTNoError && err != kOTOutStateErr)
- goto ErrorExit;
-
- state = OTGetEndpointState(endpoint);
-
- err = OTSetSynchronous(endpoint);
- if (err != kOTNoError)
- goto ErrorExit;
-
- err = OTSetBlocking(endpoint);
- if (err != kOTNoError)
- goto ErrorExit;
- }
+ {
+ OTResult state;
+ state = OTGetEndpointState(endpoint);
+
+ err = OTSndOrderlyDisconnect(endpoint);
+ if (err != kOTNoError && err != kOTOutStateErr)
+ goto ErrorExit;
+
+ state = OTGetEndpointState(endpoint);
+
+ err = OTUnbind(endpoint);
+ if (err != kOTNoError && err != kOTOutStateErr)
+ goto ErrorExit;
+
+ state = OTGetEndpointState(endpoint);
+
+ err = OTSetSynchronous(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ err = OTSetBlocking(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+ }
#endif
- (void) OTSndOrderlyDisconnect(endpoint);
+ (void) OTSndOrderlyDisconnect(endpoint);
- err = OTCloseProvider(endpoint);
- if (err != kOTNoError)
- goto ErrorExit;
+ err = OTCloseProvider(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
- return kOTNoError;
+ return kOTNoError;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return -1;
}
@@ -1248,128 +1248,161 @@ PRInt32 _MD_writev(PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size, PRInte
{
#pragma unused (fd, iov, iov_size, timeout)
- PR_ASSERT(0);
- _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
+ PR_ASSERT(0);
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
return -1;
}
static PRBool GetState(EndpointRef endpoint, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady)
{
- OSStatus err;
- OTResult resultOT;
- TDiscon discon;
- PRBool result = PR_FALSE;
-
- *readReady = *writeReady = *exceptReady = PR_FALSE;
-
- resultOT = OTLook(endpoint);
- switch (resultOT) {
- case T_DATA:
- case T_LISTEN:
- *readReady = PR_TRUE;
- break;
- case T_CONNECT:
- err = OTRcvConnect(endpoint, NULL);
- PR_ASSERT(err == kOTNoError);
- break;
- case T_DISCONNECT:
- memset(&discon, 0 , sizeof(discon));
- err = OTRcvDisconnect(endpoint, &discon);
- PR_ASSERT(err == kOTNoError);
- macsock_map_error(discon.reason);
- *exceptReady = PR_TRUE;
- break;
- case T_ORDREL:
- *readReady = PR_TRUE;
- err = OTRcvOrderlyDisconnect(endpoint);
- PR_ASSERT(err == kOTNoError);
- break;
- }
- resultOT = OTGetEndpointState(endpoint);
- switch (resultOT) {
- case T_DATAXFER:
- case T_INREL:
- *writeReady = PR_TRUE;
- break;
- default:
- *writeReady = PR_FALSE;
- }
-
- if ((*readReady == PR_TRUE) || (*writeReady==PR_TRUE) || (*exceptReady==PR_TRUE))
- result = PR_TRUE;
-
- return result;
+ OSStatus err;
+ OTResult resultOT;
+ TDiscon discon;
+ PRBool result = PR_FALSE;
+
+ *readReady = *writeReady = *exceptReady = PR_FALSE;
+
+ resultOT = OTLook(endpoint);
+ switch (resultOT) {
+ case T_DATA:
+ case T_LISTEN:
+ *readReady = PR_TRUE;
+ break;
+ case T_CONNECT:
+ err = OTRcvConnect(endpoint, NULL);
+ PR_ASSERT(err == kOTNoError);
+ break;
+ case T_DISCONNECT:
+ memset(&discon, 0 , sizeof(discon));
+ err = OTRcvDisconnect(endpoint, &discon);
+ PR_ASSERT(err == kOTNoError);
+ macsock_map_error(discon.reason);
+ *exceptReady = PR_TRUE;
+ break;
+ case T_ORDREL:
+ *readReady = PR_TRUE;
+ err = OTRcvOrderlyDisconnect(endpoint);
+ PR_ASSERT(err == kOTNoError);
+ break;
+ }
+ resultOT = OTGetEndpointState(endpoint);
+ switch (resultOT) {
+ case T_DATAXFER:
+ case T_INREL:
+ *writeReady = PR_TRUE;
+ break;
+ default:
+ *writeReady = PR_FALSE;
+ }
+
+ if ((*readReady == PR_TRUE) || (*writeReady==PR_TRUE) || (*exceptReady==PR_TRUE))
+ result = PR_TRUE;
+
+ return result;
}
PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
+ PRInt32 ready = 0;
PRPollDesc *pd, *epd;
- PRInt32 n = 0;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRIntervalTime sleepTime;
- PRIntervalTime timein = PR_IntervalNow();
-
- sleepTime = PR_MillisecondsToInterval(5UL);
- if (sleepTime > timeout)
- sleepTime = timeout;
-
- do {
-
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
- EndpointRef endpoint;
- PRInt16 out_flags = 0;
- PRBool readReady, writeReady, exceptReady;
-
- pd->out_flags = 0;
- if (NULL == bottom || in_flags == 0) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
- endpoint = (EndpointRef) osfd;
-
- if (GetState(endpoint, &readReady, &writeReady, &exceptReady)) {
-
- if ((in_flags & PR_POLL_READ) && (readReady)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && (writeReady)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && (exceptReady)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pd->out_flags = out_flags;
- if (out_flags) {
- n++;
- }
- }
+ PRIntervalTime sleepTime, timein;
+
+ sleepTime = PR_MillisecondsToInterval(5UL);
+ if (PR_INTERVAL_NO_TIMEOUT != timeout)
+ {
+ if (sleepTime > timeout) sleepTime = timeout;
+ timein = PR_IntervalNow();
}
- if (n > 0)
- return n;
+ do
+ {
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if (NULL == pd->fd || pd->in_flags == 0) continue;
+
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ ready += 1; /* some layer has buffer input */
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ PRFileDesc *bottom;
+ EndpointRef endpoint;
+ PRBool readReady, writeReady, exceptReady;
+
+ pd->out_flags = 0; /* pre-condition */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ endpoint = (EndpointRef)bottom->secret->md.osfd;
+
+ if (GetState(endpoint,
+ &readReady, &writeReady, &exceptReady))
+ {
+ if (readReady)
+ {
+ if (in_flags_read & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_WRITE;
+ }
+ if (writeReady)
+ {
+ if (in_flags_read & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_WRITE;
+ }
+ if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT))
+ {
+ pd->out_flags |= PR_POLL_EXCEPT;
+ }
+ if (0 != pd->out_flags) ready++;
+ }
+ }
+ else
+ {
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
- (void) PR_Sleep(sleepTime);
+ if (ready > 0) return ready;
- } while ((timeout == PR_INTERVAL_NO_TIMEOUT) ||
- (((PRIntervalTime)(PR_IntervalNow() - timein)) < timeout));
+ (void) PR_Sleep(sleepTime);
- return 0; /* timed out */
+ } while ((timeout == PR_INTERVAL_NO_TIMEOUT) ||
+ (((PRIntervalTime)(PR_IntervalNow() - timein)) < timeout));
+
+ return 0; /* timed out */
}
void _MD_makenonblock(PRFileDesc *fd)
{
- OSStatus err;
- PRInt32 osfd = fd->secret->md.osfd;
- EndpointRef endpoint = (EndpointRef) osfd;
+ OSStatus err;
+ PRInt32 osfd = fd->secret->md.osfd;
+ EndpointRef endpoint = (EndpointRef) osfd;
err = OTSetNonBlocking(endpoint);
- PR_ASSERT(err == kOTNoError || err == kOTOutStateErr);
+ PR_ASSERT(err == kOTNoError || err == kOTOutStateErr);
}
PR_IMPLEMENT(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how)
@@ -1384,21 +1417,21 @@ PR_IMPLEMENT(PRStatus) _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32
{
#pragma unused (fd, addr, addrlen)
- PR_ASSERT(0);
- _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
- return PR_FAILURE;
+ PR_ASSERT(0);
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
+ return PR_FAILURE;
}
PR_IMPLEMENT(unsigned long) inet_addr(const char *cp)
{
- OSStatus err;
- InetHost host;
+ OSStatus err;
+ InetHost host;
- err = OTInetStringToHost((char*) cp, &host);
- PR_ASSERT(err == kOTNoError);
-
- return host;
+ err = OTInetStringToHost((char*) cp, &host);
+ PR_ASSERT(err == kOTNoError);
+
+ return host;
}
@@ -1409,31 +1442,31 @@ static InetHost *sAddresses[kMaxHostAddrs+1];
PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name)
{
- OSStatus err;
- PRUint32 index;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ OSStatus err;
+ PRUint32 index;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- PrepareThreadForAsyncIO(me, sSvcRef, NULL);
+ PrepareThreadForAsyncIO(me, sSvcRef, NULL);
err = OTInetStringToAddress(sSvcRef, (char *)name, &sHostInfo);
- if (err != kOTNoError) {
- me->io_pending = PR_FALSE;
- me->md.osErrCode = err;
- goto ErrorExit;
- }
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ me->md.osErrCode = err;
+ goto ErrorExit;
+ }
- WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- if (me->md.osErrCode != kOTNoError)
- goto ErrorExit;
+ if (me->md.osErrCode != kOTNoError)
+ goto ErrorExit;
- sHostEnt.h_name = sHostInfo.name;
- for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
- sAddresses[index] = &sHostInfo.addrs[index];
- sAddresses[index] = NULL;
- sHostEnt.h_addr_list = (char **)sAddresses;
+ sHostEnt.h_name = sHostInfo.name;
+ for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
+ sAddresses[index] = &sHostInfo.addrs[index];
+ sAddresses[index] = NULL;
+ sHostEnt.h_addr_list = (char **)sAddresses;
- return (&sHostEnt);
+ return (&sHostEnt);
ErrorExit:
return NULL;
@@ -1442,57 +1475,57 @@ ErrorExit:
PR_IMPLEMENT(struct hostent *) gethostbyaddr(const void *addr, int addrlen, int type)
{
- PR_ASSERT(type == AF_INET);
- PR_ASSERT(addrlen == sizeof(struct in_addr));
+ PR_ASSERT(type == AF_INET);
+ PR_ASSERT(addrlen == sizeof(struct in_addr));
- OTInetHostToString((InetHost)addr, sHostInfo.name);
-
- return (gethostbyname(sHostInfo.name));
+ OTInetHostToString((InetHost)addr, sHostInfo.name);
+
+ return (gethostbyname(sHostInfo.name));
}
PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr)
{
- OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
-
- return sHostInfo.name;
+ OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
+
+ return sHostInfo.name;
}
PRStatus _MD_gethostname(char *name, int namelen)
{
- OSStatus err;
- InetInterfaceInfo info;
-
- /*
- * On a Macintosh, we donÕt have the concept of a local host name.
- * We do though have an IP address & everyone should be happy with
- * a string version of that for a name.
- * The alternative here is to ping a local DNS for our name, they
- * will often know it. This is the cheap, easiest, and safest way out.
- */
-
- /* Make sure the string is as long as the longest possible address */
- if (namelen < strlen("123.123.123.123")) {
- err = kEINVALErr;
- goto ErrorExit;
- }
-
- err = OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
- if (err != kOTNoError)
- goto ErrorExit;
-
- OTInetHostToString(info.fAddress, name);
-
- return PR_SUCCESS;
+ OSStatus err;
+ InetInterfaceInfo info;
+
+ /*
+ * On a Macintosh, we donÕt have the concept of a local host name.
+ * We do though have an IP address & everyone should be happy with
+ * a string version of that for a name.
+ * The alternative here is to ping a local DNS for our name, they
+ * will often know it. This is the cheap, easiest, and safest way out.
+ */
+
+ /* Make sure the string is as long as the longest possible address */
+ if (namelen < strlen("123.123.123.123")) {
+ err = kEINVALErr;
+ goto ErrorExit;
+ }
+
+ err = OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ OTInetHostToString(info.fAddress, name);
+
+ return PR_SUCCESS;
ErrorExit:
- macsock_map_error(err);
+ macsock_map_error(err);
return PR_FAILURE;
}
-#define kIPName "ip"
+#define kIPName "ip"
static struct protoent sIPProto = {kIPName, NULL, INET_IP};
static struct protoent sTCPProto = {kTCPName, NULL, INET_TCP};
static struct protoent sUDPProto = {kUDPName, NULL, INET_UDP};
@@ -1500,16 +1533,16 @@ static struct protoent sUDPProto = {kUDPName, NULL, INET_UDP};
PR_IMPLEMENT(struct protoent *) getprotobyname(const char * name)
{
if (strcmp(name, kIPName) == 0)
- return (&sIPProto);
-
+ return (&sIPProto);
+
if (strcmp(name, kTCPName) == 0)
- return (&sTCPProto);
-
+ return (&sTCPProto);
+
if (strcmp(name, kUDPName) == 0)
- return (&sUDPProto);
-
+ return (&sUDPProto);
+
ErrorExit:
- macsock_map_error(kEINVALErr);
+ macsock_map_error(kEINVALErr);
return NULL;
}
@@ -1517,36 +1550,36 @@ ErrorExit:
PR_IMPLEMENT(struct protoent *) getprotobynumber(int number)
{
if (number == INET_IP)
- return (&sIPProto);
-
+ return (&sIPProto);
+
if (number == INET_TCP)
- return (&sTCPProto);
-
+ return (&sTCPProto);
+
if (number == INET_UDP)
- return (&sUDPProto);
-
+ return (&sUDPProto);
+
ErrorExit:
- macsock_map_error(kEINVALErr);
+ macsock_map_error(kEINVALErr);
return NULL;
}
int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd)
{
- OTResult resultOT;
- EndpointRef endpoint = (EndpointRef) osfd;
-
- resultOT = OTGetEndpointState(endpoint);
- switch (resultOT) {
- case T_OUTCON:
- macsock_map_error(kEINPROGRESSErr);
- return -1;
- case T_DATAXFER:
- return 0;
- case T_IDLE:
- return -1;
- default:
- PR_ASSERT(0);
- return -1;
- }
+ OTResult resultOT;
+ EndpointRef endpoint = (EndpointRef) osfd;
+
+ resultOT = OTGetEndpointState(endpoint);
+ switch (resultOT) {
+ case T_OUTCON:
+ macsock_map_error(kEINPROGRESSErr);
+ return -1;
+ case T_DATAXFER:
+ return 0;
+ case T_IDLE:
+ return -1;
+ default:
+ PR_ASSERT(0);
+ return -1;
+ }
}
diff --git a/pr/src/md/mac/macthr.c b/pr/src/md/mac/macthr.c
index fa5a4637..26008768 100644
--- a/pr/src/md/mac/macthr.c
+++ b/pr/src/md/mac/macthr.c
@@ -71,7 +71,6 @@ PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
return PR_FAILURE;
}
- seg->access = PR_SEGMENT_RDWR;
seg->size = size;
return PR_SUCCESS;
@@ -163,7 +162,7 @@ pascal void TimerCallback(TMTaskPtr tmTaskPtr)
PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
return;
}
- _PR_SET_INTSOFF(1);
+ _PR_MD_SET_INTSOFF(1);
// And tell nspr that a clock interrupt occured.
_PR_ClockInterrupt();
@@ -171,7 +170,7 @@ pascal void TimerCallback(TMTaskPtr tmTaskPtr)
if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority)))
_PR_SET_RESCHED_FLAG();
- _PR_SET_INTSOFF(0);
+ _PR_MD_SET_INTSOFF(0);
// Reset the clock timer so that we fire again.
PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
diff --git a/pr/src/md/os2/os2poll.c b/pr/src/md/os2/os2poll.c
index b3353aa7..90195c64 100644
--- a/pr/src/md/os2/os2poll.c
+++ b/pr/src/md/os2/os2poll.c
@@ -22,144 +22,237 @@
#include "primpl.h"
-PRInt32
-_PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds,
- PRIntervalTime timeout)
+PRInt32 _PR_MD_PR_POLL(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
+ PRInt32 osfd;
+ int maxfd = -1;
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
PRPollDesc *pd, *epd;
- PRInt32 n, err, pdcnt;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 ready, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ struct timeval tv, *tvp = NULL;
- fd_set rd, wt, ex;
- struct timeval tv, *tvp = NULL;
- int maxfd = -1;
+ /*
+ * For restarting _MD_SELECT() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has elapsed
+ * and how much of the timeout still remains.
+ */
+ PRIntervalTime start, elapsed, remaining;
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
/*
- * For restarting _MD_SELECT() if it is interrupted by a signal.
- * We use these variables to figure out how much time has elapsed
- * and how much of the timeout still remains.
- */
- PRIntervalTime start, elapsed, remaining;
-
- FD_ZERO(&rd);
- FD_ZERO(&wt);
- FD_ZERO(&ex);
-
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
-
- if (osfd > maxfd) {
- maxfd = osfd;
- }
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &rd);
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &wt);
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &ex);
- }
- }
- if (timeout != PR_INTERVAL_NO_TIMEOUT) {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
- tvp = &tv;
- start = PR_IntervalNow();
- }
+ ** Is it an empty set? If so, just sleep for the timeout and return
+ */
+ if (0 == npds)
+ {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE),
+ &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ),
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now (buffered input) */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
+
+ remaining = timeout;
+ start = PR_IntervalNow();
retry:
- n = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
- if (n == -1 && errno == EINTR) {
- if (timeout == PR_INTERVAL_NO_TIMEOUT) {
- goto retry;
- } else {
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = remaining - (ticksPerSecond * tv.tv_sec);
+ tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond;
+ tvp = &tv;
+ }
+
+ ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
+ if (ready == -1 && errno == EINTR)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else
+ {
elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) {
- n = 0; /* timed out */
- } else {
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
remaining = timeout - elapsed;
- tv.tv_sec = PR_IntervalToSeconds(remaining);
- tv.tv_usec = PR_IntervalToMicroseconds(
- remaining - PR_SecondsToInterval(tv.tv_sec));
- goto retry;
- }
- }
- }
+ goto retry;
+ }
+ }
+ }
+
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
- if (n > 0) {
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRInt16 out_flags = 0;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- pd->out_flags = 0;
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
-
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pd->out_flags = out_flags;
- if (out_flags) {
- n++;
- }
- }
- PR_ASSERT(n > 0);
- } else if (n < 0) {
- err = _MD_ERRNO();
- if (err == EBADF) {
- /* Find the bad fds */
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- int optval;
- int optlen = sizeof(optval);
- PRFileDesc *bottom = pd->fd;
- pd->out_flags = 0;
- if ((NULL == bottom) || (pd->in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
- SO_TYPE, (char *) &optval, &optlen) == -1) {
- PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
- if (_MD_ERRNO() == ENOTSOCK) {
- pd->out_flags = PR_POLL_NVAL;
- n++;
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
}
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
}
- }
- PR_ASSERT(n > 0);
- } else {
- PR_ASSERT(err != EINTR); /* should have been handled above */
- _PR_MD_MAP_SELECT_ERROR(err);
- }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ int optval;
+ int optlen = sizeof(optval);
+ pd->out_flags = 0;
+ if ((NULL == pd->fd) || (pd->in_flags == 0)) continue;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
+ {
+ PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
+ if (_MD_ERRNO() == ENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else
+ {
+ PR_ASSERT(err != EINTR); /* should have been handled above */
+ _PR_MD_MAP_SELECT_ERROR(err);
+ }
}
- return n;
+ return ready;
}
diff --git a/pr/src/md/prosdep.c b/pr/src/md/prosdep.c
index 62b2b62f..326b3536 100644
--- a/pr/src/md/prosdep.c
+++ b/pr/src/md/prosdep.c
@@ -19,15 +19,15 @@
#include "prbit.h"
#include "prsystem.h"
-#if defined(XP_MAC)
-#include "prosdep.h"
-#else
-#include "md/prosdep.h"
-#endif
-
#ifdef XP_UNIX
#include <unistd.h>
#endif
+#ifdef SUNOS4
+#include "md/sunos4.h"
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
PRInt32 _pr_pageShift;
PRInt32 _pr_pageSize;
@@ -42,7 +42,7 @@ static void GetPageSize(void)
/* Get page size */
#ifdef XP_UNIX
#if defined SUNOS4 || defined LINUX || defined BSDI || defined AIX \
- || defined FREEBSD || defined NETBSD || defined RHAPSODY
+ || defined FREEBSD || defined NETBSD || defined OPENBSD || defined RHAPSODY
_pr_pageSize = getpagesize();
#elif defined(HPUX)
/* I have no idea. Don't get me started. --Rob */
diff --git a/pr/src/md/unix/Makefile b/pr/src/md/unix/Makefile
index 3615aabd..7d36371c 100644
--- a/pr/src/md/unix/Makefile
+++ b/pr/src/md/unix/Makefile
@@ -31,6 +31,7 @@ CSRCS = \
unix_errors.c \
uxproces.c \
uxwrap.c \
+ uxpoll.c \
$(NULL)
PTH_USER_CSRCS = \
@@ -61,6 +62,10 @@ NETBSD_CSRCS = \
netbsd.c \
$(NULL)
+OPENBSD_CSRCS = \
+ openbsd.c \
+ $(NULL)
+
BSDI_CSRCS = \
bsdi.c \
$(NULL)
@@ -134,6 +139,9 @@ endif
ifeq ($(OS_ARCH),NetBSD)
CSRCS += $(NETBSD_CSRCS)
endif
+ifeq ($(OS_ARCH),OpenBSD)
+CSRCS += $(OPENBSD_CSRCS)
+endif
ifeq ($(OS_ARCH),BSD_OS)
CSRCS += $(BSDI_CSRCS)
endif
@@ -186,8 +194,10 @@ ifeq ($(OS_ARCH),SunOS)
ASFILES = os_$(OS_ARCH)_x86.s
else
ifneq ($(OS_RELEASE),4.1.3_U1)
+ ifneq ($(LOCAL_THREADS_ONLY),1)
ASFILES = os_$(OS_ARCH).s
endif
+ endif
endif
endif
@@ -199,6 +209,10 @@ ifeq ($(OS_ARCH)$(OS_RELEASE),BSD_OS2.1)
ASFILES = os_BSD_386_2.s
endif
+ifeq ($(OS_ARCH), IRIX)
+ ASFILES = os_Irix.s
+endif
+
TARGETS = $(OBJS)
ifeq ($(OS_ARCH),AIX)
@@ -217,6 +231,7 @@ ifeq ($(OS_ARCH),SunOS)
ULTRASPARC_ASFILES = os_$(OS_ARCH)_ultrasparc.s
ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY)
+ RELEASE_LIBS = $(SHARED_LIBRARY)
endif
endif
endif
diff --git a/pr/src/md/unix/aix.c b/pr/src/md/unix/aix.c
index 879c6adc..524346e8 100644
--- a/pr/src/md/unix/aix.c
+++ b/pr/src/md/unix/aix.c
@@ -18,81 +18,6 @@
#include "primpl.h"
-/*
- * NSPR 2.0 overrides the system select() and poll() functions.
- * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
- * at the original system select() and poll() functions.
- */
-
-#ifndef AIX4_1
-
-#include <sys/select.h>
-#include <sys/poll.h>
-#include <dlfcn.h>
-
-static void *aix_handle = NULL;
-static int (*aix_select_fcn)() = NULL;
-static int (*aix_poll_fcn)() = NULL;
-
-int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
-{
- int rv;
-
- if (!aix_select_fcn) {
- if (!aix_handle) {
- aix_handle = dlopen("/unix", RTLD_NOW);
- if (!aix_handle) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- }
- aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
- if (!aix_select_fcn) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- }
- rv = (*aix_select_fcn)(width, r, w, e, t);
- return rv;
-}
-
-int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
-{
- int rv;
-
- if (!aix_poll_fcn) {
- if (!aix_handle) {
- aix_handle = dlopen("/unix", RTLD_NOW);
- if (!aix_handle) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- }
- aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
- if (!aix_poll_fcn) {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- }
- rv = (*aix_poll_fcn)(listptr, nfds, timeout);
- return rv;
-}
-
-#else
-
-/*
- * In AIX versions prior to 4.2, we use the two-step rename/link trick.
- * The binary must contain at least one "poll" symbol for linker's rename
- * to work. So we must have this dummy function that references poll().
- */
-#include <sys/poll.h>
-void _pr_aix_dummy()
-{
- poll(0,0,0);
-}
-
-#endif /* !AIX4_1 */
-
#include <sys/atomic_op.h>
PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
@@ -107,20 +32,57 @@ PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
return oldval;
} /* _AIX_AtomicSet */
+#if defined(AIX_TIMERS)
+
+#include <sys/time.h>
+
+static PRUint32 _aix_baseline_epoch;
+
+static void _MD_AixIntervalInit(void)
+{
+ timebasestruct_t real_time;
+ read_real_time(&real_time, TIMEBASE_SZ);
+ (void)time_base_to_time(&real_time, TIMEBASE_SZ);
+ _aix_baseline_epoch = real_time.tb_high;
+} /* _MD_AixIntervalInit */
+
+PRIntervalTime _MD_AixGetInterval(void)
+{
+ PRIntn rv;
+ PRUint64 temp;
+ timebasestruct_t real_time;
+ read_real_time(&real_time, TIMEBASE_SZ);
+ (void)time_base_to_time(&real_time, TIMEBASE_SZ);
+ /* tb_high is in seconds, tb_low in 10(-9)seconds */
+ temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch);
+ temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */
+ temp >>= 16; /* now it's something way different */
+ return (PRIntervalTime)temp;
+} /* _MD_AixGetInterval */
+
+PRIntervalTime _MD_AixIntervalPerSec(void)
+{
+ return 1000000000ULL >> 16; /* that's 15258, I think */
+} /* _MD_AixIntervalPerSec */
+
+#endif /* defined(AIX_TIMERS) */
+
#if !defined(PTHREADS_USER)
-#ifdef _PR_PTHREADS
+#if defined(_PR_PTHREADS)
/*
* AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield().
* So we look up the appropriate function pointer at run time.
*/
+#include <dlfcn.h>
+
int (*_PT_aix_yield_fcn)() = NULL;
void _MD_EarlyInit(void)
{
- void *main_app_handle = NULL;
+ void *main_app_handle;
main_app_handle = dlopen(NULL, RTLD_NOW);
PR_ASSERT(NULL != main_app_handle);
@@ -131,12 +93,19 @@ void _MD_EarlyInit(void)
PR_ASSERT(NULL != _PT_aix_yield_fcn);
}
dlclose(main_app_handle);
+
+#if defined(AIX_TIMERS)
+ _MD_AixIntervalInit();
+#endif
}
#else /* _PR_PTHREADS */
void _MD_EarlyInit(void)
{
+#if defined(AIX_TIMERS)
+ _MD_AixIntervalInit();
+#endif
}
#endif /* _PR_PTHREADS */
@@ -205,3 +174,128 @@ _MD_CREATE_THREAD(
}
#endif /* _PR_PTHREADS */
#endif /* PTHREADS_USER */
+
+/*
+ * NSPR 2.0 overrides the system select() and poll() functions.
+ * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
+ * at the original system select() and poll() functions.
+ */
+
+#if !defined(AIX4_1)
+
+#include <sys/select.h>
+#include <sys/poll.h>
+#include <dlfcn.h>
+
+static int (*aix_select_fcn)() = NULL;
+static int (*aix_poll_fcn)() = NULL;
+
+int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
+{
+ int rv;
+
+ if (!aix_select_fcn) {
+ void *aix_handle;
+
+ aix_handle = dlopen("/unix", RTLD_NOW);
+ if (!aix_handle) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
+ dlclose(aix_handle);
+ if (!aix_select_fcn) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ }
+ rv = (*aix_select_fcn)(width, r, w, e, t);
+ return rv;
+}
+
+int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
+{
+ int rv;
+
+ if (!aix_poll_fcn) {
+ void *aix_handle;
+
+ aix_handle = dlopen("/unix", RTLD_NOW);
+ if (!aix_handle) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
+ dlclose(aix_handle);
+ if (!aix_poll_fcn) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ }
+ rv = (*aix_poll_fcn)(listptr, nfds, timeout);
+ return rv;
+}
+
+#else
+
+/*
+ * In AIX versions prior to 4.2, we use the two-step rename/link trick.
+ * The binary must contain at least one "poll" symbol for linker's rename
+ * to work. So we must have this dummy function that references poll().
+ */
+#include <sys/poll.h>
+void _pr_aix_dummy()
+{
+ poll(0,0,0);
+}
+
+#endif /* !defined(AIX4_1) */
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include "pratom.h"
+
+#define _PR_AIX_ATOMIC_LOCK -1
+
+PR_IMPLEMENT(void)
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+PRStackElem *addr;
+boolean_t locked = TRUE;
+
+ do {
+ while ((addr = stack->prstk_head.prstk_elem_next) ==
+ (PRStackElem *)_PR_AIX_ATOMIC_LOCK)
+ ;
+ locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int) addr, _PR_AIX_ATOMIC_LOCK);
+ } while (locked == TRUE);
+ stack_elem->prstk_elem_next = addr;
+ _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem);
+ return;
+}
+
+PR_IMPLEMENT(PRStackElem *)
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+boolean_t locked = TRUE;
+
+ do {
+ while ((element = stack->prstk_head.prstk_elem_next) ==
+ (PRStackElem *) _PR_AIX_ATOMIC_LOCK)
+ ;
+ locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int)element, _PR_AIX_ATOMIC_LOCK);
+ } while (locked == TRUE);
+
+ if (element == NULL) {
+ _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL);
+ } else {
+ _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int) element->prstk_elem_next);
+ }
+ return element;
+}
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
diff --git a/pr/src/md/unix/darwin.c b/pr/src/md/unix/darwin.c
index a68f8667..01a73650 100644
--- a/pr/src/md/unix/darwin.c
+++ b/pr/src/md/unix/darwin.c
@@ -18,25 +18,13 @@
#include "primpl.h"
-#include <signal.h>
-
void _MD_EarlyInit(void)
{
- /*
- * Ignore FPE because coercion of a NaN to an int causes SIGFPE
- * to be raised.
- */
- struct sigaction act;
-
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESTART;
- sigaction(SIGFPE, &act, 0);
}
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
{
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
if (isCurrent) {
(void) setjmp(CONTEXT(t));
}
@@ -48,7 +36,7 @@ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
#endif
}
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
void
_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
{
@@ -98,3 +86,14 @@ _MD_CREATE_THREAD(
return PR_FAILURE;
}
#endif /* ! _PR_PTHREADS */
+
+/*
+** Whoops, we don't have a syscall stub for this
+*/
+int mprotect (caddr_t addr, size_t size, int prot)
+{
+ return -1;
+}
+
+/* rhapsody.c */
+
diff --git a/pr/src/md/unix/hpux.c b/pr/src/md/unix/hpux.c
index 79e244c1..e0328bb9 100644
--- a/pr/src/md/unix/hpux.c
+++ b/pr/src/md/unix/hpux.c
@@ -17,124 +17,51 @@
*/
#include "primpl.h"
-#if defined(HPUX10_30) || defined(HPUX11)
-/* for fesettrapenable */
-#include <fenv.h>
-#else
-/* for fpsetmask */
-#include <math.h>
-#endif
#include <setjmp.h>
-#include <signal.h>
-#include <values.h>
-/*
-** On HP-UX we need to define a SIGFPE handler because coercion of a
-** NaN to an int causes SIGFPE to be raised. Thanks to Marianne
-** Mueller and Doug Priest at SunSoft for this fix.
-**
-** Under DCE threads, sigaction() installs a per-thread signal handler,
-** so we use the sigvector() interface to install a process-wide
-** handler.
-**
-** On HP-UX 9, struct sigaction doesn't have the sa_sigaction field,
-** so we also need to use the sigvector() interface.
-*/
+#if defined(HPUX_LW_TIMER)
-#if defined(_PR_DCETHREADS) || defined(HPUX9)
-static void
-CatchFPE(int sig, int code, struct sigcontext *scp)
-{
- unsigned i, e;
- int r, t;
- int *source, *destination;
+#include <machine/inline.h>
+#include <machine/clock.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/pstat.h>
- /* check excepting instructions */
- for ( i = 0; i < 7; i++ ) {
- e = *(i+&(scp->sc_sl.sl_ss.ss_frexcp1));
- if ( e & 0xfc000000 != 0 ) {
- if ((e & 0xf4017720) == 0x24010200) {
- r = ((e >> 20) & 0x3e);
- t = (e & 0x1f) << 1;
- if (e & 0x08000000) {
- r |= (e >> 7) & 1;
- t |= (e >> 6) & 1;
- }
- source = (int *)(&scp->sc_sl.sl_ss.ss_frstat + r);
- destination = (int *)(&scp->sc_sl.sl_ss.ss_frstat + t);
- *destination = *source < 0 ? -MAXINT-1 : MAXINT;
- }
- }
- *(i+&(scp->sc_sl.sl_ss.ss_frexcp1)) = 0;
- }
+int __lw_get_thread_times(int which, int64_t *sample, int64_t *time);
- /* clear T-bit */
- scp->sc_sl.sl_ss.ss_frstat &= ~0x40;
-}
-#else /* _PR_DCETHREADS || HPUX9 */
-static void
-CatchFPE(int sig, siginfo_t *info, void *context)
+static double msecond_per_itick;
+
+void _PR_HPUX_LW_IntervalInit(void)
{
- ucontext_t *ucp = (ucontext_t *) context;
- unsigned i, e;
- int r, t;
- int *source, *destination;
+ struct pst_processor psp;
+ int iticksperclktick, clk_tck;
+ int rv;
- /* check excepting instructions */
- for ( i = 0; i < 7; i++ ) {
- e = *(i+&(ucp->uc_mcontext.ss_frexcp1));
- if ( e & 0xfc000000 != 0 ) {
- if ((e & 0xf4017720) == 0x24010200) {
- r = ((e >> 20) & 0x3e);
- t = (e & 0x1f) << 1;
- if (e & 0x08000000) {
- r |= (e >> 7) & 1;
- t |= (e >> 6) & 1;
- }
- source = (int *)(&ucp->uc_mcontext.ss_frstat + r);
- destination = (int *)(&ucp->uc_mcontext.ss_frstat + t);
- *destination = *source < 0 ? -MAXINT-1 : MAXINT;
- }
- }
- *(i+&(ucp->uc_mcontext.ss_frexcp1)) = 0;
- }
+ rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0);
+ PR_ASSERT(rv != -1);
- /* clear T-bit */
- ucp->uc_mcontext.ss_frstat &= ~0x40;
+ iticksperclktick = psp.psp_iticksperclktick;
+ clk_tck = sysconf(_SC_CLK_TCK);
+ msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck);
}
-#endif /* _PR_DCETHREADS || HPUX9 */
-void _MD_hpux_install_sigfpe_handler(void)
+PRIntervalTime _PR_HPUX_LW_GetInterval(void)
{
-#if defined(_PR_DCETHREADS) || defined(HPUX9)
- struct sigvec v;
-
- v.sv_handler = CatchFPE;
- v.sv_mask = 0;
- v.sv_flags = 0;
- sigvector(SIGFPE, &v, NULL);
-#else
- struct sigaction act;
-
- sigaction(SIGFPE, NULL, &act);
- act.sa_flags |= SA_SIGINFO;
- act.sa_sigaction = CatchFPE;
- sigaction(SIGFPE, &act, NULL);
-#endif /* _PR_DCETHREADS || HPUX9 */
+ int64_t time, sample;
-#if defined(HPUX10_30) || defined(HPUX11)
- fesettrapenable(FE_INVALID);
-#else
- fpsetmask(FP_X_INV);
-#endif
+ __lw_get_thread_times(1, &sample, &time);
+ /*
+ * Division is slower than float multiplication.
+ * return (time / iticks_per_msecond);
+ */
+ return (time * msecond_per_itick);
}
+#endif /* HPUX_LW_TIMER */
#if !defined(PTHREADS_USER)
void _MD_EarlyInit(void)
{
- _MD_hpux_install_sigfpe_handler();
-
#ifndef _PR_PTHREADS
/*
* The following piece of code is taken from ns/nspr/src/md_HP-UX.c.
@@ -260,28 +187,6 @@ _MD_resume_thread(PRThread *thread)
#endif /* PTHREADS_USER */
/*
- * See if we have the privilege to set the scheduling policy and
- * priority of threads. Returns 0 if privilege is available.
- * Returns EPERM otherwise.
- */
-
-#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
-PRIntn pt_hpux_privcheck()
-{
- PRIntn policy;
- struct sched_param schedule;
- PRIntn rv;
- pthread_t me = pthread_self();
-
- rv = pthread_getschedparam(me, &policy, &schedule);
- PR_ASSERT(0 == rv);
- rv = pthread_setschedparam(me, policy, &schedule);
- PR_ASSERT(0 == rv || EPERM == rv);
- return rv;
-}
-#endif
-
-/*
* The HP version of strchr is buggy. It looks past the end of the
* string and causes a segmentation fault when our (NSPR) version
* of malloc is used.
diff --git a/pr/src/md/unix/irix.c b/pr/src/md/unix/irix.c
index ca49378d..9e1963b5 100644
--- a/pr/src/md/unix/irix.c
+++ b/pr/src/md/unix/irix.c
@@ -36,12 +36,20 @@
#include <sys/resource.h>
#include <sys/procfs.h>
#include <task.h>
+#include <dlfcn.h>
-static void _MD_IntervalInit(void);
+static void _MD_IrixIntervalInit(void);
#if defined(_PR_PTHREADS)
+/*
+ * for compatibility with classic nspr
+ */
+void _PR_IRIX_CHILD_PROCESS()
+{
+}
#else /* defined(_PR_PTHREADS) */
+static void irix_detach_sproc(void);
char *_nspr_sproc_private; /* ptr. to private region in every sproc */
extern PRUintn _pr_numCPU;
@@ -61,6 +69,27 @@ ulock_t arena_list_lock;
nspr_arena first_arena;
int _nspr_irix_arena_cnt = 1;
+PRCList sproc_list = PR_INIT_STATIC_CLIST(&sproc_list);
+ulock_t sproc_list_lock;
+
+typedef struct sproc_data {
+ void (*entry) (void *, size_t);
+ unsigned inh;
+ void *arg;
+ caddr_t sp;
+ size_t len;
+ int *pid;
+ int creator_pid;
+} sproc_data;
+
+typedef struct sproc_params {
+ PRCList links;
+ sproc_data sd;
+} sproc_params;
+
+#define SPROC_PARAMS_PTR(qp) \
+ ((sproc_params *) ((char*) (qp) - offsetof(sproc_params , links)))
+
long _nspr_irix_lock_cnt = 0;
long _nspr_irix_sem_cnt = 0;
long _nspr_irix_pollsem_cnt = 0;
@@ -70,7 +99,12 @@ ulock_t _pr_heapLock;
usema_t *_pr_irix_exit_sem;
PRInt32 _pr_irix_exit_now = 0;
+PRInt32 _pr_irix_process_exit_code = 0; /* exit code for PR_ProcessExit */
+PRInt32 _pr_irix_process_exit = 0; /* process exiting due to call to
+ PR_ProcessExit */
+int _pr_irix_primoridal_cpu_fd[2] = { -1, -1 };
+static void (*libc_exit)(int) = NULL;
#define _NSPR_DEF_INITUSERS 100 /* default value of CONF_INITUSERS */
#define _NSPR_DEF_INITSIZE (4 * 1024 * 1024) /* 4 MB */
@@ -118,7 +152,7 @@ usema_t *sem = NULL;
PRCList *qp;
nspr_arena *arena;
usptr_t *irix_arena;
-PRThread *me = _PR_MD_CURRENT_THREAD();
+PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(_is);
@@ -171,7 +205,7 @@ PRThread *me = _PR_MD_CURRENT_THREAD();
static void free_poll_sem(struct _MDThread *mdthr)
{
PRIntn _is;
-PRThread *me = _PR_MD_CURRENT_THREAD();
+PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(_is);
@@ -189,7 +223,7 @@ ulock_t lock = NULL;
PRCList *qp;
nspr_arena *arena;
usptr_t *irix_arena;
-PRThread *me = _PR_MD_CURRENT_THREAD();
+PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(_is);
@@ -242,7 +276,7 @@ PRThread *me = _PR_MD_CURRENT_THREAD();
static void free_lock(struct _MDLock *lockp)
{
PRIntn _is;
-PRThread *me = _PR_MD_CURRENT_THREAD();
+PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(_is);
@@ -255,7 +289,7 @@ PRThread *me = _PR_MD_CURRENT_THREAD();
void _MD_FREE_LOCK(struct _MDLock *lockp)
{
PRIntn _is;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(_is);
@@ -274,17 +308,51 @@ void _MD_FREE_LOCK(struct _MDLock *lockp)
*/
PRThread *_MD_get_attached_thread(void)
{
- if (_MD_GET_SPROC_PID() == getpid())
- return _PR_MD_CURRENT_THREAD();
+
+ if (_MD_GET_SPROC_PID() == get_pid())
+ return _MD_THIS_THREAD();
else
return 0;
}
+/*
+ * _MD_get_current_thread
+ * Return the thread pointer of the current thread (attaching it if
+ * necessary)
+ */
+PRThread *_MD_get_current_thread(void)
+{
+PRThread *me;
+
+ me = _MD_GET_ATTACHED_THREAD();
+ if (NULL == me) {
+ me = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(me != NULL);
+ return(me);
+}
+
+/*
+ * irix_detach_sproc
+ * auto-detach a sproc when it exits
+ */
+void irix_detach_sproc(void)
+{
+PRThread *me;
+
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED)) {
+ _PRI_DetachThread();
+ }
+}
+
+
PRStatus _MD_NEW_LOCK(struct _MDLock *lockp)
{
PRStatus rv;
PRIntn is;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRThread *me = _MD_GET_ATTACHED_THREAD();
if (me && !_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(is);
@@ -311,7 +379,7 @@ sigchld_handler(int sig)
(WTERMSIG(status) == SIGILL))) {
prctl(PR_SETEXITSIG, SIGKILL);
- exit(status);
+ _exit(status);
}
}
}
@@ -412,9 +480,13 @@ void _MD_InitLocks()
exit(-1);
}
_pr_heapLock = usnewlock(_pr_usArena);
+ _nspr_irix_lock_cnt++;
arena_list_lock = usnewlock(_pr_usArena);
- _nspr_irix_lock_cnt = 3;
+ _nspr_irix_lock_cnt++;
+
+ sproc_list_lock = usnewlock(_pr_usArena);
+ _nspr_irix_lock_cnt++;
_pr_irix_exit_sem = usnewsema(_pr_usArena, 0);
_nspr_irix_sem_cnt = 1;
@@ -427,13 +499,16 @@ void _MD_InitLocks()
/* _PR_IRIX_CHILD_PROCESS is a private API for Server group */
void _PR_IRIX_CHILD_PROCESS()
{
+extern PRUint32 _pr_global_threads;
+
PR_ASSERT(_PR_MD_CURRENT_CPU() == _pr_primordialCPU);
PR_ASSERT(_pr_numCPU == 1);
- PR_ASSERT((_pr_userActive + _pr_systemActive) == 2);
+ PR_ASSERT(_pr_global_threads == 0);
/*
* save the new pid
*/
_pr_primordialCPU->md.id = getpid();
+ _MD_SET_SPROC_PID(getpid());
}
static PRStatus pr_cvar_wait_sem(PRThread *thread, PRIntervalTime timeout)
@@ -544,7 +619,6 @@ PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks)
PRStatus _MD_WakeupWaiter(PRThread *thread)
{
PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 pid, rv;
PRIntn is;
PR_ASSERT(_pr_md_idle_cpus >= 0);
@@ -565,6 +639,80 @@ PRStatus _MD_WakeupWaiter(PRThread *thread)
return PR_SUCCESS;
}
+void create_sproc (void (*entry) (void *, size_t), unsigned inh,
+ void *arg, caddr_t sp, size_t len, int *pid)
+{
+sproc_params sparams;
+char data;
+int rv;
+PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {
+ *pid = sprocsp(entry, /* startup func */
+ inh, /* attribute flags */
+ arg, /* thread param */
+ sp, /* stack address */
+ len); /* stack size */
+ } else {
+ sparams.sd.entry = entry;
+ sparams.sd.inh = inh;
+ sparams.sd.arg = arg;
+ sparams.sd.sp = sp;
+ sparams.sd.len = len;
+ sparams.sd.pid = pid;
+ sparams.sd.creator_pid = getpid();
+ _PR_LOCK(sproc_list_lock);
+ PR_APPEND_LINK(&sparams.links, &sproc_list);
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+ _PR_UNLOCK(sproc_list_lock);
+ blockproc(getpid());
+ }
+}
+
+/*
+ * _PR_MD_WAKEUP_PRIMORDIAL_CPU
+ *
+ * wakeup cpu 0
+ */
+
+void _PR_MD_WAKEUP_PRIMORDIAL_CPU()
+{
+char data = '0';
+int rv;
+
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+}
+
+/*
+ * _PR_MD_primordial_cpu
+ *
+ * process events that need to executed by the primordial cpu on each
+ * iteration through the idle loop
+ */
+
+void _PR_MD_primordial_cpu()
+{
+PRCList *qp;
+sproc_params *sp;
+int pid;
+
+ _PR_LOCK(sproc_list_lock);
+ while ((qp = sproc_list.next) != &sproc_list) {
+ sp = SPROC_PARAMS_PTR(qp);
+ PR_REMOVE_LINK(&sp->links);
+ pid = sp->sd.creator_pid;
+ (*(sp->sd.pid)) = sprocsp(sp->sd.entry, /* startup func */
+ sp->sd.inh, /* attribute flags */
+ sp->sd.arg, /* thread param */
+ sp->sd.sp, /* stack address */
+ sp->sd.len); /* stack size */
+ unblockproc(pid);
+ }
+ _PR_UNLOCK(sproc_list_lock);
+}
+
PRStatus _MD_CreateThread(PRThread *thread,
void (*start)(void *),
PRThreadPriority priority,
@@ -578,43 +726,44 @@ PRUint32 stackSize)
PRThread *me = _PR_MD_CURRENT_THREAD();
PRInt32 pid;
PRStatus rv;
- PRStatus creation_status;
if (!_PR_IS_NATIVE_THREAD(me))
_PR_INTSOFF(is);
thread->md.cvar_pollsem_select = 0;
- thread->md.creation_status = &creation_status;
thread->flags |= _PR_GLOBAL_SCOPE;
- pid = sprocsp(
- spentry, /* startup func */
- PR_SALL, /* attribute flags */
- (void *)thread, /* thread param */
- NULL, /* stack address */
- stackSize); /* stack size */
+
+ thread->md.cvar_pollsemfd = -1;
+ if (new_poll_sem(&thread->md,0) == PR_FAILURE) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+ thread->md.cvar_pollsemfd =
+ _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);
+ if ((thread->md.cvar_pollsemfd < 0)) {
+ free_poll_sem(&thread->md);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+
+ create_sproc(spentry, /* startup func */
+ PR_SALL, /* attribute flags */
+ (void *)thread, /* thread param */
+ NULL, /* stack address */
+ stackSize, &pid); /* stack size */
if (pid > 0) {
- /*
- * Wait for the sproc to signal me after it has initialized
- * itself
- */
- if (!_PR_IS_NATIVE_THREAD(me))
- blockproc(me->cpu->md.id);
- else
- blockproc(me->md.id);
- if (creation_status == PR_FAILURE) {
- /*
- * the sproc failed to create a polled semaphore and exited
- */
- _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed);
- rv = PR_FAILURE;
- } else {
- _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created);
- _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs);
- rv = PR_SUCCESS;
- }
+ _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created);
+ _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs);
+ rv = PR_SUCCESS;
if (!_PR_IS_NATIVE_THREAD(me))
_PR_FAST_INTSON(is);
return rv;
} else {
+ close(thread->md.cvar_pollsemfd);
+ thread->md.cvar_pollsemfd = -1;
+ free_poll_sem(&thread->md);
+ thread->md.cvar_pollsem = NULL;
_MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed);
if (!_PR_IS_NATIVE_THREAD(me))
_PR_FAST_INTSON(is);
@@ -686,38 +835,39 @@ extern void __sgi_prda_procmask(int);
#endif
PRStatus
-_MD_InitThread(PRThread *thread, PRBool wakeup_parent)
+_MD_InitAttachedThread(PRThread *thread, PRBool wakeup_parent)
{
- struct sigaction sigact;
PRStatus rv = PR_SUCCESS;
if (thread->flags & _PR_GLOBAL_SCOPE) {
- /*
- * create a polled semaphore
- *
- * NOTE: On Irix there is a bug which requires the sproc that
- * created a polled semaphore to not exit for that semaphore
- * to be useable by other sprocs.
- */
- thread->md.id = getpid();
- thread->md.cvar_pollsemfd = -1;
if (new_poll_sem(&thread->md,0) == PR_FAILURE) {
- if (wakeup_parent == PR_TRUE) {
- *thread->md.creation_status = PR_FAILURE;
- unblockproc(getppid());
- }
return PR_FAILURE;
}
thread->md.cvar_pollsemfd =
_PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);
if ((thread->md.cvar_pollsemfd < 0)) {
free_poll_sem(&thread->md);
- if (wakeup_parent == PR_TRUE) {
- *thread->md.creation_status = PR_FAILURE;
- unblockproc(getppid());
- }
return PR_FAILURE;
}
+ if (_MD_InitThread(thread, PR_FALSE) == PR_FAILURE) {
+ close(thread->md.cvar_pollsemfd);
+ thread->md.cvar_pollsemfd = -1;
+ free_poll_sem(&thread->md);
+ thread->md.cvar_pollsem = NULL;
+ return PR_FAILURE;
+ }
+ }
+ return rv;
+}
+
+PRStatus
+_MD_InitThread(PRThread *thread, PRBool wakeup_parent)
+{
+ struct sigaction sigact;
+ PRStatus rv = PR_SUCCESS;
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ thread->md.id = getpid();
setblockproccnt(thread->md.id, 0);
_MD_SET_SPROC_PID(getpid());
#ifndef IRIX5_3
@@ -729,7 +879,6 @@ _MD_InitThread(PRThread *thread, PRBool wakeup_parent)
#endif
/*
* set up SIGUSR1 handler; this is used to save state
- * during PR_SuspendAll
*/
sigact.sa_handler = save_context_and_block;
sigact.sa_flags = SA_RESTART;
@@ -740,52 +889,199 @@ _MD_InitThread(PRThread *thread, PRBool wakeup_parent)
sigaction(SIGUSR1, &sigact, 0);
- if (_nspr_terminate_on_error) {
+ /*
+ * PR_SETABORTSIG is a new command implemented in a patch to
+ * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
+ * sprocs in the process when one of them terminates abnormally
+ *
+ */
+ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
/*
- * PR_SETABORTSIG is a new command implemented in a patch to
- * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
- * sprocs in the process when one of them terminates abnormally
+ * if (errno == EINVAL)
*
+ * PR_SETABORTSIG not supported under this OS.
+ * You may want to get a recent kernel rollup patch that
+ * supports this feature.
*/
-
- if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
- /*
- * if (errno == EINVAL)
- *
- * PR_SETABORTSIG not supported under this OS.
- * You may want to get a recent kernel rollup patch that
- * supports this feature.
- */
- /*
- * SIGCLD handler for detecting abormally-terminating
- * sprocs
- */
- sigact.sa_handler = sigchld_handler;
- sigact.sa_flags = SA_RESTART;
- sigact.sa_mask = ints_off;
- sigaction(SIGCLD, &sigact, NULL);
- }
}
/*
- * unblock the parent sproc
+ * SIGCLD handler for detecting abormally-terminating
+ * sprocs and for reaping sprocs
*/
- if (wakeup_parent == PR_TRUE) {
- *thread->md.creation_status = PR_SUCCESS;
- unblockproc(getppid());
- }
+ sigact.sa_handler = sigchld_handler;
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_mask = ints_off;
+ sigaction(SIGCLD, &sigact, NULL);
}
return rv;
}
+/*
+ * PR_Cleanup should be executed on the primordial sproc; migrate the thread
+ * to the primordial cpu
+ */
+
+void _PR_MD_PRE_CLEANUP(PRThread *me)
+{
+PRIntn is;
+_PRCPU *cpu = _pr_primordialCPU;
+
+ PR_ASSERT(cpu);
+
+ me->flags |= _PR_BOUND_THREAD;
+
+ if (me->cpu->id != 0) {
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(cpu);
+ me->cpu = cpu;
+ me->state = _PR_RUNNABLE;
+ _PR_ADD_RUNQ(me, cpu, me->priority);
+ _PR_RUNQ_UNLOCK(cpu);
+ _MD_Wakeup_CPUs();
+
+ _PR_MD_SWITCH_CONTEXT(me);
+
+ _PR_FAST_INTSON(is);
+ PR_ASSERT(me->cpu->id == 0);
+ }
+}
+
+/*
+ * process exiting
+ */
PR_EXTERN(void ) _MD_exit(PRIntn status)
{
+PRThread *me = _PR_MD_CURRENT_THREAD();
+
/*
- * Cause SIGKILL to be sent to other sprocs, if any, in the application
+ * the exit code of the process is the exit code of the primordial
+ * sproc
*/
- prctl(PR_SETEXITSIG, SIGKILL);
- exit(status);
+ if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {
+ /*
+ * primordial sproc case: call _exit directly
+ * Cause SIGKILL to be sent to other sprocs
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(status);
+ } else {
+ int rv;
+ char data;
+ sigset_t set;
+
+ /*
+ * non-primordial sproc case: cause the primordial sproc, cpu 0,
+ * to wakeup and call _exit
+ */
+ _pr_irix_process_exit = 1;
+ _pr_irix_process_exit_code = status;
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+ /*
+ * block all signals and wait for SIGKILL to terminate this sproc
+ */
+ sigfillset(&set);
+ sigsuspend(&set);
+ /*
+ * this code doesn't (shouldn't) execute
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(status);
+ }
+}
+
+/*
+ * Override the exit() function in libc to cause the process to exit
+ * when the primodial/main nspr thread calls exit. Calls to exit by any
+ * other thread simply result in a call to the exit function in libc.
+ * The exit code of the process is the exit code of the primordial
+ * sproc.
+ */
+
+void exit(int status)
+{
+PRThread *me, *thr;
+PRCList *qp;
+void __exit(int status);
+
+ if (!_pr_initialized)
+ __exit(status);
+
+ me = _PR_MD_CURRENT_THREAD();
+
+ if (me == NULL) /* detached thread */
+ (*libc_exit)(status);
+
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) ||
+ (_PR_MD_CURRENT_CPU())->id == me->cpu->id);
+
+ if (me->flags & _PR_PRIMORDIAL) {
+
+ me->flags |= _PR_BOUND_THREAD;
+
+ PR_ASSERT((_PR_MD_CURRENT_CPU())->id == me->cpu->id);
+ if (me->cpu->id != 0) {
+ _PRCPU *cpu = _pr_primordialCPU;
+ PRIntn is;
+
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(cpu);
+ me->cpu = cpu;
+ me->state = _PR_RUNNABLE;
+ _PR_ADD_RUNQ(me, cpu, me->priority);
+ _PR_RUNQ_UNLOCK(cpu);
+ _MD_Wakeup_CPUs();
+
+ _PR_MD_SWITCH_CONTEXT(me);
+
+ _PR_FAST_INTSON(is);
+ }
+
+ PR_ASSERT((_PR_MD_CURRENT_CPU())->id == 0);
+
+ if (prctl(PR_GETNSHARE) > 1) {
+#define SPROC_EXIT_WAIT_TIME 5
+ int sleep_cnt = SPROC_EXIT_WAIT_TIME;
+
+ /*
+ * sprocs still running; caue cpus and recycled global threads
+ * to exit
+ */
+ _pr_irix_exit_now = 1;
+ if (_pr_numCPU > 1) {
+ _MD_Wakeup_CPUs();
+ }
+ _PR_DEADQ_LOCK;
+ if (_PR_NUM_DEADNATIVE != 0) {
+ PRThread *thread;
+ PRCList *ptr;
+
+ ptr = _PR_DEADNATIVEQ.next;
+ while( ptr != &_PR_DEADNATIVEQ ) {
+ thread = _PR_THREAD_PTR(ptr);
+ _MD_CVAR_POST_SEM(thread);
+ ptr = ptr->next;
+ }
+ }
+
+ while (sleep_cnt-- > 0) {
+ if (waitpid(0, NULL, WNOHANG) >= 0)
+ sleep(1);
+ else
+ break;
+ }
+ prctl(PR_SETEXITSIG, SIGKILL);
+ }
+ (*libc_exit)(status);
+ } else {
+ /*
+ * non-primordial thread; simply call exit in libc.
+ */
+ (*libc_exit)(status);
+ }
}
+
void
_MD_InitRunningCPU(_PRCPU *cpu)
{
@@ -882,11 +1178,9 @@ _MD_SuspendThread(PRThread *thread)
void
_MD_ResumeThread(PRThread *thread)
{
- PRInt32 rv;
-
PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
(thread->flags & _PR_GCABLE_THREAD));
- rv = unblockproc(thread->md.id);
+ (void)unblockproc(thread->md.id);
}
/*
@@ -902,7 +1196,7 @@ PRInt32 _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask)
nprocs = sysmp(MP_NPROCS);
if (nprocs < 0)
return(-1);
- pstat = PR_MALLOC(sizeof(struct pda_stat) * nprocs);
+ pstat = (struct pda_stat*)PR_MALLOC(sizeof(struct pda_stat) * nprocs);
if (pstat == NULL)
return(-1);
rv = sysmp(MP_STAT, pstat);
@@ -938,13 +1232,13 @@ static char *_thr_state[] = {
"DEAD"
};
-_PR_List_Threads()
+void _PR_List_Threads()
{
PRThread *thr;
void *handle;
struct _PRCPU *cpu;
PRCList *qp;
- int len, status, rv, fd;
+ int len, fd;
char pidstr[24];
char path[24];
prpsinfo_t pinfo;
@@ -1097,6 +1391,7 @@ void _MD_EarlyInit(void)
#if !defined(_PR_PTHREADS)
char *eval;
int fd;
+ extern int __ateachexit(void (*func)(void));
sigemptyset(&ints_off);
sigaddset(&ints_off, SIGALRM);
@@ -1116,23 +1411,26 @@ void _MD_EarlyInit(void)
* This region exists at the same address, _nspr_sproc_private, for
* every sproc, but each sproc gets a private copy of the region.
*/
- _nspr_sproc_private = mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE,
+ _nspr_sproc_private = (char*)mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE,
MAP_PRIVATE| MAP_LOCAL, fd, 0);
if (_nspr_sproc_private == (void*)-1) {
perror("mmap /dev/zero failed");
exit(1);
}
+ _MD_SET_SPROC_PID(getpid());
close(fd);
+ __ateachexit(irix_detach_sproc);
#endif
- _MD_IntervalInit();
+ _MD_IrixIntervalInit();
} /* _MD_EarlyInit */
void _MD_IrixInit()
{
#if !defined(_PR_PTHREADS)
struct sigaction sigact;
- rlim_t stack_max_limit;
PRThread *me = _PR_MD_CURRENT_THREAD();
+ void *libc_handle;
+ int rv;
#ifndef IRIX5_3
/*
@@ -1161,48 +1459,60 @@ void _MD_IrixInit()
/*
* Irix-specific terminate on error processing
*/
- if (_nspr_terminate_on_error) {
+ /*
+ * PR_SETABORTSIG is a new command implemented in a patch to
+ * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
+ * sprocs in the process when one of them terminates abnormally
+ *
+ */
+ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
/*
- * PR_SETABORTSIG is a new command implemented in a patch to
- * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
- * sprocs in the process when one of them terminates abnormally
+ * if (errno == EINVAL)
+ *
+ * PR_SETABORTSIG not supported under this OS.
+ * You may want to get a recent kernel rollup patch that
+ * supports this feature.
*
*/
- if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
- /*
- * if (errno == EINVAL)
- *
- * PR_SETABORTSIG not supported under this OS.
- * You may want to get a recent kernel rollup patch that
- * supports this feature.
- *
- */
- /*
- * PR_SETEXITSIG - send the SIGCLD signal to the parent
- * sproc when any sproc terminates
- *
- * This is used to cause the entire application to
- * terminate when any sproc terminates abnormally by
- * receipt of a SIGSEGV, SIGBUS or SIGABRT signal.
- * If this is not done, the application may seem
- * "hung" to the user because the other sprocs may be
- * waiting for resources held by the
- * abnormally-terminating sproc.
- */
- prctl(PR_SETEXITSIG, 0);
-
- sigact.sa_handler = sigchld_handler;
- sigact.sa_flags = SA_RESTART;
- sigact.sa_mask = ints_off;
- sigaction(SIGCLD, &sigact, NULL);
- }
}
+ /*
+ * PR_SETEXITSIG - send the SIGCLD signal to the parent
+ * sproc when any sproc terminates
+ *
+ * This is used to cause the entire application to
+ * terminate when any sproc terminates abnormally by
+ * receipt of a SIGSEGV, SIGBUS or SIGABRT signal.
+ * If this is not done, the application may seem
+ * "hung" to the user because the other sprocs may be
+ * waiting for resources held by the
+ * abnormally-terminating sproc.
+ */
+ prctl(PR_SETEXITSIG, 0);
+
+ sigact.sa_handler = sigchld_handler;
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_mask = ints_off;
+ sigaction(SIGCLD, &sigact, NULL);
/*
* setup stack fields for the primordial thread
*/
me->stack->stackSize = prctl(PR_GETSTACKSIZE);
me->stack->stackBottom = me->stack->stackTop - me->stack->stackSize;
+
+ rv = pipe(_pr_irix_primoridal_cpu_fd);
+ PR_ASSERT(rv == 0);
+#ifndef _PR_USE_POLL
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0];
+ FD_SET(_pr_irix_primoridal_cpu_fd[0], &_PR_FD_READ_SET(me->cpu));
+#endif
+
+ libc_handle = dlopen("libc.so",RTLD_NOW);
+ PR_ASSERT(libc_handle != NULL);
+ libc_exit = (void (*)(int)) dlsym(libc_handle, "exit");
+ PR_ASSERT(libc_exit != NULL);
+ /* dlclose(libc_handle); */
+
#endif /* _PR_PTHREADS */
_PR_UnixInit();
@@ -1218,7 +1528,7 @@ void _MD_IrixInit()
#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
#endif
-static PRUintn mmem_fd = -1;
+static PRIntn mmem_fd = -1;
static PRIntn clock_width = 0;
static void *iotimer_addr = NULL;
static PRUint32 pr_clock_mask = 0;
@@ -1230,7 +1540,7 @@ static PRUint32 pr_previous = 0, pr_residual = 0;
extern PRIntervalTime _PR_UNIX_GetInterval(void);
extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
-void _MD_IntervalInit(void)
+static void _MD_IrixIntervalInit()
{
/*
* As much as I would like, the service available through this
@@ -1290,14 +1600,14 @@ void _MD_IntervalInit(void)
((__psunsigned_t)iotimer_addr + (phys_addr & poffmask));
}
-} /* _PR_MD_INTERVAL_INIT */
+} /* _MD_IrixIntervalInit */
-PRIntervalTime _MD_IntervalPerSec()
+PRIntervalTime _MD_IrixIntervalPerSec()
{
return pr_clock_granularity;
}
-PRIntervalTime _MD_GetInterval()
+PRIntervalTime _MD_IrixGetInterval()
{
if (mmem_fd != -1)
{
@@ -1333,5 +1643,5 @@ PRIntervalTime _MD_GetInterval()
pr_ticks *= (PR_CLOCK_GRANULARITY / _PR_UNIX_TicksPerSecond());
}
return pr_ticks;
-} /* _MD_GetInterval */
+} /* _MD_IrixGetInterval */
diff --git a/pr/src/md/unix/ncr.c b/pr/src/md/unix/ncr.c
index 1560cc2c..a22a3b96 100644
--- a/pr/src/md/unix/ncr.c
+++ b/pr/src/md/unix/ncr.c
@@ -89,6 +89,15 @@ _MD_ATOMIC_INCREMENT(PRInt32 *val)
}
void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+
+void
_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
flockfile(_uw_semf);
diff --git a/pr/src/md/unix/objs.mk b/pr/src/md/unix/objs.mk
index 315a6e29..1d321324 100644
--- a/pr/src/md/unix/objs.mk
+++ b/pr/src/md/unix/objs.mk
@@ -23,6 +23,7 @@ CSRCS = \
unix_errors.c \
uxproces.c \
uxwrap.c \
+ uxpoll.c \
$(NULL)
PTH_USER_CSRCS = \
@@ -53,6 +54,10 @@ NETBSD_CSRCS = \
netbsd.c \
$(NULL)
+OPENBSD_CSRCS = \
+ openbsd.c \
+ $(NULL)
+
BSDI_CSRCS = \
bsdi.c \
$(NULL)
@@ -127,6 +132,9 @@ endif
ifeq ($(OS_ARCH),NetBSD)
CSRCS += $(NETBSD_CSRCS)
endif
+ifeq ($(OS_ARCH),OpenBSD)
+CSRCS += $(OPENBSD_CSRCS)
+endif
ifeq ($(OS_ARCH),BSD_OS)
CSRCS += $(BSDI_CSRCS)
endif
@@ -179,8 +187,10 @@ ifeq ($(OS_ARCH),SunOS)
ASFILES = os_$(OS_ARCH)_x86.s
else
ifneq ($(OS_RELEASE),4.1.3_U1)
+ ifneq ($(LOCAL_THREADS_ONLY),1)
ASFILES = os_$(OS_ARCH).s
endif
+ endif
endif
endif
@@ -188,6 +198,10 @@ ifeq ($(OS_ARCH), SINIX)
ASFILES = os_ReliantUNIX.s
endif
+ifeq ($(OS_ARCH), IRIX)
+ ASFILES = os_Irix.s
+endif
+
ifeq ($(OS_ARCH)$(OS_RELEASE),BSD_OS2.1)
ASFILES = os_BSD_386_2.s
endif
diff --git a/pr/src/md/unix/openbsd.c b/pr/src/md/unix/openbsd.c
new file mode 100644
index 00000000..1ad32d9f
--- /dev/null
+++ b/pr/src/md/unix/openbsd.c
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <poll.h>
+#include <sys/syscall.h>
+
+void _MD_EarlyInit(void)
+{
+ /*
+ * Ignore FPE because coercion of a NaN to an int causes SIGFPE
+ * to be raised.
+ */
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGFPE, &act, 0);
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) sigsetjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for OpenBSD */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for OpenBSD.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OpenBSD.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/pr/src/md/unix/os_Irix.s b/pr/src/md/unix/os_Irix.s
new file mode 100644
index 00000000..5d92fb67
--- /dev/null
+++ b/pr/src/md/unix/os_Irix.s
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * Atomically add a new element to the top of the stack
+ *
+ * usage : PR_StackPush(listp, elementp);
+ * -----------------------
+ */
+
+#include "md/_irix.h"
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include <sys/asm.h>
+#include <sys/regdef.h>
+
+LEAF(PR_StackPush)
+
+retry_push:
+.set noreorder
+ lw v0,0(a0)
+ li t1,1
+ beq v0,t1,retry_push
+ move t0,a1
+
+ ll v0,0(a0)
+ beq v0,t1,retry_push
+ nop
+ sc t1,0(a0)
+ beq t1,0,retry_push
+ nop
+ sw v0,0(a1)
+ sync
+ sw t0,0(a0)
+ jr ra
+ nop
+
+END(PR_StackPush)
+
+/*
+ *
+ * Atomically remove the element at the top of the stack
+ *
+ * usage : elemep = PR_StackPop(listp);
+ *
+ */
+
+LEAF(PR_StackPop)
+retry_pop:
+.set noreorder
+
+
+ lw v0,0(a0)
+ li t1,1
+ beq v0,0,done
+ beq v0,t1,retry_pop
+ nop
+
+ ll v0,0(a0)
+ beq v0,0,done
+ beq v0,t1,retry_pop
+ nop
+ sc t1,0(a0)
+ beq t1,0,retry_pop
+ nop
+ lw t0,0(v0)
+ sw t0,0(a0)
+done:
+ jr ra
+ nop
+
+END(PR_StackPop)
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
diff --git a/pr/src/md/unix/os_SunOS.s b/pr/src/md/unix/os_SunOS.s
index 2edf276f..bbad267c 100644
--- a/pr/src/md/unix/os_SunOS.s
+++ b/pr/src/md/unix/os_SunOS.s
@@ -49,3 +49,86 @@ _MD_FlushRegisterWindows:
ret
restore
+! ======================================================================
+!
+! Atomically add a new element to the top of the stack
+!
+! usage : PR_StackPush(listp, elementp);
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the stack
+! %o1 [input] - the address of the element to be added to the stack
+! -----------------------
+
+ .section ".text"
+ .global PR_StackPush
+
+PR_StackPush:
+
+pulock: ld [%o0],%o3 !
+ cmp %o3,-1 ! check if stack is locked
+ be pulock ! loop, if locked
+ mov -1,%o3 ! use delay-slot
+ swap [%o0],%o3 ! atomically lock the stack and get
+ ! the pointer to stack head
+ cmp %o3,-1 ! check, if the stack is locked
+ be pulock ! loop, if so
+ nop
+ st %o3,[%o1]
+ retl ! return back to the caller
+ st %o1,[%o0] !
+
+ .size PR_StackPush,(.-PR_StackPush)
+
+
+! end
+! ======================================================================
+
+! ======================================================================
+!
+! Atomically remove the element at the top of the stack
+!
+! usage : elemep = PR_StackPop(listp);
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the stack
+! %o1 [input] - work register (top element)
+! -----------------------
+
+ .section ".text"
+ .global PR_StackPop
+
+PR_StackPop:
+
+polock: ld [%o0],%o1 !
+ cmp %o1,-1 ! check if stack is locked
+ be polock ! loop, if locked
+ mov -1,%o1 ! use delay-slot
+ swap [%o0],%o1 ! atomically lock the stack and get
+ ! the pointer to stack head
+ cmp %o1,-1 ! check, if the stack is locked
+ be polock ! loop, if so
+ nop
+ tst %o1 ! test for empty stack
+ be,a empty ! is empty
+ st %g0,[%o0]
+ ld [%o1], %o2 ! load the second element
+ st %o2,[%o0] ! set stack head to second
+ st %g0,[%o1] ! reset the next pointer; for
+ ! debugging
+empty:
+ retl ! return back to the caller
+ mov %o1, %o0 ! return the first element
+
+ .size PR_StackPop,(.-PR_StackPop)
+
+! end
+! ======================================================================
diff --git a/pr/src/md/unix/os_SunOS_ultrasparc.s b/pr/src/md/unix/os_SunOS_ultrasparc.s
index 1391a9bc..8dd70636 100644
--- a/pr/src/md/unix/os_SunOS_ultrasparc.s
+++ b/pr/src/md/unix/os_SunOS_ultrasparc.s
@@ -155,3 +155,30 @@ retryAS:
!
! ======================================================================
!
+
+! ======================================================================
+!
+! Perform the sequence a = a + b atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : newval = PR_AtomicAdd(address, val)
+! return: the value after addition
+!
+ ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue
+
+retryAA:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, %o1, %o3 ! calc the new value
+ mov %o3, %o4 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAA ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o4, %o0 ! set the return code to the new value
+
+ SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue
+
+!
+! end
+!
diff --git a/pr/src/md/unix/osf1.c b/pr/src/md/unix/osf1.c
index e79e6607..5b02adb2 100644
--- a/pr/src/md/unix/osf1.c
+++ b/pr/src/md/unix/osf1.c
@@ -86,3 +86,60 @@ _MD_CREATE_THREAD(
return PR_FAILURE;
}
#endif /* ! _PR_PTHREADS */
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include <c_asm.h>
+
+#define _PR_OSF_ATOMIC_LOCK 1
+
+void
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+long locked;
+
+ do {
+ while ((long) stack->prstk_head.prstk_elem_next ==
+ _PR_OSF_ATOMIC_LOCK)
+ ;
+ locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+ _PR_OSF_ATOMIC_LOCK);
+
+ } while (locked == _PR_OSF_ATOMIC_LOCK);
+ stack_elem->prstk_elem_next = (PRStackElem *) locked;
+ /*
+ * memory-barrier instruction
+ */
+ asm("mb");
+ stack->prstk_head.prstk_elem_next = stack_elem;
+}
+
+PRStackElem *
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+long locked;
+
+ do {
+ while ((long)stack->prstk_head.prstk_elem_next == _PR_OSF_ATOMIC_LOCK)
+ ;
+ locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+ _PR_OSF_ATOMIC_LOCK);
+
+ } while (locked == _PR_OSF_ATOMIC_LOCK);
+
+ element = (PRStackElem *) locked;
+
+ if (element == NULL) {
+ stack->prstk_head.prstk_elem_next = NULL;
+ } else {
+ stack->prstk_head.prstk_elem_next =
+ element->prstk_elem_next;
+ }
+ /*
+ * memory-barrier instruction
+ */
+ asm("mb");
+ return element;
+}
+#endif /* _PR_HAVE_ATOMIC_CAS */
diff --git a/pr/src/md/unix/pthreads_user.c b/pr/src/md/unix/pthreads_user.c
index 63908b21..08fea163 100644
--- a/pr/src/md/unix/pthreads_user.c
+++ b/pr/src/md/unix/pthreads_user.c
@@ -38,10 +38,6 @@ void _MD_EarlyInit(void)
{
extern PRInt32 _nspr_noclock;
-#ifdef HPUX
- _MD_hpux_install_sigfpe_handler();
-#endif
-
if (pthread_key_create(&current_thread_key, NULL) != 0) {
perror("pthread_key_create failed");
exit(1);
@@ -355,6 +351,7 @@ _MD_CreateThread(
PRUint32 stackSize)
{
PRIntn is;
+ int rv;
PRThread *me = _PR_MD_CURRENT_THREAD();
pthread_attr_t attr;
@@ -386,8 +383,8 @@ _MD_CreateThread(
}
thread->md.wait = 0;
- if (pthread_create(&thread->md.pthread, &attr, start, (void *)thread)
- == 0) {
+ rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread);
+ if (0 == rv) {
_MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created);
_MD_ATOMIC_INCREMENT(&_pr_md_pthreads);
if (!_PR_IS_NATIVE_THREAD(me))
@@ -400,6 +397,7 @@ _MD_CreateThread(
_MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed);
if (!_PR_IS_NATIVE_THREAD(me))
_PR_FAST_INTSON(is);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv);
return PR_FAILURE;
}
}
@@ -413,7 +411,9 @@ _MD_InitRunningCPU(struct _PRCPU *cpu)
cpu->md.pthread = pthread_self();
if (_pr_md_pipefd[0] >= 0) {
_PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));
+#endif
}
}
diff --git a/pr/src/md/unix/rhapsody.c b/pr/src/md/unix/rhapsody.c
index a68f8667..01a73650 100644
--- a/pr/src/md/unix/rhapsody.c
+++ b/pr/src/md/unix/rhapsody.c
@@ -18,25 +18,13 @@
#include "primpl.h"
-#include <signal.h>
-
void _MD_EarlyInit(void)
{
- /*
- * Ignore FPE because coercion of a NaN to an int causes SIGFPE
- * to be raised.
- */
- struct sigaction act;
-
- act.sa_handler = SIG_IGN;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_RESTART;
- sigaction(SIGFPE, &act, 0);
}
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
{
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
if (isCurrent) {
(void) setjmp(CONTEXT(t));
}
@@ -48,7 +36,7 @@ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
#endif
}
-#ifndef _PR_PTHREADS
+#if !defined(_PR_PTHREADS)
void
_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
{
@@ -98,3 +86,14 @@ _MD_CREATE_THREAD(
return PR_FAILURE;
}
#endif /* ! _PR_PTHREADS */
+
+/*
+** Whoops, we don't have a syscall stub for this
+*/
+int mprotect (caddr_t addr, size_t size, int prot)
+{
+ return -1;
+}
+
+/* rhapsody.c */
+
diff --git a/pr/src/md/unix/scoos.c b/pr/src/md/unix/scoos.c
index 14365e8e..7b812aa0 100644
--- a/pr/src/md/unix/scoos.c
+++ b/pr/src/md/unix/scoos.c
@@ -89,6 +89,14 @@ _MD_ATOMIC_INCREMENT(PRInt32 *val)
}
void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+void
_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
flockfile(_uw_semf);
diff --git a/pr/src/md/unix/solaris.c b/pr/src/md/unix/solaris.c
index b102aa36..882cbca4 100644
--- a/pr/src/md/unix/solaris.c
+++ b/pr/src/md/unix/solaris.c
@@ -16,6 +16,8 @@
* Reserved.
*/
+#undef _FILE_OFFSET_BITS
+
#include "primpl.h"
@@ -100,6 +102,21 @@ _MD_AtomicIncrement(PRInt32 *val)
}
PRInt32
+_MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+{
+ PRInt32 rv;
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = ((*ptr) += val);
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+
+ return rv;
+}
+
+PRInt32
_MD_AtomicDecrement(PRInt32 *val)
{
PRInt32 rv;
@@ -171,8 +188,18 @@ PRStatus _MD_CreateThread(PRThread *thread,
/* mask out SIGALRM for native thread creation */
thr_sigsetmask(SIG_BLOCK, &set, &oldset);
- flags = (state == PR_JOINABLE_THREAD) ?
- THR_SUSPENDED : THR_SUSPENDED|THR_DETACHED;
+ /*
+ * Note that we create joinable threads with the THR_DETACHED
+ * flag. The reasons why we don't use thr_join to implement
+ * PR_JoinThread are:
+ * - We use a termination condition variable in the PRThread
+ * structure to implement PR_JoinThread across all classic
+ * nspr implementation strategies.
+ * - The native threads may be recycled by NSPR to run other
+ * new NSPR threads, so the native threads may not terminate
+ * when the corresponding NSPR threads terminate.
+ */
+ flags = THR_SUSPENDED|THR_DETACHED;
if (thread->flags & (_PR_GCABLE_THREAD|_PR_BOUND_THREAD))
flags |= THR_BOUND;
diff --git a/pr/src/md/unix/unix.c b/pr/src/md/unix/unix.c
index c3abd131..dd7e6d91 100644
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -18,6 +18,7 @@
#include "primpl.h"
+#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <memory.h>
@@ -29,7 +30,7 @@
#include <sys/mman.h>
#ifdef _PR_POLL_AVAILABLE
-#include <poll.h>
+#include <sys/poll.h>
#endif
/* To get FIONREAD */
@@ -48,7 +49,7 @@
|| defined(SUNOS4) || defined(NCR) || defined(RHAPSODY)
#define _PRSockLen_t int
#elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
- || defined(NETBSD) || defined(UNIXWARE) || defined(DGUX)
+ || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) || defined(DGUX)
#define _PRSockLen_t size_t
#else
#error "Cannot determine architecture"
@@ -69,6 +70,7 @@ static PRMonitor *_pr_Xfe_mon = NULL;
* to be a global variable for now.
*/
PRInt32 _pr_zero_fd = -1;
+static PRInt64 minus_one;
static PRLock *_pr_md_lock = NULL;
sigset_t timer_set;
@@ -108,46 +110,48 @@ extern PRInt32 _nspr_terminate_on_error;
int _pr_md_pipefd[2] = { -1, -1 };
static char _pr_md_pipebuf[PIPE_BUF];
+static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag,
+ PRIntervalTime timeout);
_PRInterruptTable _pr_interruptTable[] = {
- {
- "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
- {
- 0 }
+ {
+ "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
+ {
+ 0 }
};
PR_IMPLEMENT(void) _MD_unix_init_running_cpu(_PRCPU *cpu)
{
- PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));
- cpu->md.md_unix.ioq_max_osfd = -1;
- cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
+ PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));
+ cpu->md.md_unix.ioq_max_osfd = -1;
+ cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
}
PRStatus _MD_open_dir(_MDDir *d, const char *name)
{
int err;
- d->d = opendir(name);
- if (!d->d) {
- err = _MD_ERRNO();
- _PR_MD_MAP_OPENDIR_ERROR(err);
- return PR_FAILURE;
- }
- return PR_SUCCESS;
+ d->d = opendir(name);
+ if (!d->d) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPENDIR_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
}
PRInt32 _MD_close_dir(_MDDir *d)
{
int rv = 0, err;
- if (d->d) {
- rv = closedir(d->d);
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_CLOSEDIR_ERROR(err);
- }
- }
- return rv;
+ if (d->d) {
+ rv = closedir(d->d);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSEDIR_ERROR(err);
+ }
+ }
+ return rv;
}
char * _MD_read_dir(_MDDir *d, PRIntn flags)
@@ -155,144 +159,56 @@ char * _MD_read_dir(_MDDir *d, PRIntn flags)
struct dirent *de;
int err;
- for (;;) {
- /*
- * XXX: readdir() is not MT-safe. There is an MT-safe version
- * readdir_r() on some systems.
- */
- de = readdir(d->d);
- if (!de) {
- err = _MD_ERRNO();
- _PR_MD_MAP_READDIR_ERROR(err);
- return 0;
- }
- if ((flags & PR_SKIP_DOT) &&
- (de->d_name[0] == '.') && (de->d_name[1] == 0))
- continue;
- if ((flags & PR_SKIP_DOT_DOT) &&
- (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
- (de->d_name[2] == 0))
- continue;
- if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.'))
- continue;
- break;
- }
- return de->d_name;
+ for (;;) {
+ /*
+ * XXX: readdir() is not MT-safe. There is an MT-safe version
+ * readdir_r() on some systems.
+ */
+ de = readdir(d->d);
+ if (!de) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return 0;
+ }
+ if ((flags & PR_SKIP_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == 0))
+ continue;
+ if ((flags & PR_SKIP_DOT_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
+ (de->d_name[2] == 0))
+ continue;
+ if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.'))
+ continue;
+ break;
+ }
+ return de->d_name;
}
PRInt32 _MD_delete(const char *name)
{
PRInt32 rv, err;
#ifdef UNIXWARE
- sigset_t set, oset;
+ sigset_t set, oset;
#endif
#ifdef UNIXWARE
- sigfillset(&set);
- sigprocmask(SIG_SETMASK, &set, &oset);
+ sigfillset(&set);
+ sigprocmask(SIG_SETMASK, &set, &oset);
#endif
- rv = unlink(name);
+ rv = unlink(name);
#ifdef UNIXWARE
- sigprocmask(SIG_SETMASK, &oset, NULL);
+ sigprocmask(SIG_SETMASK, &oset, NULL);
#endif
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_UNLINK_ERROR(err);
- }
- return(rv);
-}
-
-PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info)
-{
- struct stat sb;
- PRInt64 s, s2us;
- PRInt32 rv, err;
-
- rv = stat(fn, &sb);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_STAT_ERROR(err);
- } else if (info) {
- if (S_IFREG & sb.st_mode)
- info->type = PR_FILE_FILE ;
- else if (S_IFDIR & sb.st_mode)
- info->type = PR_FILE_DIRECTORY;
- else
- info->type = PR_FILE_OTHER;
- info->size = sb.st_size;
- LL_I2L(s, sb.st_mtime);
- LL_I2L(s2us, PR_USEC_PER_SEC);
- LL_MUL(s, s, s2us);
- info->modifyTime = s;
- LL_I2L(s, sb.st_ctime);
- LL_MUL(s, s, s2us);
- info->creationTime = s;
- }
- return rv;
-}
-
-PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
-{
- PRFileInfo info32;
- PRInt32 rv = _MD_getfileinfo(fn, &info32);
- if (rv >= 0)
- {
- info->type = info32.type;
- LL_I2L(info->size, info32.size);
- info->modifyTime = info32.modifyTime;
- info->creationTime = info32.creationTime;
- }
- return rv;
-}
-
-PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
-{
- struct stat sb;
- PRInt64 s, s2us;
- PRInt32 rv, err;
-
- rv = fstat(fd->secret->md.osfd, &sb);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_FSTAT_ERROR(err);
- } else if (info) {
- if (info) {
- if (S_IFREG & sb.st_mode)
- info->type = PR_FILE_FILE ;
- else if (S_IFDIR & sb.st_mode)
- info->type = PR_FILE_DIRECTORY;
- else
- info->type = PR_FILE_OTHER;
- info->size = sb.st_size;
- LL_I2L(s, sb.st_mtime);
- LL_I2L(s2us, PR_USEC_PER_SEC);
- LL_MUL(s, s, s2us);
- info->modifyTime = s;
- LL_I2L(s, sb.st_ctime);
- LL_MUL(s, s, s2us);
- info->creationTime = s;
- }
- }
- return rv;
-}
-
-PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
-{
- PRFileInfo info32;
- PRInt32 rv = _MD_getopenfileinfo(fd, &info32);
- if (rv >= 0)
- {
- info->type = info32.type;
- LL_I2L(info->size, info32.size);
- info->modifyTime = info32.modifyTime;
- info->creationTime = info32.creationTime;
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_UNLINK_ERROR(err);
}
- return rv;
+ return(rv);
}
PRInt32 _MD_rename(const char *from, const char *to)
{
- PRInt32 rv = -1, err;
+ PRInt32 rv = -1, err;
/*
** This is trying to enforce the semantics of WINDOZE' rename
@@ -306,46 +222,46 @@ PRInt32 _MD_rename(const char *from, const char *to)
PR_SetError(PR_FILE_EXISTS_ERROR, 0);
else
{
- rv = rename(from, to);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_RENAME_ERROR(err);
- }
+ rv = rename(from, to);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RENAME_ERROR(err);
+ }
}
if (NULL != _pr_rename_lock)
PR_Unlock(_pr_rename_lock);
- return rv;
+ return rv;
}
-PRInt32 _MD_access(const char *name, PRIntn how)
+PRInt32 _MD_access(const char *name, PRAccessHow how)
{
PRInt32 rv, err;
int amode;
- switch (how) {
- case PR_ACCESS_WRITE_OK:
- amode = W_OK;
- break;
- case PR_ACCESS_READ_OK:
- amode = R_OK;
- break;
- case PR_ACCESS_EXISTS:
- amode = F_OK;
- break;
- default:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- rv = -1;
- goto done;
- }
- rv = access(name, amode);
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ amode = W_OK;
+ break;
+ case PR_ACCESS_READ_OK:
+ amode = R_OK;
+ break;
+ case PR_ACCESS_EXISTS:
+ amode = F_OK;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = access(name, amode);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_ACCESS_ERROR(err);
- }
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_ACCESS_ERROR(err);
+ }
done:
- return(rv);
+ return(rv);
}
PRInt32 _MD_mkdir(const char *name, PRIntn mode)
@@ -358,26 +274,26 @@ int rv, err;
*/
if (NULL !=_pr_rename_lock)
PR_Lock(_pr_rename_lock);
- rv = mkdir(name, mode);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_MKDIR_ERROR(err);
- }
+ rv = mkdir(name, mode);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_MKDIR_ERROR(err);
+ }
if (NULL !=_pr_rename_lock)
PR_Unlock(_pr_rename_lock);
- return rv;
+ return rv;
}
PRInt32 _MD_rmdir(const char *name)
{
int rv, err;
- rv = rmdir(name);
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_RMDIR_ERROR(err);
- }
- return rv;
+ rv = rmdir(name);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RMDIR_ERROR(err);
+ }
+ return rv;
}
PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)
@@ -392,53 +308,56 @@ struct pollfd pfd;
PRInt32 osfd = fd->secret->md.osfd;
#ifndef _PR_USE_POLL
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
+ FD_ZERO(&rd);
+ FD_SET(osfd, &rd);
#else
- pfd.fd = osfd;
- pfd.events = POLLIN;
+ pfd.fd = osfd;
+ pfd.events = POLLIN;
#endif /* _PR_USE_POLL */
- while ((rv = read(osfd,buf,amount)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- _PR_WaitForFD(osfd, PR_POLL_READ, PR_INTERVAL_NO_TIMEOUT);
- } else {
+ while ((rv = read(osfd,buf,amount)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ,
+ PR_INTERVAL_NO_TIMEOUT)) < 0)
+ goto done;
+ } else {
#ifndef _PR_USE_POLL
- while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
- == -1 && (err = _MD_ERRNO()) == EINTR) {
- /* retry _MD_SELECT() if it is interrupted */
- }
+ while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_SELECT() if it is interrupted */
+ }
#else /* _PR_USE_POLL */
- while ((rv = _MD_POLL(&pfd, 1, -1))
- == -1 && (err = _MD_ERRNO()) == EINTR) {
- /* retry _MD_POLL() if it is interrupted */
- }
+ while ((rv = _MD_POLL(&pfd, 1, -1))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_POLL() if it is interrupted */
+ }
#endif /* _PR_USE_POLL */
- if (rv == -1) {
- break;
- }
- }
- if (_PR_PENDING_INTERRUPT(me))
- break;
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- } else {
- _PR_MD_MAP_READ_ERROR(err);
- }
- }
- return(rv);
+ if (rv == -1) {
+ break;
+ }
+ }
+ if (_PR_PENDING_INTERRUPT(me))
+ break;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ _PR_MD_MAP_READ_ERROR(err);
+ }
+ }
+done:
+ return(rv);
}
PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
@@ -453,146 +372,106 @@ struct pollfd pfd;
PRInt32 osfd = fd->secret->md.osfd;
#ifndef _PR_USE_POLL
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
+ FD_ZERO(&wd);
+ FD_SET(osfd, &wd);
#else
- pfd.fd = osfd;
- pfd.events = POLLOUT;
+ pfd.fd = osfd;
+ pfd.events = POLLOUT;
#endif /* _PR_USE_POLL */
- while ((rv = write(osfd,buf,amount)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- _PR_WaitForFD(osfd, PR_POLL_WRITE, PR_INTERVAL_NO_TIMEOUT);
- } else {
+ while ((rv = write(osfd,buf,amount)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE,
+ PR_INTERVAL_NO_TIMEOUT)) < 0)
+ goto done;
+ } else {
#ifndef _PR_USE_POLL
- while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
- == -1 && (err = _MD_ERRNO()) == EINTR) {
- /* retry _MD_SELECT() if it is interrupted */
- }
+ while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_SELECT() if it is interrupted */
+ }
#else /* _PR_USE_POLL */
- while ((rv = _MD_POLL(&pfd, 1, -1))
- == -1 && (err = _MD_ERRNO()) == EINTR) {
- /* retry _MD_POLL() if it is interrupted */
- }
+ while ((rv = _MD_POLL(&pfd, 1, -1))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_POLL() if it is interrupted */
+ }
#endif /* _PR_USE_POLL */
- if (rv == -1) {
- break;
- }
- }
- if (_PR_PENDING_INTERRUPT(me))
- break;
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- } else {
- _PR_MD_MAP_WRITE_ERROR(err);
- }
- }
- return(rv);
-}
-
-PRInt32 _MD_lseek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
-{
-PRInt32 rv, where, err;
-
- switch (whence) {
- case PR_SEEK_SET:
- where = SEEK_SET;
- break;
- case PR_SEEK_CUR:
- where = SEEK_CUR;
- break;
- case PR_SEEK_END:
- where = SEEK_END;
- break;
- default:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- rv = -1;
- goto done;
- }
- rv = lseek(fd->secret->md.osfd,offset,where);
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_LSEEK_ERROR(err);
- }
+ if (rv == -1) {
+ break;
+ }
+ }
+ if (_PR_PENDING_INTERRUPT(me))
+ break;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ _PR_MD_MAP_WRITE_ERROR(err);
+ }
+ }
done:
- return(rv);
+ return(rv);
}
-PRInt64 _MD_lseek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
-{
- PRInt32 off, rv;
- PRInt64 on, result = LL_MININT;
- LL_L2I(off, offset);
- LL_I2L(on, off);
- if (LL_EQ(offset, on))
- {
- rv = _MD_lseek(fd, off, whence);
- if (rv >= 0) LL_I2L(result, rv);
- }
- else PR_SetError(PR_FILE_TOO_BIG_ERROR, 0); /* overflow */
- return result;
-} /* _MD_lseek64 */
-
PRInt32 _MD_fsync(PRFileDesc *fd)
{
PRInt32 rv, err;
- rv = fsync(fd->secret->md.osfd);
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_FSYNC_ERROR(err);
- }
- return(rv);
+ rv = fsync(fd->secret->md.osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ }
+ return(rv);
}
PRInt32 _MD_close(PRInt32 osfd)
{
PRInt32 rv, err;
- rv = close(osfd);
- if (rv == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_CLOSE_ERROR(err);
- }
- return(rv);
+ rv = close(osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
+ return(rv);
}
PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
{
- PRInt32 osfd, err;
+ PRInt32 osfd, err;
- osfd = socket(domain, type, proto);
+ osfd = socket(domain, type, proto);
- if (osfd == -1) {
- err = _MD_ERRNO();
- _PR_MD_MAP_SOCKET_ERROR(err);
- return(osfd);
- }
+ if (osfd == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ return(osfd);
+ }
- return(osfd);
+ return(osfd);
}
PRInt32 _MD_socketavailable(PRFileDesc *fd)
{
- PRInt32 result;
+ PRInt32 result;
- if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
- _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
- return -1;
- }
- return result;
+ if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
+ return -1;
+ }
+ return result;
}
PRInt64 _MD_socketavailable64(PRFileDesc *fd)
@@ -602,8 +481,8 @@ PRInt64 _MD_socketavailable64(PRFileDesc *fd)
return result;
} /* _MD_socketavailable64 */
-#define READ_FD 1
-#define WRITE_FD 2
+#define READ_FD 1
+#define WRITE_FD 2
/*
* socket_io_wait --
@@ -619,120 +498,110 @@ PRInt64 _MD_socketavailable64(PRFileDesc *fd)
static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
PRIntervalTime timeout)
{
- PRInt32 rv = -1;
- struct timeval tv, *tvp;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRIntervalTime epoch, now, elapsed, 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:
- /*
- * This is a special case of the 'default' case below.
- * Please see the comments there.
- */
- tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
- tv.tv_usec = 0;
- tvp = &tv;
- FD_ZERO(&rd_wr);
- do {
- FD_SET(osfd, &rd_wr);
- if (fd_type == READ_FD)
- rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
- else
- rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- if (syserror == EBADF) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, syserror);
- }
- break;
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- break;
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- default:
- now = epoch = PR_IntervalNow();
- remaining = timeout;
- tvp = &tv;
- 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.
- */
- tv.tv_sec = PR_IntervalToSeconds(remaining);
- if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
- 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, tvp);
- else
- rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
- /*
- * we don't consider EINTR a real error
- */
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- if (syserror == EBADF) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, syserror);
- }
- break;
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- break;
- }
- /*
- * We loop again if _MD_SELECT timed out or got interrupted
- * by a signal, and the timeout deadline has not passed yet.
- */
- 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);
- } else {
- now = PR_IntervalNow();
- }
- elapsed = (PRIntervalTime) (now - epoch);
- if (elapsed >= timeout) {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- } else {
- remaining = timeout - elapsed;
- }
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- }
- return(rv);
+ PRInt32 rv = -1;
+ struct timeval tv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, 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:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ 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);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ 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.
+ */
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ 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);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ 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);
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
}
#else /* _PR_USE_POLL */
@@ -740,115 +609,160 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
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;
- 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:
- /*
- * This is a special case of the 'default' case below.
- * Please see the comments there.
- */
- msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
- pfd.fd = osfd;
- if (fd_type == READ_FD) {
- pfd.events = POLLIN;
- } else {
- pfd.events = POLLOUT;
- }
- do {
- rv = _MD_POLL(&pfd, 1, msecs);
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- _PR_MD_MAP_POLL_ERROR(syserror);
- break;
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- break;
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- default:
- now = epoch = PR_IntervalNow();
- remaining = timeout;
- pfd.fd = osfd;
- if (fd_type == READ_FD) {
- pfd.events = POLLIN;
- } else {
- pfd.events = POLLOUT;
- }
- 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.
- */
- msecs = PR_IntervalToMilliseconds(remaining);
- if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
- msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
- }
- rv = _MD_POLL(&pfd, 1, msecs);
+ PRInt32 rv = -1;
+ int msecs;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, 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:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ pfd.fd = osfd;
+ if (fd_type == READ_FD) {
+ pfd.events = POLLIN;
+ } else {
+ pfd.events = POLLOUT;
+ }
+ do {
+ rv = _MD_POLL(&pfd, 1, msecs);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_POLL_ERROR(syserror);
+ break;
+ }
/*
- * we don't consider EINTR a real error
+ * If POLLERR is set, don't process it; retry the operation
*/
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- _PR_MD_MAP_POLL_ERROR(syserror);
- break;
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
rv = -1;
- break;
- }
+ _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ pfd.fd = osfd;
+ if (fd_type == READ_FD) {
+ pfd.events = POLLIN;
+ } else {
+ pfd.events = POLLOUT;
+ }
+ 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.
+ */
+ msecs = PR_IntervalToMilliseconds(remaining);
+ if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+ 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);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
/*
- * We loop again if _MD_POLL timed out or got interrupted
- * by a signal, and the timeout deadline has not passed yet.
+ * If POLLERR is set, don't process it; retry the operation
*/
- 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);
- } else {
- now = PR_IntervalNow();
- }
- elapsed = (PRIntervalTime) (now - epoch);
- if (elapsed >= timeout) {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- } else {
- remaining = timeout - elapsed;
- }
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- }
- return(rv);
+ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
+ rv = -1;
+ _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
+ break;
+ }
+ /*
+ * We loop again if _MD_POLL timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ 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);
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
}
#endif /* _PR_USE_POLL */
+static PRInt32 local_io_wait(
+ PRInt32 osfd,
+ PRInt32 wait_flag,
+ PRIntervalTime timeout)
+{
+ _PRUnixPollDesc pd;
+ PRInt32 rv;
+
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("waiting to %s on osfd=%d",
+ (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write",
+ osfd));
+
+ if (timeout == PR_INTERVAL_NO_WAIT) return 0;
+
+ pd.osfd = osfd;
+ pd.in_flags = wait_flag;
+ pd.out_flags = 0;
+
+ rv = _PR_WaitForMultipleFDs(&pd, 1, timeout);
+
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ }
+ return rv;
+}
+
+
PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
- PRInt32 flags, PRIntervalTime timeout)
+ PRInt32 flags, PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
/*
* Many OS's (Solaris, Unixware) have a broken recv which won't read
@@ -856,94 +770,67 @@ PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
* is a decent fix. - mikep
*/
#if defined(UNIXWARE) || defined(SOLARIS) || defined(NCR)
- while ((rv = read(osfd,buf,amount)) == -1) {
-/*
- while ((rv = recv(osfd,buf,amount,flags)) == -1) {
-*/
+ while ((rv = read(osfd,buf,amount)) == -1) {
#else
- while ((rv = recv(osfd,buf,amount,flags)) == -1) {
+ while ((rv = recv(osfd,buf,amount,flags)) == -1) {
#endif
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0)
goto done;
- }
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_RECV_ERROR(err);
- }
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
done:
- return(rv);
+ return(rv);
}
PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
- PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
- PRIntervalTime timeout)
-{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- while ((*addrlen = PR_NETADDR_SIZE(addr)),
- ((rv = recvfrom(osfd, buf, amount, flags,
- (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
- goto done;
- }
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_RECVFROM_ERROR(err);
- }
+ PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
done:
#ifdef _PR_HAVE_SOCKADDR_LEN
if (rv != -1) {
@@ -956,246 +843,203 @@ done:
}
}
#endif /* _PR_HAVE_SOCKADDR_LEN */
- return(rv);
+ return(rv);
}
PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
- PRInt32 flags, PRIntervalTime timeout)
+ PRInt32 flags, PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while ((rv = send(osfd,buf,amount,flags)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
- goto done;
+ /*
+ * On pre-2.6 Solaris, send() is much slower than write().
+ * On 2.6 and beyond, with in-kernel sockets, send() and
+ * write() are fairly equivalent in performance.
+ */
+#if defined(SOLARIS)
+ PR_ASSERT(0 == flags);
+ while ((rv = write(osfd,buf,amount)) == -1) {
+#else
+ while ((rv = send(osfd,buf,amount,flags)) == -1) {
+#endif
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next send() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
+ rv = -1;
+ goto done;
}
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- /*
- * optimization; if bytes sent is less than "amount" call
- * select before returning. This is because it is likely that
- * the next send() call will return EWOULDBLOCK.
- */
- if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
- && (timeout != PR_INTERVAL_NO_WAIT)) {
- if (_PR_IS_NATIVE_THREAD(me)) {
- if (socket_io_wait(osfd, WRITE_FD, timeout)< 0)
- goto done;
- } else {
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
+ } else {
+ if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
+ rv = -1;
+ goto done;
}
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_SEND_ERROR(err);
- }
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
done:
- return(rv);
+ return(rv);
}
PRInt32 _MD_sendto(
PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while ((rv = sendto(osfd, buf, amount, flags,
- (struct sockaddr *) addr, addrlen)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
goto done;
- }
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_SENDTO_ERROR(err);
- }
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
done:
return(rv);
}
-PRInt32 _MD_writev(PRFileDesc *fd, PRIOVec *iov,
- PRInt32 iov_size, PRIntervalTime timeout)
-{
- PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRInt32 index, amount = 0;
- PRInt32 osfd = fd->secret->md.osfd;
-
- /*
- * Calculate the total number of bytes to be sent; needed for
- * optimization later.
- * We could avoid this if this number was passed in; but it is
- * probably not a big deal because iov_size is usually small (less than
- * 3)
- */
- if (!fd->secret->nonblocking) {
- for (index=0; index<iov_size; index++) {
- amount += iov[index].iov_len;
- }
- }
+PRInt32 _MD_writev(
+ PRFileDesc *fd, PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
- while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
}
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- /*
- * optimization; if bytes sent is less than "amount" call
- * select before returning. This is because it is likely that
- * the next writev() call will return EWOULDBLOCK.
- */
- if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
- && (timeout != PR_INTERVAL_NO_WAIT)) {
- if (_PR_IS_NATIVE_THREAD(me)) {
- if (socket_io_wait(osfd, WRITE_FD, timeout) < 0)
- goto done;
- } else {
- if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
+ } else {
+ if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
+ rv = -1;
+ goto done;
}
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_WRITEV_ERROR(err);
- }
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
done:
return(rv);
}
PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr,
- PRUint32 *addrlen, PRIntervalTime timeout)
+ PRUint32 *addrlen, PRIntervalTime timeout)
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- while ((rv = accept(osfd, (struct sockaddr *) addr,
- (_PRSockLen_t *)addrlen)) == -1) {
- err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
- rv = -1;
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto done;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- goto done;
- }
- } else {
- if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = accept(osfd, (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)
goto done;
- }
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
- } else {
- break;
- }
- }
- if (rv < 0) {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
done:
#ifdef _PR_HAVE_SOCKADDR_LEN
if (rv != -1) {
@@ -1208,7 +1052,7 @@ done:
}
}
#endif /* _PR_HAVE_SOCKADDR_LEN */
- return(rv);
+ return(rv);
}
extern int _connect (int s, const struct sockaddr *name, int namelen);
@@ -1216,11 +1060,11 @@ PRInt32 _MD_connect(
PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
{
PRInt32 rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRThread *me = _PR_MD_CURRENT_THREAD();
PRInt32 osfd = fd->secret->md.osfd;
#ifdef IRIX
extern PRInt32 _MD_irix_connect(
- PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);
+ PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);
#endif
/*
@@ -1254,20 +1098,9 @@ retry:
if (!fd->secret->nonblocking && (err == EINPROGRESS)) {
if (!_PR_IS_NATIVE_THREAD(me)) {
- /*
- * _PR_WaitForFD() may return 0 (timeout or interrupt) or 1.
- */
- rv = _PR_WaitForFD(osfd, PR_POLL_WRITE, timeout);
- if (rv == 0) {
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
return -1;
- }
} else {
/*
* socket_io_wait() may return -1 or 1.
@@ -1303,53 +1136,53 @@ PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
{
PRInt32 rv, err;
- rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_BIND_ERROR(err);
- }
- return(rv);
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+ return(rv);
}
PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
{
PRInt32 rv, err;
- rv = listen(fd->secret->md.osfd, backlog);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_LISTEN_ERROR(err);
- }
- return(rv);
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LISTEN_ERROR(err);
+ }
+ return(rv);
}
PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how)
{
PRInt32 rv, err;
- rv = shutdown(fd->secret->md.osfd, how);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_SHUTDOWN_ERROR(err);
- }
- return(rv);
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SHUTDOWN_ERROR(err);
+ }
+ return(rv);
}
PRInt32 _MD_socketpair(int af, int type, int flags,
- PRInt32 *osfd)
+ PRInt32 *osfd)
{
PRInt32 rv, err;
- rv = socketpair(af, type, flags, osfd);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_SOCKETPAIR_ERROR(err);
- }
- return rv;
+ rv = socketpair(af, type, flags, osfd);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKETPAIR_ERROR(err);
+ }
+ return rv;
}
PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
- PRUint32 *addrlen)
+ PRUint32 *addrlen)
{
PRInt32 rv, err;
@@ -1374,7 +1207,7 @@ PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
}
PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
- PRUint32 *addrlen)
+ PRUint32 *addrlen)
{
PRInt32 rv, err;
@@ -1399,565 +1232,131 @@ PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
}
PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
- PRInt32 optname, char* optval, PRInt32* optlen)
+ PRInt32 optname, char* optval, PRInt32* optlen)
{
PRInt32 rv, err;
- rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_GETSOCKOPT_ERROR(err);
- }
- return rv==0?PR_SUCCESS:PR_FAILURE;
+ rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,
- PRInt32 optname, const char* optval, PRInt32 optlen)
+ PRInt32 optname, const char* optval, PRInt32 optlen)
{
PRInt32 rv, err;
- rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_SETSOCKOPT_ERROR(err);
- }
- return rv==0?PR_SUCCESS:PR_FAILURE;
-}
-
-PR_IMPLEMENT(PRInt32) _MD_pr_poll(PRPollDesc *pds, PRIntn npds,
- PRIntervalTime timeout)
-{
- PRPollDesc *pd, *epd;
- PRPollQueue pq;
- PRInt32 n, err, pdcnt;
- PRIntn is;
- _PRUnixPollDesc *unixpds, *unixpd;
- _PRCPU *io_cpu;
- PRThread *me = _PR_MD_CURRENT_THREAD();
-
- if (0 == npds) {
- PR_Sleep(timeout);
- return 0;
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
- if (_PR_IS_NATIVE_THREAD(me)) {
-#ifndef _PR_USE_POLL
- /*
- * On platforms that don't have poll(), we call select().
- */
- fd_set rd, wt, ex;
- struct timeval tv, *tvp = NULL;
- int maxfd = -1;
- /*
- * For restarting _MD_SELECT() if it is interrupted by a signal.
- * We use these variables to figure out how much time has elapsed
- * and how much of the timeout still remains.
- */
- PRIntervalTime start, elapsed, remaining;
-
- FD_ZERO(&rd);
- FD_ZERO(&wt);
- FD_ZERO(&ex);
-
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
+/************************************************************************/
+#if !defined(_PR_USE_POLL)
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
+/*
+** Scan through io queue and find any bad fd's that triggered the error
+** from _MD_SELECT
+*/
+static void FindBadFDs(void)
+{
+ PRCList *q;
+ PRThread *me = _MD_CURRENT_THREAD();
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
+ q = (_PR_IOQ(me->cpu)).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ pds->out_flags = 0;
+ PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
+ if (pds->in_flags == 0) {
+ continue; /* skip this fd */
}
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
+ if (fcntl(osfd, F_GETFL, 0) == -1) {
+ /* Found a bad descriptor, remove it from the fd_sets. */
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("file descriptor %d is bad", osfd));
+ pds->out_flags = _PR_UNIX_POLL_NVAL;
+ notify = PR_TRUE;
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
}
- osfd = bottom->secret->md.osfd;
-
- if (osfd > maxfd) {
- maxfd = osfd;
- }
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &rd);
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &wt);
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &ex);
- }
}
- if (timeout != PR_INTERVAL_NO_TIMEOUT) {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
- tvp = &tv;
- start = PR_IntervalNow();
- }
-
-retry:
- n = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
- if (n == -1 && errno == EINTR) {
- if (timeout == PR_INTERVAL_NO_TIMEOUT) {
- goto retry;
- } else {
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) {
- n = 0; /* timed out */
- } else {
- remaining = timeout - elapsed;
- tv.tv_sec = PR_IntervalToSeconds(remaining);
- tv.tv_usec = PR_IntervalToMicroseconds(
- remaining - PR_SecondsToInterval(tv.tv_sec));
- goto retry;
- }
- }
- }
-
- if (n > 0) {
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRInt16 out_flags = 0;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- pd->out_flags = 0;
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pd->out_flags = out_flags;
- if (out_flags) {
- n++;
- }
- }
- PR_ASSERT(n > 0);
- } else if (n < 0) {
- err = _MD_ERRNO();
- if (err == EBADF) {
- /* Find the bad fds */
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRFileDesc *bottom = pd->fd;
- pd->out_flags = 0;
- if ((NULL == bottom) || (pd->in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) {
- pd->out_flags = PR_POLL_NVAL;
- n++;
- }
- }
- PR_ASSERT(n > 0);
- } else {
- PR_ASSERT(err != EINTR); /* should have been handled above */
- _PR_MD_MAP_SELECT_ERROR(err);
- }
- }
+ if (notify) {
+ PRIntn pri;
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
- return n;
-#else /* _PR_USE_POLL */
- /*
- * For restarting _MD_POLL() if it is interrupted by a signal.
- * We use these variables to figure out how much time has elapsed
- * and how much of the timeout still remains.
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
*/
- PRIntervalTime start, elapsed, remaining;
- int index, msecs;
- struct pollfd *syspoll;
-
- syspoll = (struct pollfd *) PR_MALLOC(npds * sizeof(struct pollfd));
- if (NULL == syspoll) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return -1;
- }
- for (index = 0; index < npds; index++) {
- PRFileDesc *bottom = pds[index].fd;
-
- if (NULL == bottom) {
- /* make poll() ignore this entry */
- syspoll[index].fd = -1;
- continue;
- }
-
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- syspoll[index].fd = bottom->secret->md.osfd;
-
- syspoll[index].events = 0;
- if (pds[index].in_flags & PR_POLL_READ) {
- syspoll[index].events |= POLLIN;
- }
- if (pds[index].in_flags & PR_POLL_WRITE) {
- syspoll[index].events |= POLLOUT;
- }
- if (pds[index].in_flags & PR_POLL_EXCEPT) {
- syspoll[index].events |= POLLPRI;
- }
- pds[index].out_flags = 0; /* init the result */
- }
- if (timeout == PR_INTERVAL_NO_TIMEOUT) {
- msecs = -1;
- } else {
- msecs = PR_IntervalToMilliseconds(timeout);
- start = PR_IntervalNow();
- }
-
-retry:
- n = _MD_POLL(syspoll, npds, msecs);
- if (n == -1) {
- err = _MD_ERRNO();
- if (err == EINTR) {
- if (timeout == PR_INTERVAL_NO_TIMEOUT) {
- goto retry;
- } else if (timeout == PR_INTERVAL_NO_WAIT) {
- n = 0; /* don't retry, just time out */
- } else {
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) {
- n = 0; /* timed out */
- } else {
- remaining = timeout - elapsed;
- msecs = PR_IntervalToMilliseconds(remaining);
- goto retry;
- }
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
}
- } else {
- _PR_MD_MAP_POLL_ERROR(err);
- }
- } else if (n > 0) {
- for (index = 0; index < npds; index++) {
- if (NULL == pds[index].fd) {
- continue;
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
}
- PR_ASSERT(0 == pds[index].out_flags);
- if (0 != syspoll[index].revents) {
- if (syspoll[index].revents & POLLIN) {
- pds[index].out_flags |= PR_POLL_READ;
- }
- if (syspoll[index].revents & POLLOUT) {
- pds[index].out_flags |= PR_POLL_WRITE;
- }
- if (syspoll[index].revents & POLLPRI) {
- pds[index].out_flags |= PR_POLL_EXCEPT;
- }
- if (syspoll[index].revents & POLLERR) {
- pds[index].out_flags |= PR_POLL_ERR;
- }
- if (syspoll[index].revents & POLLNVAL) {
- pds[index].out_flags |= PR_POLL_NVAL;
- }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
}
}
- }
-
- PR_DELETE(syspoll);
- return n;
-#endif /* _PR_USE_POLL */
- }
- /*
- * XXX
- * PRPollDesc has a PRFileDesc field, fd, while the IOQ
- * is a list of PRPollQueue structures, each of which contains
- * a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
- * the OS file descriptor, osfd, and not a PRFileDesc.
- * So, we have allocate memory for _PRUnixPollDesc structures,
- * copy the flags information from the pds list and have pq
- * point to this list of _PRUnixPollDesc structures.
- *
- * It would be better if the memory allocation can be avoided.
- */
-
- unixpds = (_PRUnixPollDesc*) PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
- if (!unixpds) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return -1;
- }
- unixpd = unixpds;
+ _PR_THREAD_LOCK(pq->thr);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = pq->thr->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
- _PR_INTSOFF(is);
- _PR_MD_IOQ_LOCK();
- _PR_THREAD_LOCK(me);
-
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
- _PR_FAST_INTSON(is);
- PR_DELETE(unixpds);
- return -1;
- }
-
- pdcnt = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
-
- PR_ASSERT(osfd >= 0 || in_flags == 0);
-
- unixpd->osfd = osfd;
- unixpd->in_flags = pd->in_flags;
- unixpd++;
- pdcnt++;
-
-#ifndef _PR_USE_POLL
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
- _PR_FD_READ_CNT(me->cpu)[osfd]++;
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
- (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
- }
-#endif /* _PR_USE_POLL */
- if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
- _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
- }
- if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = timeout;
-
- _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;
-
- pq.pds = unixpds;
- pq.npds = pdcnt;
-
- pq.thr = me;
- io_cpu = me->cpu;
- pq.on_ioq = PR_TRUE;
- pq.timeout = timeout;
- _PR_ADD_TO_IOQ(pq, me->cpu);
- _PR_SLEEPQ_LOCK(me->cpu);
- _PR_ADD_SLEEPQ(me, timeout);
- me->state = _PR_IO_WAIT;
- me->io_pending = PR_TRUE;
- me->io_suspended = PR_FALSE;
- _PR_SLEEPQ_UNLOCK(me->cpu);
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
-
- _PR_MD_WAIT(me, timeout);
-
- me->io_pending = PR_FALSE;
- me->io_suspended = PR_FALSE;
-
- /*
- * This thread should run on the same cpu on which it was blocked; when
- * the IO request times out the fd sets and fd counts for the
- * cpu are updated below.
- */
- PR_ASSERT(me->cpu == io_cpu);
- /*
- * Copy the out_flags from the _PRUnixPollDesc structures to the
- * user's PRPollDesc structures and free the allocated memory
- */
- unixpd = unixpds;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- if ((NULL == pd->fd) || (pd->in_flags == 0)) {
- pd->out_flags = 0;
- continue;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ }
+ _PR_THREAD_UNLOCK(pq->thr);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
}
- pd->out_flags = unixpd->out_flags;
- unixpd++;
- }
- PR_DELETE(unixpds);
-
- /*
- ** If we timed out the pollq might still be on the ioq. Remove it
- ** before continuing.
- */
- if (pq.on_ioq) {
- _PR_MD_IOQ_LOCK();
- /*
- * Need to check pq.on_ioq again
- */
- if (pq.on_ioq == PR_TRUE) {
- PR_REMOVE_LINK(&pq.links);
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- PRInt32 osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
-
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
-#ifndef _PR_USE_POLL
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
-#endif
- }
- _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;
- PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
- }
- _PR_MD_IOQ_UNLOCK();
}
- _PR_INTSON(is);
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- return -1;
- } else {
- n = 0;
- if (pq.on_ioq == PR_FALSE) {
- /* Count the number of ready descriptors */
- while (--npds >= 0) {
- if (pds->out_flags) {
- n++;
- }
- pds++;
- }
- }
- return n;
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
}
}
-
-
-
-
-/************************************************************************/
-
-/*
-** Scan through io queue and find any bad fd's that triggered the error
-** from _MD_SELECT
-*/
-static void FindBadFDs(void)
-{
- PRCList *q;
- PRThread *me = _MD_CURRENT_THREAD();
-
- PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
- q = (_PR_IOQ(me->cpu)).next;
- _PR_IOQ_MAX_OSFD(me->cpu) = -1;
- _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
- while (q != &_PR_IOQ(me->cpu)) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- PRBool notify = PR_FALSE;
- _PRUnixPollDesc *pds = pq->pds;
- _PRUnixPollDesc *epds = pds + pq->npds;
- PRInt32 pq_max_osfd = -1;
-
- q = q->next;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- pds->out_flags = 0;
- PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
- if (pds->in_flags == 0) {
- continue; /* skip this fd */
- }
- if (fcntl(osfd, F_GETFL, 0) == -1) {
- /* Found a bad descriptor, remove it from the fd_sets. */
- PR_LOG(_pr_io_lm, PR_LOG_MAX,
- ("file descriptor %d is bad", osfd));
- pds->out_flags = PR_POLL_NVAL;
- notify = PR_TRUE;
- }
- if (osfd > pq_max_osfd) {
- pq_max_osfd = osfd;
- }
- }
-
- if (notify) {
- PRIntn pri;
- PR_REMOVE_LINK(&pq->links);
- pq->on_ioq = PR_FALSE;
-
- /*
- * Decrement the count of descriptors for each desciptor/event
- * because this I/O request is being removed from the
- * ioq
- */
- pds = pq->pds;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
-#ifndef _PR_USE_POLL
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
-#endif /* !_PR_USE_POLL */
- }
-
- _PR_THREAD_LOCK(pq->thr);
- if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
- _PRCPU *cpu = pq->thr->cpu;
- _PR_SLEEPQ_LOCK(pq->thr->cpu);
- _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
-
- pri = pq->thr->priority;
- pq->thr->state = _PR_RUNNABLE;
-
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(pq->thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- }
- _PR_THREAD_UNLOCK(pq->thr);
- } else {
- if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
- if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
- }
- }
- if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
- if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
- _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
- }
-}
+#endif /* !defined(_PR_USE_POLL) */
/************************************************************************/
@@ -1974,463 +1373,534 @@ static void FindBadFDs(void)
*/
void _MD_PauseCPU(PRIntervalTime ticks)
{
- PRThread *me = _MD_CURRENT_THREAD();
+ PRThread *me = _MD_CURRENT_THREAD();
#ifdef _PR_USE_POLL
- int timeout;
- struct pollfd *pollfds; /* an array of pollfd structures */
- struct pollfd *pollfdPtr; /* a pointer that steps through the array */
- unsigned long npollfds; /* number of pollfd structures in array */
- unsigned long pollfds_size;
- int nfd; /* to hold the return value of poll() */
+ int timeout;
+ struct pollfd *pollfds; /* an array of pollfd structures */
+ struct pollfd *pollfdPtr; /* a pointer that steps through the array */
+ unsigned long npollfds; /* number of pollfd structures in array */
+ unsigned long pollfds_size;
+ int nfd; /* to hold the return value of poll() */
#else
- struct timeval timeout, *tvp;
- fd_set r, w, e;
- fd_set *rp, *wp, *ep;
- PRInt32 max_osfd, nfd;
+ struct timeval timeout, *tvp;
+ fd_set r, w, e;
+ fd_set *rp, *wp, *ep;
+ PRInt32 max_osfd, nfd;
#endif /* _PR_USE_POLL */
- PRInt32 rv;
- PRCList *q;
- PRUint32 min_timeout;
- sigset_t oldset;
+ PRInt32 rv;
+ PRCList *q;
+ PRUint32 min_timeout;
+ sigset_t oldset;
#ifdef IRIX
extern sigset_t ints_off;
#endif
- PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
- _PR_MD_IOQ_LOCK();
+ _PR_MD_IOQ_LOCK();
#ifdef _PR_USE_POLL
- /* Build up the pollfd structure array to wait on */
+ /* Build up the pollfd structure array to wait on */
- /* Find out how many pollfd structures are needed */
- npollfds = _PR_IOQ_OSFD_CNT(me->cpu);
- PR_ASSERT(npollfds >= 0);
+ /* Find out how many pollfd structures are needed */
+ npollfds = _PR_IOQ_OSFD_CNT(me->cpu);
+ PR_ASSERT(npollfds >= 0);
- /*
+ /*
* We use a pipe to wake up a native thread. An fd is needed
* for the pipe and we poll it for reading.
*/
- if (_PR_IS_NATIVE_THREAD_SUPPORTED())
- npollfds++;
-
- /*
- * if the cpu's pollfd array is not big enough, release it and allocate a new one
- */
- if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
- if (_PR_IOQ_POLLFDS(me->cpu) != NULL)
- PR_DELETE(pollfds);
- pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
- pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
- _PR_IOQ_POLLFDS(me->cpu) = pollfds;
- _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
- pollfdPtr = pollfds;
- } else {
- pollfds = _PR_IOQ_POLLFDS(me->cpu);
- pollfdPtr = pollfds;
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ npollfds++;
+#ifdef IRIX
+ /*
+ * On Irix, a second pipe is used to cause the primordial cpu to
+ * wakeup and exit, when the process is exiting because of a call
+ * to exit/PR_ProcessExit.
+ */
+ if (me->cpu->id == 0) {
+ npollfds++;
+ }
+#endif
}
- /*
+ /*
+ * if the cpu's pollfd array is not big enough, release it and allocate a new one
+ */
+ if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
+ if (_PR_IOQ_POLLFDS(me->cpu) != NULL)
+ PR_DELETE(pollfds);
+ pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
+ pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
+ _PR_IOQ_POLLFDS(me->cpu) = pollfds;
+ _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
+ pollfdPtr = pollfds;
+ } else {
+ pollfds = _PR_IOQ_POLLFDS(me->cpu);
+ pollfdPtr = pollfds;
+ }
+
+ /*
* If we need to poll the pipe for waking up a native thread,
* the pipe's fd is the first element in the pollfds array.
*/
- if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
- pollfdPtr->fd = _pr_md_pipefd[0];
- pollfdPtr->events = PR_POLL_READ;
- pollfdPtr++;
- }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ pollfdPtr->fd = _pr_md_pipefd[0];
+ pollfdPtr->events = POLLIN;
+ pollfdPtr++;
+#ifdef IRIX
+ /*
+ * On Irix, the second element is the exit pipe
+ */
+ if (me->cpu->id == 0) {
+ pollfdPtr->fd = _pr_irix_primoridal_cpu_fd[0];
+ pollfdPtr->events = POLLIN;
+ pollfdPtr++;
+ }
+#endif
+ }
- min_timeout = PR_INTERVAL_NO_TIMEOUT;
- for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- _PRUnixPollDesc *pds = pq->pds;
- _PRUnixPollDesc *epds = pds + pq->npds;
+ min_timeout = PR_INTERVAL_NO_TIMEOUT;
+ for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
- if (pq->timeout < min_timeout) {
- min_timeout = pq->timeout;
- }
- for (; pds < epds; pds++, pollfdPtr++) {
- /*
- * Assert that the pollfdPtr pointer does not go
- * beyond the end of the pollfds array
- */
- PR_ASSERT(pollfdPtr < pollfds + npollfds);
- pollfdPtr->fd = pds->osfd;
- /* direct copy of poll flags */
- pollfdPtr->events = pds->in_flags;
- }
- }
- _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;
+ if (pq->timeout < min_timeout) {
+ min_timeout = pq->timeout;
+ }
+ for (; pds < epds; pds++, pollfdPtr++) {
+ /*
+ * Assert that the pollfdPtr pointer does not go
+ * beyond the end of the pollfds array
+ */
+ PR_ASSERT(pollfdPtr < pollfds + npollfds);
+ pollfdPtr->fd = pds->osfd;
+ /* direct copy of poll flags */
+ pollfdPtr->events = pds->in_flags;
+ }
+ }
+ _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;
#else
- /*
+ /*
* assigment of fd_sets
*/
- r = _PR_FD_READ_SET(me->cpu);
- w = _PR_FD_WRITE_SET(me->cpu);
- e = _PR_FD_EXCEPTION_SET(me->cpu);
+ r = _PR_FD_READ_SET(me->cpu);
+ w = _PR_FD_WRITE_SET(me->cpu);
+ e = _PR_FD_EXCEPTION_SET(me->cpu);
- rp = &r;
- wp = &w;
- ep = &e;
+ rp = &r;
+ wp = &w;
+ ep = &e;
- max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
- min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
+ max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
+ min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
#endif /* _PR_USE_POLL */
- /*
+ /*
** Compute the minimum timeout value: make it the smaller of the
** timeouts specified by the i/o pollers or the timeout of the first
** sleeping thread.
*/
- q = _PR_SLEEPQ(me->cpu).next;
+ q = _PR_SLEEPQ(me->cpu).next;
- if (q != &_PR_SLEEPQ(me->cpu)) {
- PRThread *t = _PR_THREAD_PTR(q);
+ if (q != &_PR_SLEEPQ(me->cpu)) {
+ PRThread *t = _PR_THREAD_PTR(q);
- if (t->sleep < min_timeout) {
- min_timeout = t->sleep;
- }
- }
- if (min_timeout > ticks) {
- min_timeout = ticks;
- }
+ if (t->sleep < min_timeout) {
+ min_timeout = t->sleep;
+ }
+ }
+ if (min_timeout > ticks) {
+ min_timeout = ticks;
+ }
#ifdef _PR_USE_POLL
- if (min_timeout == PR_INTERVAL_NO_TIMEOUT)
- timeout = -1;
- else
- timeout = PR_IntervalToMilliseconds(min_timeout);
+ if (min_timeout == PR_INTERVAL_NO_TIMEOUT)
+ timeout = -1;
+ else
+ timeout = PR_IntervalToMilliseconds(min_timeout);
#else
- if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
- tvp = NULL;
- } else {
- timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
- timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
- % PR_USEC_PER_SEC;
- tvp = &timeout;
- }
+ if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
+ timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
+ % PR_USEC_PER_SEC;
+ tvp = &timeout;
+ }
#endif /* _PR_USE_POLL */
- _PR_MD_IOQ_UNLOCK();
- _MD_CHECK_FOR_EXIT();
- /*
+ _PR_MD_IOQ_UNLOCK();
+ _MD_CHECK_FOR_EXIT();
+ /*
* check for i/o operations
*/
#ifndef _PR_NO_CLOCK_TIMER
- /*
+ /*
* Disable the clock interrupts while we are in select, if clock interrupts
* are enabled. Otherwise, when the select/poll calls are interrupted, the
* timer value starts ticking from zero again when the system call is restarted.
*/
#ifdef IRIX
- /*
- * SIGCHLD signal is used on Irix to detect he termination of an
- * sproc by SIGSEGV, SIGBUS or SIGABRT signals when
- * _nspr_terminate_on_error is set.
- */
- if ((!_nspr_noclock) || (_nspr_terminate_on_error))
+ /*
+ * SIGCHLD signal is used on Irix to detect he termination of an
+ * sproc by SIGSEGV, SIGBUS or SIGABRT signals when
+ * _nspr_terminate_on_error is set.
+ */
+ if ((!_nspr_noclock) || (_nspr_terminate_on_error))
#else
- if (!_nspr_noclock)
-#endif /* IRIX */
+ if (!_nspr_noclock)
+#endif /* IRIX */
#ifdef IRIX
- sigprocmask(SIG_BLOCK, &ints_off, &oldset);
+ sigprocmask(SIG_BLOCK, &ints_off, &oldset);
#else
- PR_ASSERT(sigismember(&timer_set, SIGALRM));
- sigprocmask(SIG_BLOCK, &timer_set, &oldset);
-#endif /* IRIX */
+ PR_ASSERT(sigismember(&timer_set, SIGALRM));
+ sigprocmask(SIG_BLOCK, &timer_set, &oldset);
+#endif /* IRIX */
#endif /* !_PR_NO_CLOCK_TIMER */
#ifndef _PR_USE_POLL
- PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));
- nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
+ PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));
+ nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
#else
- nfd = _MD_POLL(pollfds, npollfds, timeout);
+ nfd = _MD_POLL(pollfds, npollfds, timeout);
#endif /* !_PR_USE_POLL */
#ifndef _PR_NO_CLOCK_TIMER
#ifdef IRIX
- if ((!_nspr_noclock) || (_nspr_terminate_on_error))
+ if ((!_nspr_noclock) || (_nspr_terminate_on_error))
#else
- if (!_nspr_noclock)
-#endif /* IRIX */
- sigprocmask(SIG_SETMASK, &oldset, 0);
+ if (!_nspr_noclock)
+#endif /* IRIX */
+ sigprocmask(SIG_SETMASK, &oldset, 0);
#endif /* !_PR_NO_CLOCK_TIMER */
- _MD_CHECK_FOR_EXIT();
- _PR_MD_IOQ_LOCK();
- /*
+ _MD_CHECK_FOR_EXIT();
+
+#ifdef IRIX
+ _PR_MD_primordial_cpu();
+#endif
+
+ _PR_MD_IOQ_LOCK();
+ /*
** Notify monitors that are associated with the selected descriptors.
*/
#ifdef _PR_USE_POLL
- if (nfd > 0) {
- pollfdPtr = pollfds;
- if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if (nfd > 0) {
+ pollfdPtr = pollfds;
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ /*
+ * Assert that the pipe is the first element in the
+ * pollfds array.
+ */
+ PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);
+ if ((pollfds[0].revents & POLLIN) && (nfd == 1)) {
+ /*
+ * woken up by another thread; read all the data
+ * in the pipe to empty the pipe
+ */
+ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,
+ PIPE_BUF)) == PIPE_BUF){
+ }
+ PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));
+ }
+ pollfdPtr++;
+#ifdef IRIX
/*
- * Assert that the pipe is the first element in the
- * pollfds array.
- */
- PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);
- if ((pollfds[0].revents & PR_POLL_READ) && (nfd == 1)) {
- /*
- * woken up by another thread; read all the data
- * in the pipe to empty the pipe
- */
- while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,
- PIPE_BUF)) == PIPE_BUF){
+ * On Irix, check to see if the primordial cpu needs to exit
+ * to cause the process to terminate
+ */
+ if (me->cpu->id == 0) {
+ PR_ASSERT(pollfds[1].fd == _pr_irix_primoridal_cpu_fd[0]);
+ if (pollfdPtr->revents & POLLIN) {
+ if (_pr_irix_process_exit) {
+ /*
+ * process exit due to a call to PR_ProcessExit
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(_pr_irix_process_exit_code);
+ } else {
+ while ((rv = read(_pr_irix_primoridal_cpu_fd[0],
+ _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {
+ }
+ PR_ASSERT(rv > 0);
+ }
}
- PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));
+ pollfdPtr++;
}
- pollfdPtr++;
- }
- for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- PRBool notify = PR_FALSE;
- _PRUnixPollDesc *pds = pq->pds;
- _PRUnixPollDesc *epds = pds + pq->npds;
+#endif
+ }
+ for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
- for (; pds < epds; pds++, pollfdPtr++) {
- /*
- * Assert that the pollfdPtr pointer does not go beyond
- * the end of the pollfds array.
- */
- PR_ASSERT(pollfdPtr < pollfds + npollfds);
- /*
- * Assert that the fd's in the pollfds array (stepped
- * through by pollfdPtr) are in the same order as
- * the fd's in _PR_IOQ() (stepped through by q and pds).
- * This is how the pollfds array was created earlier.
- */
- PR_ASSERT(pollfdPtr->fd == pds->osfd);
- pds->out_flags = pollfdPtr->revents;
- /* Negative fd's are ignored by poll() */
- if (pds->osfd >= 0 && pds->out_flags) {
- notify = PR_TRUE;
- }
- }
- if (notify) {
- PRIntn pri;
- PRThread *thred;
+ for (; pds < epds; pds++, pollfdPtr++) {
+ /*
+ * Assert that the pollfdPtr pointer does not go beyond
+ * the end of the pollfds array.
+ */
+ PR_ASSERT(pollfdPtr < pollfds + npollfds);
+ /*
+ * Assert that the fd's in the pollfds array (stepped
+ * through by pollfdPtr) are in the same order as
+ * the fd's in _PR_IOQ() (stepped through by q and pds).
+ * This is how the pollfds array was created earlier.
+ */
+ PR_ASSERT(pollfdPtr->fd == pds->osfd);
+ pds->out_flags = pollfdPtr->revents;
+ /* Negative fd's are ignored by poll() */
+ if (pds->osfd >= 0 && pds->out_flags) {
+ notify = PR_TRUE;
+ }
+ }
+ if (notify) {
+ PRIntn pri;
+ PRThread *thred;
- PR_REMOVE_LINK(&pq->links);
- pq->on_ioq = PR_FALSE;
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
- thred = pq->thr;
+ thred = pq->thr;
_PR_THREAD_LOCK(thred);
- if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
- _PRCPU *cpu = pq->thr->cpu;
- _PR_SLEEPQ_LOCK(pq->thr->cpu);
- _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
-
- pri = pq->thr->priority;
- pq->thr->state = _PR_RUNNABLE;
-
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(pq->thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- if (_pr_md_idle_cpus > 1)
- _PR_MD_WAKEUP_WAITER(thred);
- }
- _PR_THREAD_UNLOCK(thred);
- _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;
- PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
- }
- }
- } else if (nfd == -1) {
- PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
- }
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = pq->thr->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (_pr_md_idle_cpus > 1)
+ _PR_MD_WAKEUP_WAITER(thred);
+ }
+ _PR_THREAD_UNLOCK(thred);
+ _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;
+ PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
+ }
+ }
+ } else if (nfd == -1) {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
+ }
#else
- if (nfd > 0) {
- q = _PR_IOQ(me->cpu).next;
- _PR_IOQ_MAX_OSFD(me->cpu) = -1;
- _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
- while (q != &_PR_IOQ(me->cpu)) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- PRBool notify = PR_FALSE;
- _PRUnixPollDesc *pds = pq->pds;
- _PRUnixPollDesc *epds = pds + pq->npds;
- PRInt32 pq_max_osfd = -1;
-
- q = q->next;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PRInt16 out_flags = 0;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, rp)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, wp)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
- out_flags |= PR_POLL_EXCEPT;
- }
- pds->out_flags = out_flags;
- if (out_flags) {
- notify = PR_TRUE;
- }
- if (osfd > pq_max_osfd) {
- pq_max_osfd = osfd;
- }
- }
- if (notify == PR_TRUE) {
- PRIntn pri;
- PRThread *thred;
+ if (nfd > 0) {
+ q = _PR_IOQ(me->cpu).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PRInt16 out_flags = 0;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) {
+ out_flags |= _PR_UNIX_POLL_READ;
+ }
+ if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) {
+ out_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
+ out_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ pds->out_flags = out_flags;
+ if (out_flags) {
+ notify = PR_TRUE;
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
+ }
+ }
+ if (notify == PR_TRUE) {
+ PRIntn pri;
+ PRThread *thred;
- PR_REMOVE_LINK(&pq->links);
- pq->on_ioq = PR_FALSE;
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
- /*
- * Decrement the count of descriptors for each desciptor/event
- * because this I/O request is being removed from the
- * ioq
- */
- pds = pq->pds;
- for (; pds < epds; pds++) {
- PRInt32 osfd = pds->osfd;
- PRInt16 in_flags = pds->in_flags;
- PR_ASSERT(osfd >= 0 || in_flags == 0);
- if (in_flags & PR_POLL_READ) {
- if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
- }
- if (in_flags & PR_POLL_WRITE) {
- if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- }
- if (in_flags & PR_POLL_EXCEPT) {
- if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
- }
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
+ */
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
- /*
- * Because this thread can run on a different cpu right
- * after being added to the run queue, do not dereference
- * pq
- */
- thred = pq->thr;
+ /*
+ * Because this thread can run on a different cpu right
+ * after being added to the run queue, do not dereference
+ * pq
+ */
+ thred = pq->thr;
_PR_THREAD_LOCK(thred);
- if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
- _PRCPU *cpu = thred->cpu;
- _PR_SLEEPQ_LOCK(pq->thr->cpu);
- _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
-
- pri = pq->thr->priority;
- pq->thr->state = _PR_RUNNABLE;
-
- pq->thr->cpu = cpu;
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(pq->thr, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- if (_pr_md_idle_cpus > 1)
- _PR_MD_WAKEUP_WAITER(thred);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = thred->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ pq->thr->cpu = cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (_pr_md_idle_cpus > 1)
+ _PR_MD_WAKEUP_WAITER(thred);
+ }
+ _PR_THREAD_UNLOCK(thred);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {
+ /*
+ * woken up by another thread; read all the data
+ * in the pipe to empty the pipe
+ */
+ while ((rv =
+ read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
+ == PIPE_BUF){
+ }
+ PR_ASSERT((rv > 0) ||
+ ((rv == -1) && (errno == EAGAIN)));
+ }
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+#ifdef IRIX
+ if ((me->cpu->id == 0) &&
+ (FD_ISSET(_pr_irix_primoridal_cpu_fd[0], rp))) {
+ if (_pr_irix_process_exit) {
+ /*
+ * process exit due to a call to PR_ProcessExit
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(_pr_irix_process_exit_code);
+ } else {
+ while ((rv = read(_pr_irix_primoridal_cpu_fd[0],
+ _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {
+ }
+ PR_ASSERT(rv > 0);
}
- _PR_THREAD_UNLOCK(thred);
- } else {
- if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
- if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
}
- }
- if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
- if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {
- /*
- * woken up by another thread; read all the data
- * in the pipe to empty the pipe
- */
- while ((rv =
- read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
- == PIPE_BUF){
- }
- PR_ASSERT((rv > 0) ||
- ((rv == -1) && (errno == EAGAIN)));
+ if (me->cpu->id == 0) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_irix_primoridal_cpu_fd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0];
}
- if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
- _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
- }
- } else if (nfd < 0) {
- if (errno == EBADF) {
- FindBadFDs();
- } else {
- PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
- errno));
- }
- } else {
- PR_ASSERT(nfd == 0);
- /*
- * compute the new value of _PR_IOQ_TIMEOUT
- */
- q = _PR_IOQ(me->cpu).next;
- _PR_IOQ_MAX_OSFD(me->cpu) = -1;
- _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
- while (q != &_PR_IOQ(me->cpu)) {
- PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
- _PRUnixPollDesc *pds = pq->pds;
- _PRUnixPollDesc *epds = pds + pq->npds;
- PRInt32 pq_max_osfd = -1;
-
- q = q->next;
- for (; pds < epds; pds++) {
- if (pds->osfd > pq_max_osfd) {
- pq_max_osfd = pds->osfd;
- }
- }
- if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
- _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
- if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
- }
- if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
- if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
- _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
- }
- }
+#endif
+ }
+ } else if (nfd < 0) {
+ if (errno == EBADF) {
+ FindBadFDs();
+ } else {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
+ errno));
+ }
+ } else {
+ PR_ASSERT(nfd == 0);
+ /*
+ * compute the new value of _PR_IOQ_TIMEOUT
+ */
+ q = _PR_IOQ(me->cpu).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ if (pds->osfd > pq_max_osfd) {
+ pq_max_osfd = pds->osfd;
+ }
+ }
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+ }
+ }
#endif /* _PR_USE_POLL */
- _PR_MD_IOQ_UNLOCK();
+ _PR_MD_IOQ_UNLOCK();
}
void _MD_Wakeup_CPUs()
{
- PRInt32 rv, data;
+ PRInt32 rv, data;
- data = 0;
- rv = write(_pr_md_pipefd[1], &data, 1);
+ data = 0;
+ rv = write(_pr_md_pipefd[1], &data, 1);
- while ((rv < 0) && (errno == EAGAIN)) {
- /*
- * pipe full, read all data in pipe to empty it
- */
- while ((rv =
- read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
- == PIPE_BUF) {
- }
- PR_ASSERT((rv > 0) ||
- ((rv == -1) && (errno == EAGAIN)));
- rv = write(_pr_md_pipefd[1], &data, 1);
- }
+ while ((rv < 0) && (errno == EAGAIN)) {
+ /*
+ * pipe full, read all data in pipe to empty it
+ */
+ while ((rv =
+ read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
+ == PIPE_BUF) {
+ }
+ PR_ASSERT((rv > 0) ||
+ ((rv == -1) && (errno == EAGAIN)));
+ rv = write(_pr_md_pipefd[1], &data, 1);
+ }
}
void _MD_InitCPUS()
{
- PRInt32 rv, flags;
- PRThread *me = _MD_CURRENT_THREAD();
+ PRInt32 rv, flags;
+ PRThread *me = _MD_CURRENT_THREAD();
- rv = pipe(_pr_md_pipefd);
- PR_ASSERT(rv == 0);
- _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+ rv = pipe(_pr_md_pipefd);
+ PR_ASSERT(rv == 0);
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
#ifndef _PR_USE_POLL
- FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
+ FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
#endif
- flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
- fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
- flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
- fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
+ fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
+ fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
}
/*
@@ -2438,68 +1908,68 @@ void _MD_InitCPUS()
*/
static void ClockInterruptHandler()
{
- int olderrno;
- PRUintn pri;
- _PRCPU *cpu = _PR_MD_CURRENT_CPU();
- PRThread *me = _MD_CURRENT_THREAD();
+ int olderrno;
+ PRUintn pri;
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+ PRThread *me = _MD_CURRENT_THREAD();
#ifdef SOLARIS
- if (!me || _PR_IS_NATIVE_THREAD(me)) {
- _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;
- return;
- }
+ if (!me || _PR_IS_NATIVE_THREAD(me)) {
+ _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;
+ return;
+ }
#endif
- if (_PR_MD_GET_INTSOFF() != 0) {
- cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
- return;
- }
- _PR_MD_SET_INTSOFF(1);
+ if (_PR_MD_GET_INTSOFF() != 0) {
+ cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
+ return;
+ }
+ _PR_MD_SET_INTSOFF(1);
- olderrno = errno;
- _PR_ClockInterrupt();
- errno = olderrno;
+ olderrno = errno;
+ _PR_ClockInterrupt();
+ errno = olderrno;
- /*
+ /*
** If the interrupt wants a resched or if some other thread at
** the same priority needs the cpu, reschedule.
*/
- pri = me->priority;
- if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {
+ pri = me->priority;
+ if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {
#ifdef _PR_NO_PREEMPT
- cpu->resched = PR_TRUE;
- if (pr_interruptSwitchHook) {
- (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);
- }
+ cpu->resched = PR_TRUE;
+ if (pr_interruptSwitchHook) {
+ (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);
+ }
#else /* _PR_NO_PREEMPT */
- /*
+ /*
** Re-enable unix interrupts (so that we can use
** setjmp/longjmp for context switching without having to
** worry about the signal state)
*/
- sigprocmask(SIG_SETMASK, &empty_set, 0);
- PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));
-
- if(!(me->flags & _PR_IDLE_THREAD)) {
- _PR_THREAD_LOCK(me);
- me->state = _PR_RUNNABLE;
- me->cpu = cpu;
- _PR_RUNQ_LOCK(cpu);
- _PR_ADD_RUNQ(me, cpu, pri);
- _PR_RUNQ_UNLOCK(cpu);
- _PR_THREAD_UNLOCK(me);
- } else
- me->state = _PR_RUNNABLE;
- _MD_SWITCH_CONTEXT(me);
- PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));
+ sigprocmask(SIG_SETMASK, &empty_set, 0);
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));
+
+ if(!(me->flags & _PR_IDLE_THREAD)) {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_RUNNABLE;
+ me->cpu = cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(me, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(me);
+ } else
+ me->state = _PR_RUNNABLE;
+ _MD_SWITCH_CONTEXT(me);
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));
#endif /* _PR_NO_PREEMPT */
- }
- /*
+ }
+ /*
* Because this thread could be running on a different cpu after
* a context switch the current cpu should be accessed and the
* value of the 'cpu' variable should not be used.
*/
- _PR_MD_SET_INTSOFF(0);
+ _PR_MD_SET_INTSOFF(0);
}
/*
@@ -2525,204 +1995,704 @@ static void HPUX9_ClockInterruptHandler(
void _MD_StartInterrupts()
{
- struct itimerval itval;
- char *eval;
+ struct itimerval itval;
+ char *eval;
#ifdef HPUX9
- struct sigvec vec;
+ struct sigvec vec;
- vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler;
- vec.sv_mask = 0;
- vec.sv_flags = 0;
- sigvector(SIGALRM, &vec, 0);
+ vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler;
+ vec.sv_mask = 0;
+ vec.sv_flags = 0;
+ sigvector(SIGALRM, &vec, 0);
#else
- struct sigaction vtact;
+ struct sigaction vtact;
- vtact.sa_handler = (void (*)()) ClockInterruptHandler;
- sigemptyset(&vtact.sa_mask);
- vtact.sa_flags = SA_RESTART;
- sigaction(SIGALRM, &vtact, 0);
+ vtact.sa_handler = (void (*)()) ClockInterruptHandler;
+ sigemptyset(&vtact.sa_mask);
+ vtact.sa_flags = SA_RESTART;
+ sigaction(SIGALRM, &vtact, 0);
#endif /* HPUX9 */
- if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {
- if (atoi(eval) == 0)
- _nspr_noclock = 0;
- else
- _nspr_noclock = 1;
- }
+ if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {
+ if (atoi(eval) == 0)
+ _nspr_noclock = 0;
+ else
+ _nspr_noclock = 1;
+ }
#ifndef _PR_NO_CLOCK_TIMER
- if (!_nspr_noclock) {
- itval.it_interval.tv_sec = 0;
- itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
- itval.it_value = itval.it_interval;
- setitimer(ITIMER_REAL, &itval, 0);
- }
+ if (!_nspr_noclock) {
+ itval.it_interval.tv_sec = 0;
+ itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
+ itval.it_value = itval.it_interval;
+ setitimer(ITIMER_REAL, &itval, 0);
+ }
#endif
}
void _MD_StopInterrupts()
{
- sigprocmask(SIG_BLOCK, &timer_set, 0);
+ sigprocmask(SIG_BLOCK, &timer_set, 0);
+}
+
+void _MD_EnableClockInterrupts()
+{
+ struct itimerval itval;
+ extern PRUintn _pr_numCPU;
+
+ PR_ASSERT(_pr_numCPU == 1);
+ itval.it_interval.tv_sec = 0;
+ itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
+ itval.it_value = itval.it_interval;
+ setitimer(ITIMER_REAL, &itval, 0);
}
void _MD_DisableClockInterrupts()
{
- struct itimerval itval;
- extern PRUintn _pr_numCPU;
+ struct itimerval itval;
+ extern PRUintn _pr_numCPU;
- PR_ASSERT(_pr_numCPU == 1);
- if (!_nspr_noclock) {
- itval.it_interval.tv_sec = 0;
- itval.it_interval.tv_usec = 0;
- itval.it_value = itval.it_interval;
- setitimer(ITIMER_REAL, &itval, 0);
- }
+ PR_ASSERT(_pr_numCPU == 1);
+ itval.it_interval.tv_sec = 0;
+ itval.it_interval.tv_usec = 0;
+ itval.it_value = itval.it_interval;
+ setitimer(ITIMER_REAL, &itval, 0);
}
void _MD_BlockClockInterrupts()
{
- sigprocmask(SIG_BLOCK, &timer_set, 0);
+ sigprocmask(SIG_BLOCK, &timer_set, 0);
}
void _MD_UnblockClockInterrupts()
{
- sigprocmask(SIG_UNBLOCK, &timer_set, 0);
+ sigprocmask(SIG_UNBLOCK, &timer_set, 0);
}
void _MD_MakeNonblock(PRFileDesc *fd)
{
- PRInt32 osfd = fd->secret->md.osfd;
- int flags;
+ PRInt32 osfd = fd->secret->md.osfd;
+ int flags;
- if (osfd <= 2) {
- /* Don't mess around with stdin, stdout or stderr */
- return;
- }
- flags = fcntl(osfd, F_GETFL, 0);
+ if (osfd <= 2) {
+ /* Don't mess around with stdin, stdout or stderr */
+ return;
+ }
+ flags = fcntl(osfd, F_GETFL, 0);
- /*
+ /*
* Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible.
* On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O),
* otherwise connect() still blocks and can be interrupted by SIGALRM.
*/
#ifdef SUNOS4
- fcntl(osfd, F_SETFL, flags | FNDELAY);
+ fcntl(osfd, F_SETFL, flags | FNDELAY);
#else
- fcntl(osfd, F_SETFL, flags | O_NONBLOCK);
+ fcntl(osfd, F_SETFL, flags | O_NONBLOCK);
#endif
- }
+ }
PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode)
{
- PRInt32 osflags;
- PRInt32 rv, err;
+ PRInt32 osflags;
+ PRInt32 rv, err;
- if (flags & PR_RDWR) {
- osflags = O_RDWR;
- } else if (flags & PR_WRONLY) {
- osflags = O_WRONLY;
- } else {
- osflags = O_RDONLY;
- }
+ if (flags & PR_RDWR) {
+ osflags = O_RDWR;
+ } else if (flags & PR_WRONLY) {
+ osflags = O_WRONLY;
+ } else {
+ osflags = O_RDONLY;
+ }
- if (flags & PR_APPEND)
- osflags |= O_APPEND;
- if (flags & PR_TRUNCATE)
- osflags |= O_TRUNC;
- if (flags & PR_SYNC) {
+ if (flags & PR_APPEND)
+ osflags |= O_APPEND;
+ if (flags & PR_TRUNCATE)
+ osflags |= O_TRUNC;
+ if (flags & PR_SYNC) {
#if defined(O_SYNC)
- osflags |= O_SYNC;
+ osflags |= O_SYNC;
#elif defined(O_FSYNC)
- osflags |= O_FSYNC;
+ osflags |= O_FSYNC;
#else
#error "Neither O_SYNC nor O_FSYNC is defined on this platform"
#endif
- }
+ }
/*
** On creations we hold the 'create' lock in order to enforce
** the semantics of PR_Rename. (see the latter for more details)
*/
- if (flags & PR_CREATE_FILE)
+ if (flags & PR_CREATE_FILE)
{
- osflags |= O_CREAT ;
+ osflags |= O_CREAT;
if (NULL !=_pr_rename_lock)
PR_Lock(_pr_rename_lock);
}
- rv = open(name, osflags, mode);
+ rv = _md_iovector._open64(name, osflags, mode);
- if (rv < 0) {
- err = _MD_ERRNO();
- _PR_MD_MAP_OPEN_ERROR(err);
- }
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPEN_ERROR(err);
+ }
if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
PR_Unlock(_pr_rename_lock);
- return rv;
+ return rv;
}
PRIntervalTime intr_timeout_ticks;
#if defined(SOLARIS) || defined(IRIX)
static void sigsegvhandler() {
- fprintf(stderr,"Received SIGSEGV\n");
- fflush(stderr);
+ fprintf(stderr,"Received SIGSEGV\n");
+ fflush(stderr);
pause();
}
static void sigaborthandler() {
- fprintf(stderr,"Received SIGABRT\n");
- fflush(stderr);
+ fprintf(stderr,"Received SIGABRT\n");
+ fflush(stderr);
pause();
}
static void sigbushandler() {
- fprintf(stderr,"Received SIGBUS\n");
- fflush(stderr);
+ fprintf(stderr,"Received SIGBUS\n");
+ fflush(stderr);
pause();
}
#endif /* SOLARIS, IRIX */
#endif /* !defined(_PR_PTHREADS) */
-void _PR_UnixInit()
+PRInt32 _MD_lseek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
+{
+ PRInt32 rv, where;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ where = SEEK_SET;
+ break;
+ case PR_SEEK_CUR:
+ where = SEEK_CUR;
+ break;
+ case PR_SEEK_END:
+ where = SEEK_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = lseek(fd->secret->md.osfd,offset,where);
+ if (rv == -1)
+ {
+ PRInt32 syserr = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(syserr);
+ }
+done:
+ return(rv);
+}
+
+PRInt64 _MD_lseek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
+{
+ PRInt32 where;
+ PRInt64 rv;
+
+ switch (whence)
+ {
+ case PR_SEEK_SET:
+ where = SEEK_SET;
+ break;
+ case PR_SEEK_CUR:
+ where = SEEK_CUR;
+ break;
+ case PR_SEEK_END:
+ where = SEEK_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = minus_one;
+ goto done;
+ }
+ rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where);
+ if (LL_EQ(rv, minus_one))
+ {
+ PRInt32 syserr = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(syserr);
+ }
+done:
+ return rv;
+} /* _MD_lseek64 */
+
+/*
+** _MD_set_fileinfo_times --
+** Set the modifyTime and creationTime of the PRFileInfo
+** structure using the values in struct stat.
+**
+** _MD_set_fileinfo64_times --
+** Set the modifyTime and creationTime of the PRFileInfo64
+** structure using the values in _MDStat64.
+*/
+
+#if defined(_PR_STAT_HAS_ST_ATIM)
+/*
+** struct stat has st_atim, st_mtim, and st_ctim fields of
+** type timestruc_t.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ info->modifyTime = ((PRTime)sb->st_mtim.tv_sec * PR_USEC_PER_SEC);
+ info->modifyTime += (sb->st_mtim.tv_nsec / 1000);
+ info->creationTime = ((PRTime)sb->st_ctim.tv_sec * PR_USEC_PER_SEC);
+ info->creationTime += (sb->st_ctim.tv_nsec / 1000);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ info->modifyTime = ((PRTime)sb->st_mtim.tv_sec * PR_USEC_PER_SEC);
+ info->modifyTime += (sb->st_mtim.tv_nsec / 1000);
+ info->creationTime = ((PRTime)sb->st_ctim.tv_sec * PR_USEC_PER_SEC);
+ info->creationTime += (sb->st_ctim.tv_nsec / 1000);
+}
+#elif defined(_PR_STAT_HAS_ST_ATIMESPEC)
+/*
+** struct stat has st_atimespec, st_mtimespec, and st_ctimespec
+** fields of type struct timespec.
+*/
+#if defined(_PR_TIMESPEC_HAS_TS_SEC)
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#else /* _PR_TIMESPEC_HAS_TS_SEC */
+/*
+** The POSIX timespec structure has tv_sec and tv_nsec.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#endif /* _PR_TIMESPEC_HAS_TS_SEC */
+#elif defined(_PR_STAT_HAS_ONLY_ST_ATIME)
+/*
+** struct stat only has st_atime, st_mtime, and st_ctime fields
+** of type time_t.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 s, s2us;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, sb->st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb->st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 s, s2us;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, sb->st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb->st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+}
+#else
+#error "I don't know yet"
+#endif
+
+static int _MD_convert_stat_to_fileinfo(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ if (S_IFREG & sb->st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb->st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+#if defined(_PR_HAVE_LARGE_OFF_T)
+ if (0x7fffffffL < sb->st_size)
+ {
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ return -1;
+ }
+#endif /* defined(_PR_HAVE_LARGE_OFF_T) */
+ info->size = sb->st_size;
+
+ _MD_set_fileinfo_times(sb, info);
+ return 0;
+} /* _MD_convert_stat_to_fileinfo */
+
+static int _MD_convert_stat64_to_fileinfo64(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
{
- struct sigaction sigact;
- int rv;
+ if (S_IFREG & sb->st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb->st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ LL_I2L(info->size, sb->st_size);
+
+ _MD_set_fileinfo64_times(sb, info);
+ return 0;
+} /* _MD_convert_stat64_to_fileinfo64 */
- sigemptyset(&timer_set);
+PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = stat(fn, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat_to_fileinfo(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
+{
+ _MDStat64 sb;
+ PRInt32 rv = _md_iovector._stat64(fn, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
+{
+ struct stat sb;
+ PRInt32 rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat_to_fileinfo(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ _MDStat64 sb;
+ PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
+ return rv;
+}
+
+struct _MD_IOVector _md_iovector;
+
+/*
+** These implementations are to emulate large file routines on systems that
+** don't have them. Their goal is to check in case overflow occurs. Otherwise
+** they will just operate as normal using 32-bit file routines.
+**
+** The checking might be pre- or post-op, depending on the semantics.
+*/
+
+#if defined(SOLARIS2_5)
+
+static PRIntn _MD_solaris25_fstat64(PRIntn osfd, _MDStat64 *buf)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = fstat(osfd, &sb);
+ if (rv >= 0)
+ {
+ /*
+ ** I'm only copying the fields that are immediately needed.
+ ** If somebody else calls this function, some of the fields
+ ** may not be defined.
+ */
+ (void)memset(buf, 0, sizeof(_MDStat64));
+ buf->st_mode = sb.st_mode;
+ buf->st_ctim = sb.st_ctim;
+ buf->st_mtim = sb.st_mtim;
+ buf->st_size = sb.st_size;
+ }
+ return rv;
+} /* _MD_solaris25_fstat64 */
+
+static PRIntn _MD_solaris25_stat64(const char *fn, _MDStat64 *buf)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = stat(fn, &sb);
+ if (rv >= 0)
+ {
+ /*
+ ** I'm only copying the fields that are immediately needed.
+ ** If somebody else calls this function, some of the fields
+ ** may not be defined.
+ */
+ (void)memset(buf, 0, sizeof(_MDStat64));
+ buf->st_mode = sb.st_mode;
+ buf->st_ctim = sb.st_ctim;
+ buf->st_mtim = sb.st_mtim;
+ buf->st_size = sb.st_size;
+ }
+ return rv;
+} /* _MD_solaris25_stat64 */
+#endif /* defined(SOLARIS2_5) */
+
+#if defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5)
+
+static PRIntn _MD_Unix_lockf64(PRIntn osfd, PRIntn function, PRInt64 size)
+{
+#if defined(RHAPSODY) || defined(BSDI)
+ /* No lockf */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+#else
+ PRInt64 desired, maxoff;
+ PRInt32 current = lseek(osfd, SEEK_CUR, 0);
+
+ LL_I2L(maxoff, 0x7fffffff);
+ LL_I2L(desired, current);
+ LL_ADD(desired, desired, size);
+ if (LL_CMP(desired, <=, maxoff))
+ {
+ off_t offset;
+ LL_L2I(offset, size);
+ return lockf(osfd, function, offset);
+ }
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ return -1;
+#endif
+} /* _MD_Unix_lockf64 */
+
+static PRInt64 _MD_Unix_lseek64(PRIntn osfd, PRInt64 offset, PRIntn whence)
+{
+ PRUint64 maxoff;
+ PRInt64 rv = minus_one;
+ LL_I2L(maxoff, 0x7fffffff);
+ if (LL_CMP(offset, <=, maxoff))
+ {
+ off_t off;
+ LL_L2I(off, offset);
+ LL_I2L(rv, lseek(osfd, off, whence));
+ }
+ else errno = EFBIG; /* we can't go there */
+ return rv;
+} /* _MD_Unix_lseek64 */
+
+static void* _MD_Unix_mmap64(
+ void *addr, PRSize len, PRIntn prot, PRIntn flags,
+ PRIntn fildes, PRInt64 offset)
+{
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ return NULL;
+} /* _MD_Unix_mmap64 */
+#endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */
+
+#if defined(IRIX)
+
+/*
+** This function emulates a lock64 for IRIX using fcntl calls. It is a true
+** 64-bit operation, just a different system API to get it.
+*/
+static PRIntn _MD_irix_lockf64(PRIntn osfd, PRIntn function, PRInt64 size)
+{
+#if 1
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ PR_NOT_REACHED("NOT IMPLEMENTED");
+ return -1;
+#else
+ flock64_t lock;
+ /* $$$ have no idea what I'm doing $$$ */
+ lock.l_type = function;
+ lock.l_whence = SEEK_CUR;
+ lock.l_start = 0;
+ lock.l_len = size;
+
+ return fcntl(osfd, F_SETLKW64, &lock);
+#endif
+} /* _MD_irix_lockf64 */
+
+#endif /* defined(IRIX) */
+
+static void _PR_InitIOV(void)
+{
+#if defined(SOLARIS2_5)
+ PRLibrary *lib;
+ void *open64_func;
+
+ open64_func = PR_FindSymbolAndLibrary("open64", &lib);
+ if (NULL != open64_func)
+ {
+ PR_ASSERT(NULL != lib);
+ _md_iovector._open64 = (_MD_Open64)open64_func;
+ _md_iovector._mmap64 = (_MD_Mmap64)PR_FindSymbol(lib, "mmap64");
+ _md_iovector._fstat64 = (_MD_Fstat64)PR_FindSymbol(lib, "fstat64");
+ _md_iovector._stat64 = (_MD_Stat64)PR_FindSymbol(lib, "stat64");
+ _md_iovector._lockf64 = (_MD_Lockf64)PR_FindSymbol(lib, "lockf64");
+ _md_iovector._lseek64 = (_MD_Lseek64)PR_FindSymbol(lib, "lseek64");
+ (void)PR_UnloadLibrary(lib);
+ }
+ else
+ {
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = _MD_Unix_mmap64;
+ _md_iovector._fstat64 = _MD_solaris25_fstat64;
+ _md_iovector._stat64 = _MD_solaris25_stat64;
+ _md_iovector._lockf64 = _MD_Unix_lockf64;
+ _md_iovector._lseek64 = _MD_Unix_lseek64;
+ }
+#elif defined(_PR_NO_LARGE_FILES)
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = _MD_Unix_mmap64;
+ _md_iovector._fstat64 = fstat;
+ _md_iovector._stat64 = stat;
+ _md_iovector._lockf64 = _MD_Unix_lockf64;
+ _md_iovector._lseek64 = _MD_Unix_lseek64;
+#elif defined(_PR_HAVE_OFF64_T)
+ _md_iovector._open64 = open64;
+ _md_iovector._mmap64 = mmap64;
+ _md_iovector._fstat64 = fstat64;
+ _md_iovector._stat64 = stat64;
+
+/*
+** $$$ IRIX does not have a lockf64. One must fabricate it from fcntl
+** calls with 64 bit arguments.
+*/
+#if defined(IRIX)
+ _md_iovector._lockf64 = _MD_irix_lockf64;
+#else
+ _md_iovector._lockf64 = lockf64;
+#endif
+ _md_iovector._lseek64 = lseek64;
+#elif defined(_PR_HAVE_LARGE_OFF_T)
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = mmap;
+ _md_iovector._fstat64 = fstat;
+ _md_iovector._stat64 = stat;
+ _md_iovector._lockf64 = lockf;
+ _md_iovector._lseek64 = lseek;
+#else
+#error "I don't know yet"
+#endif
+ LL_I2L(minus_one, -1);
+} /* _PR_InitIOV */
+
+void _PR_UnixInit(void)
+{
+ struct sigaction sigact;
+ int rv;
+
+ sigemptyset(&timer_set);
#if !defined(_PR_PTHREADS)
- sigaddset(&timer_set, SIGALRM);
- sigemptyset(&empty_set);
- intr_timeout_ticks =
- PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);
+ sigaddset(&timer_set, SIGALRM);
+ sigemptyset(&empty_set);
+ intr_timeout_ticks =
+ PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);
#if defined(SOLARIS) || defined(IRIX)
if (getenv("NSPR_SIGSEGV_HANDLE")) {
- sigact.sa_handler = sigsegvhandler;
- sigact.sa_flags = 0;
- sigact.sa_mask = timer_set;
- sigaction(SIGSEGV, &sigact, 0);
- }
+ sigact.sa_handler = sigsegvhandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGSEGV, &sigact, 0);
+ }
if (getenv("NSPR_SIGABRT_HANDLE")) {
- sigact.sa_handler = sigaborthandler;
- sigact.sa_flags = 0;
- sigact.sa_mask = timer_set;
- sigaction(SIGABRT, &sigact, 0);
- }
+ sigact.sa_handler = sigaborthandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGABRT, &sigact, 0);
+ }
if (getenv("NSPR_SIGBUS_HANDLE")) {
- sigact.sa_handler = sigbushandler;
- sigact.sa_flags = 0;
- sigact.sa_mask = timer_set;
- sigaction(SIGBUS, &sigact, 0);
- }
+ sigact.sa_handler = sigbushandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGBUS, &sigact, 0);
+ }
#endif
#endif /* !defined(_PR_PTHREADS) */
@@ -2743,18 +2713,19 @@ void _PR_UnixInit()
PR_ASSERT(0 == rv);
}
#else
- sigact.sa_handler = SIG_IGN;
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- rv = sigaction(SIGPIPE, &sigact, 0);
- PR_ASSERT(0 == rv);
+ sigact.sa_handler = SIG_IGN;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ rv = sigaction(SIGPIPE, &sigact, 0);
+ PR_ASSERT(0 == rv);
#endif /* HPUX && _PR_DCETHREADS */
- _pr_rename_lock = PR_NewLock();
- PR_ASSERT(NULL != _pr_rename_lock);
- _pr_Xfe_mon = PR_NewMonitor();
- PR_ASSERT(NULL != _pr_Xfe_mon);
+ _pr_rename_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_rename_lock);
+ _pr_Xfe_mon = PR_NewMonitor();
+ PR_ASSERT(NULL != _pr_Xfe_mon);
+ _PR_InitIOV(); /* one last hack */
}
/*
@@ -2764,77 +2735,75 @@ void _PR_UnixInit()
* called by _PR_InitSegs(), which in turn is called by
* PR_Init().
*/
-void _MD_InitSegs()
+void _MD_InitSegs(void)
{
#ifdef DEBUG
- /*
+ /*
** Disable using mmap(2) if NSPR_NO_MMAP is set
*/
- if (getenv("NSPR_NO_MMAP")) {
- _pr_zero_fd = -2;
- return;
- }
+ if (getenv("NSPR_NO_MMAP")) {
+ _pr_zero_fd = -2;
+ return;
+ }
#endif
- _pr_zero_fd = open("/dev/zero",O_RDWR , 0);
- _pr_md_lock = PR_NewLock();
+ _pr_zero_fd = open("/dev/zero",O_RDWR , 0);
+ _pr_md_lock = PR_NewLock();
}
PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
{
- static char *lastaddr = (char*) _PR_STACK_VMBASE;
- PRStatus retval = PR_SUCCESS;
- int prot;
- void *rv;
+ static char *lastaddr = (char*) _PR_STACK_VMBASE;
+ PRStatus retval = PR_SUCCESS;
+ int prot;
+ void *rv;
- PR_ASSERT(seg != 0);
- PR_ASSERT(size != 0);
+ PR_ASSERT(seg != 0);
+ PR_ASSERT(size != 0);
- PR_Lock(_pr_md_lock);
- if (_pr_zero_fd < 0) {
+ PR_Lock(_pr_md_lock);
+ if (_pr_zero_fd < 0) {
from_heap:
- seg->vaddr = PR_MALLOC(size);
- if (!seg->vaddr) {
- retval = PR_FAILURE;
- }
- else {
- seg->size = size;
- seg->access = PR_SEGMENT_RDWR;
- }
- goto exit;
- }
+ seg->vaddr = PR_MALLOC(size);
+ if (!seg->vaddr) {
+ retval = PR_FAILURE;
+ }
+ else {
+ seg->size = size;
+ }
+ goto exit;
+ }
- prot = PROT_READ|PROT_WRITE;
- /*
- * On Alpha Linux, the user-level thread stack needs
- * to be made executable because longjmp/signal seem
- * to put machine instructions on the stack.
- */
+ prot = PROT_READ|PROT_WRITE;
+ /*
+ * On Alpha Linux, the user-level thread stack needs
+ * to be made executable because longjmp/signal seem
+ * to put machine instructions on the stack.
+ */
#if defined(LINUX) && defined(__alpha)
- prot |= PROT_EXEC;
+ prot |= PROT_EXEC;
#endif
- rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,
- _MD_MMAP_FLAGS,
- _pr_zero_fd, 0);
- if (rv == (void*)-1) {
- goto from_heap;
- }
- lastaddr += size;
- seg->vaddr = rv;
- seg->size = size;
- seg->access = PR_SEGMENT_RDWR;
- seg->flags = _PR_SEG_VM;
+ rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,
+ _MD_MMAP_FLAGS,
+ _pr_zero_fd, 0);
+ if (rv == (void*)-1) {
+ goto from_heap;
+ }
+ lastaddr += size;
+ seg->vaddr = rv;
+ seg->size = size;
+ seg->flags = _PR_SEG_VM;
exit:
- PR_Unlock(_pr_md_lock);
- return retval;
+ PR_Unlock(_pr_md_lock);
+ return retval;
}
void _MD_FreeSegment(PRSegment *seg)
{
- if (seg->flags & _PR_SEG_VM)
- (void) munmap(seg->vaddr, seg->size);
- else
- PR_DELETE(seg->vaddr);
+ if (seg->flags & _PR_SEG_VM)
+ (void) munmap(seg->vaddr, seg->size);
+ else
+ PR_DELETE(seg->vaddr);
}
/*
@@ -2854,159 +2823,159 @@ void _MD_FreeSegment(PRSegment *seg)
PR_IMPLEMENT(PRTime)
PR_Now(void)
{
- struct timeval tv;
- PRInt64 s, us, s2us;
+ struct timeval tv;
+ PRInt64 s, us, s2us;
- GETTIMEOFDAY(&tv);
- LL_I2L(s2us, PR_USEC_PER_SEC);
- LL_I2L(s, tv.tv_sec);
- LL_I2L(us, tv.tv_usec);
- LL_MUL(s, s, s2us);
- LL_ADD(s, s, us);
- return s;
+ GETTIMEOFDAY(&tv);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, tv.tv_sec);
+ LL_I2L(us, tv.tv_usec);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, us);
+ return s;
}
PRIntervalTime _PR_UNIX_GetInterval()
{
- struct timeval time;
- PRIntervalTime ticks;
+ struct timeval time;
+ PRIntervalTime ticks;
- (void)GETTIMEOFDAY(&time); /* fallicy of course */
- ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
- ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
- return ticks;
+ (void)GETTIMEOFDAY(&time); /* fallicy of course */
+ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
+ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
+ return ticks;
} /* _PR_SUNOS_GetInterval */
PRIntervalTime _PR_UNIX_TicksPerSecond()
{
- return 1000; /* this needs some work :) */
+ return 1000; /* this needs some work :) */
}
/*
* _PR_UnixTransmitFile
*
- * Send file fd across socket sd. If headers is non-NULL, 'hlen'
- * bytes of headers is sent before sending the file.
+ * Send file fd across socket sd. If headers is non-NULL, 'hlen'
+ * bytes of headers is sent before sending the file.
*
- * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
- *
- * return number of bytes sent or -1 on error
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
*
*/
-#define TRANSMITFILE_MMAP_CHUNK (256 * 1024)
+#define TRANSMITFILE_MMAP_CHUNK (256 * 1024)
PR_IMPLEMENT(PRInt32) _PR_UnixTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
PRIntervalTime timeout)
{
- PRInt32 rv, count = 0;
- PRInt32 len, index = 0;
- struct stat statbuf;
- struct PRIOVec iov[2];
- void *addr;
- PRInt32 err;
+ PRInt32 rv, count = 0;
+ PRInt32 len, index = 0;
+ struct stat statbuf;
+ struct PRIOVec iov[2];
+ void *addr;
+ PRInt32 err;
- /* Get file size */
- if (fstat(fd->secret->md.osfd, &statbuf) == -1) {
+ /* Get file size */
+ if (fstat(fd->secret->md.osfd, &statbuf) == -1) {
err = _MD_ERRNO();
- switch (err) {
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case EFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
- case EINTR:
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
- break;
- case ETIMEDOUT:
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ETIMEDOUT:
#ifdef ENOLINK
- case ENOLINK:
+ case ENOLINK:
#endif
- PR_SetError(PR_REMOTE_FILE_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
- count = -1;
- goto done;
- }
- /*
- * If the file is large, mmap and send the file in chunks so as
- * to not consume too much virtual address space
- */
- len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
- TRANSMITFILE_MMAP_CHUNK;
- /*
- * Map in (part of) file. Take care of zero-length files.
- */
- if (len) {
- addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
- fd->secret->md.osfd, 0);
-
- if (addr == (void*)-1) {
- _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
- count = -1;
- goto done;
- }
- }
- /*
- * send headers, first, followed by the file
- */
- if (hlen) {
- iov[index].iov_base = (char *) headers;
- iov[index].iov_len = hlen;
- index++;
- }
- iov[index].iov_base = (char*)addr;
- iov[index].iov_len = len;
- index++;
- rv = PR_Writev(sd, iov, index, timeout);
- if (len)
- munmap(addr,len);
- if (rv >= 0) {
- PR_ASSERT(rv == hlen + len);
- statbuf.st_size -= len;
- count += rv;
- } else {
- count = -1;
- goto done;
- }
- /*
- * send remaining bytes of the file, if any
- */
- len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
- TRANSMITFILE_MMAP_CHUNK;
- while (len > 0) {
- /*
- * Map in (part of) file
- */
- PR_ASSERT((count - hlen) % TRANSMITFILE_MMAP_CHUNK == 0);
- addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
- fd->secret->md.osfd, count - hlen);
-
- if (addr == (void*)-1) {
- _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
- count = -1;
- goto done;
- }
- rv = PR_Send(sd, addr, len, 0, timeout);
- munmap(addr,len);
- if (rv >= 0) {
- PR_ASSERT(rv == len);
- statbuf.st_size -= rv;
- count += rv;
- len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ?
- statbuf.st_size : TRANSMITFILE_MMAP_CHUNK;
- } else {
- count = -1;
- goto done;
- }
- }
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+ count = -1;
+ goto done;
+ }
+ /*
+ * If the file is large, mmap and send the file in chunks so as
+ * to not consume too much virtual address space
+ */
+ len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
+ TRANSMITFILE_MMAP_CHUNK;
+ /*
+ * Map in (part of) file. Take care of zero-length files.
+ */
+ if (len) {
+ addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
+ fd->secret->md.osfd, 0);
+
+ if (addr == (void*)-1) {
+ _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
+ count = -1;
+ goto done;
+ }
+ }
+ /*
+ * send headers, first, followed by the file
+ */
+ if (hlen) {
+ iov[index].iov_base = (char *) headers;
+ iov[index].iov_len = hlen;
+ index++;
+ }
+ iov[index].iov_base = (char*)addr;
+ iov[index].iov_len = len;
+ index++;
+ rv = PR_Writev(sd, iov, index, timeout);
+ if (len)
+ munmap(addr,len);
+ if (rv >= 0) {
+ PR_ASSERT(rv == hlen + len);
+ statbuf.st_size -= len;
+ count += rv;
+ } else {
+ count = -1;
+ goto done;
+ }
+ /*
+ * send remaining bytes of the file, if any
+ */
+ len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ? statbuf.st_size :
+ TRANSMITFILE_MMAP_CHUNK;
+ while (len > 0) {
+ /*
+ * Map in (part of) file
+ */
+ PR_ASSERT((count - hlen) % TRANSMITFILE_MMAP_CHUNK == 0);
+ addr = mmap((caddr_t) 0, len, PROT_READ, MAP_PRIVATE,
+ fd->secret->md.osfd, count - hlen);
+
+ if (addr == (void*)-1) {
+ _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
+ count = -1;
+ goto done;
+ }
+ rv = PR_Send(sd, addr, len, 0, timeout);
+ munmap(addr,len);
+ if (rv >= 0) {
+ PR_ASSERT(rv == len);
+ statbuf.st_size -= rv;
+ count += rv;
+ len = statbuf.st_size < TRANSMITFILE_MMAP_CHUNK ?
+ statbuf.st_size : TRANSMITFILE_MMAP_CHUNK;
+ } else {
+ count = -1;
+ goto done;
+ }
+ }
done:
- if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
- PR_Close(sd);
- return count;
+ if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
+ PR_Close(sd);
+ return count;
}
#if defined(HPUX11) && !defined(_PR_PTHREADS)
@@ -3014,12 +2983,12 @@ done:
/*
* _PR_HPUXTransmitFile
*
- * Send file fd across socket sd. If headers is non-NULL, 'hlen'
- * bytes of headers is sent before sending the file.
+ * Send file fd across socket sd. If headers is non-NULL, 'hlen'
+ * bytes of headers is sent before sending the file.
*
- * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
- *
- * return number of bytes sent or -1 on error
+ * 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 HP-UX B.11.00.
@@ -3079,7 +3048,7 @@ _PR_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
}
continue; /* retry */
}
- if (err != EAGAIN && err != EWOULDBLOCK) {
+ if (err != EAGAIN && err != EWOULDBLOCK) {
_MD_hpux_map_sendfile_error(err);
return -1;
}
@@ -3094,20 +3063,9 @@ _PR_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
* the next sendfile() call will return EWOULDBLOCK.
*/
if (!_PR_IS_NATIVE_THREAD(me)) {
- if (_PR_WaitForFD(sd->secret->md.osfd,
- PR_POLL_WRITE, timeout) == 0) {
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- } else {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
+ if ((rv = local_io_wait(sd->secret->md.osfd,
+ _PR_UNIX_POLL_WRITE, timeout)) < 0)
return -1;
- } else if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
- return -1;
- }
} else {
if (socket_io_wait(sd->secret->md.osfd, WRITE_FD, timeout)< 0) {
return -1;
@@ -3142,71 +3100,72 @@ _PR_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
#if !defined(_PR_PTHREADS)
/*
-** Wait for I/O on a single descriptor.
+ * Wait for I/O on multiple descriptors.
*
- * return 0, if timed-out or interrupted, else return 1
-*/
-PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
+ * Return 0 if timed out, return -1 if interrupted,
+ * else return the number of ready descriptors.
+ */
+PRInt32 _PR_WaitForMultipleFDs(
+ _PRUnixPollDesc *unixpds,
+ PRInt32 pdcnt,
+ PRIntervalTime timeout)
{
- _PRUnixPollDesc pd;
PRPollQueue pq;
PRIntn is;
- PRInt32 rv = 1;
- _PRCPU *io_cpu;
+ PRInt32 rv;
+ _PRCPU *io_cpu;
+ _PRUnixPollDesc *unixpd, *eunixpd;
PRThread *me = _PR_MD_CURRENT_THREAD();
PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
- PR_LOG(_pr_io_lm, PR_LOG_MIN,
- ("waiting to %s on osfd=%d",
- (how == PR_POLL_READ) ? "read" : "write",
- osfd));
- if (timeout == PR_INTERVAL_NO_WAIT) return 0;
-
- pd.osfd = osfd;
- pd.in_flags = how;
- pd.out_flags = 0;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
- pq.pds = &pd;
- pq.npds = 1;
+ pq.pds = unixpds;
+ pq.npds = pdcnt;
_PR_INTSOFF(is);
_PR_MD_IOQ_LOCK();
_PR_THREAD_LOCK(me);
- if (_PR_PENDING_INTERRUPT(me)) {
- _PR_THREAD_UNLOCK(me);
- _PR_MD_IOQ_UNLOCK();
- _PR_FAST_INTSON(is);
- return 0;
- }
-
pq.thr = me;
- io_cpu = me->cpu;
+ io_cpu = me->cpu;
pq.on_ioq = PR_TRUE;
pq.timeout = timeout;
_PR_ADD_TO_IOQ(pq, me->cpu);
-#ifndef _PR_USE_POLL
- if (how == PR_POLL_READ) {
- FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
- (_PR_FD_READ_CNT(me->cpu))[osfd]++;
- } else if (how == PR_POLL_WRITE) {
- FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
- (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
- } else {
- FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
- }
-#endif /* _PR_USE_POLL */
+#if !defined(_PR_USE_POLL)
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ PRInt32 osfd = unixpd->osfd;
+ if (unixpd->in_flags & _PR_UNIX_POLL_READ) {
+ FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
+ _PR_FD_READ_CNT(me->cpu)[osfd]++;
+ }
+ if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) {
+ FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
+ }
+ if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) {
+ FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
+ }
+ if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) {
+ _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
+ }
+ }
+#endif /* !defined(_PR_USE_POLL) */
- if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
- _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
- if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
- _PR_IOQ_TIMEOUT(me->cpu) = timeout;
+ if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) {
+ _PR_IOQ_TIMEOUT(me->cpu) = timeout;
+ }
- _PR_IOQ_OSFD_CNT(me->cpu) += 1;
-
+ _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;
+
_PR_SLEEPQ_LOCK(me->cpu);
_PR_ADD_SLEEPQ(me, timeout);
me->state = _PR_IO_WAIT;
@@ -3217,53 +3176,84 @@ PRInt32 _PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
_PR_MD_IOQ_UNLOCK();
_PR_MD_WAIT(me, timeout);
+
me->io_pending = PR_FALSE;
me->io_suspended = PR_FALSE;
- /*
- * This thread should run on the same cpu on which it was blocked; when
- * the IO request times out the fd sets and fd counts for the
- * cpu are updated below.
- */
- PR_ASSERT(me->cpu == io_cpu);
+ /*
+ * This thread should run on the same cpu on which it was blocked; when
+ * the IO request times out the fd sets and fd counts for the
+ * cpu are updated below.
+ */
+ PR_ASSERT(me->cpu == io_cpu);
/*
** If we timed out the pollq might still be on the ioq. Remove it
** before continuing.
*/
if (pq.on_ioq) {
- _PR_MD_IOQ_LOCK();
- /*
- * Need to check pq.on_ioq again
- */
+ _PR_MD_IOQ_LOCK();
+ /*
+ * Need to check pq.on_ioq again
+ */
if (pq.on_ioq) {
- PR_REMOVE_LINK(&pq.links);
+ PR_REMOVE_LINK(&pq.links);
#ifndef _PR_USE_POLL
- if (how == PR_POLL_READ) {
- if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
-
- } else if (how == PR_POLL_WRITE) {
- if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
- } else {
- if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
- FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
- }
-#endif /* _PR_USE_POLL */
- PR_ASSERT(pq.npds == 1);
- _PR_IOQ_OSFD_CNT(me->cpu) -= 1;
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ PRInt32 osfd = unixpd->osfd;
+ PRInt16 in_flags = unixpd->in_flags;
+
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+#endif /* _PR_USE_POLL */
+ PR_ASSERT(pq.npds == pdcnt);
+ _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;
+ PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
}
- _PR_MD_IOQ_UNLOCK();
- rv = 0;
+ _PR_MD_IOQ_UNLOCK();
}
- _PR_FAST_INTSON(is);
- return(rv);
+ /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */
+ if (1 == pdcnt) {
+ _PR_FAST_INTSON(is);
+ } else {
+ _PR_INTSON(is);
+ }
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ rv = 0;
+ if (pq.on_ioq == PR_FALSE) {
+ /* Count the number of ready descriptors */
+ while (--pdcnt >= 0) {
+ if (unixpds->out_flags != 0) {
+ rv++;
+ }
+ unixpds++;
+ }
+ }
+
+ return rv;
}
/*
* Unblock threads waiting for I/O
- * used when interrupting threads
+ * used when interrupting threads
*
* NOTE: The thread lock should held when this function is called.
* On return, the thread lock is released.
@@ -3273,9 +3263,9 @@ void _PR_Unblock_IO_Wait(PRThread *thr)
int pri = thr->priority;
_PRCPU *cpu = thr->cpu;
- /*
- * GLOBAL threads wakeup periodically to check for interrupt
- */
+ /*
+ * GLOBAL threads wakeup periodically to check for interrupt
+ */
if (_PR_IS_NATIVE_THREAD(thr)) {
_PR_THREAD_UNLOCK(thr);
return;
@@ -3338,34 +3328,34 @@ int _MD_unix_get_nonblocking_connect_error(int osfd)
** in a pre-emptive threaded environment, we need to use a lock.
*/
-void PR_XLock()
+void PR_XLock(void)
{
- PR_EnterMonitor(_pr_Xfe_mon);
+ PR_EnterMonitor(_pr_Xfe_mon);
}
-void PR_XUnlock()
+void PR_XUnlock(void)
{
- PR_ExitMonitor(_pr_Xfe_mon);
+ PR_ExitMonitor(_pr_Xfe_mon);
}
-PRBool PR_XIsLocked()
+PRBool PR_XIsLocked(void)
{
- return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
+ return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
}
void PR_XWait(int ms)
{
- PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
+ PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
}
void PR_XNotify(void)
{
- PR_Notify(_pr_Xfe_mon);
+ PR_Notify(_pr_Xfe_mon);
}
void PR_XNotifyAll(void)
{
- PR_NotifyAll(_pr_Xfe_mon);
+ PR_NotifyAll(_pr_Xfe_mon);
}
#ifdef HAVE_BSD_FLOCK
@@ -3375,68 +3365,68 @@ void PR_XNotifyAll(void)
PR_IMPLEMENT(PRStatus)
_MD_LockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = flock(f, LOCK_EX);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
PR_IMPLEMENT(PRStatus)
_MD_TLockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = flock(f, LOCK_EX|LOCK_NB);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX|LOCK_NB);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
PR_IMPLEMENT(PRStatus)
_MD_UnlockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = flock(f, LOCK_UN);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = flock(f, LOCK_UN);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
#else
PR_IMPLEMENT(PRStatus)
_MD_LockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = lockf(f, F_LOCK, 0);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = lockf(f, F_LOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
PR_IMPLEMENT(PRStatus)
_MD_TLockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = lockf(f, F_TLOCK, 0);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = lockf(f, F_TLOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
PR_IMPLEMENT(PRStatus)
_MD_UnlockFile(PRInt32 f)
{
- PRInt32 rv;
- rv = lockf(f, F_ULOCK, 0);
- if (rv == 0)
- return PR_SUCCESS;
- _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
- return PR_FAILURE;
+ PRInt32 rv;
+ rv = lockf(f, F_ULOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
}
#endif
@@ -3446,9 +3436,9 @@ PR_IMPLEMENT(PRStatus) _MD_gethostname(char *name, PRUint32 namelen)
rv = gethostname(name, namelen);
if (0 == rv) {
- return PR_SUCCESS;
+ return PR_SUCCESS;
}
- _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
+ _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
return PR_FAILURE;
}
@@ -3468,34 +3458,34 @@ PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
LL_L2UI(sz, size);
if (sz) {
if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) {
- return PR_FAILURE;
+ return PR_FAILURE;
}
if (sz > info.size) {
/*
* Need to extend the file
*/
if (fmap->prot != PR_PROT_READWRITE) {
- PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
- return PR_FAILURE;
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
+ return PR_FAILURE;
}
if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) {
- return PR_FAILURE;
+ return PR_FAILURE;
}
if (PR_Write(fmap->fd, "", 1) != 1) {
- return PR_FAILURE;
+ return PR_FAILURE;
}
- }
+ }
}
if (fmap->prot == PR_PROT_READONLY) {
- fmap->md.prot = PROT_READ;
- fmap->md.flags = 0;
+ fmap->md.prot = PROT_READ;
+ fmap->md.flags = MAP_PRIVATE;
} else if (fmap->prot == PR_PROT_READWRITE) {
- fmap->md.prot = PROT_READ | PROT_WRITE;
- fmap->md.flags = MAP_SHARED;
+ fmap->md.prot = PROT_READ | PROT_WRITE;
+ fmap->md.flags = MAP_SHARED;
} else {
- PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
- fmap->md.prot = PROT_READ | PROT_WRITE;
- fmap->md.flags = MAP_PRIVATE;
+ PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
+ fmap->md.prot = PROT_READ | PROT_WRITE;
+ fmap->md.flags = MAP_PRIVATE;
}
return PR_SUCCESS;
}
@@ -3510,8 +3500,8 @@ void * _MD_MemMap(
LL_L2I(off, offset);
if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags,
- fmap->fd->secret->md.osfd, off)) == (void *) -1) {
- _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
+ fmap->fd->secret->md.osfd, off)) == (void *) -1) {
+ _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
addr = NULL;
}
return addr;
@@ -3522,11 +3512,11 @@ PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
if (munmap(addr, len) == 0) {
return PR_SUCCESS;
} else {
- if (errno == EINVAL) {
+ if (errno == EINVAL) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, errno);
- }
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, errno);
+ }
return PR_FAILURE;
}
}
@@ -3544,8 +3534,6 @@ PRStatus _MD_CloseFileMap(PRFileMap *fmap)
* that calls poll(), we emulate poll() using select().
*/
-#include <fcntl.h>
-
int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
{
int i;
@@ -3555,15 +3543,15 @@ int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
struct timeval tv, *tvp;
if (timeout < 0 && timeout != -1) {
- errno = EINVAL;
- return -1;
+ errno = EINVAL;
+ return -1;
}
if (timeout == -1) {
tvp = NULL;
} else {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
tvp = &tv;
}
@@ -3573,100 +3561,100 @@ int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
FD_ZERO(&ex);
for (i = 0; i < nfds; i++) {
- int osfd = filedes[i].fd;
- int events = filedes[i].events;
- PRBool fdHasEvent = PR_FALSE;
+ int osfd = filedes[i].fd;
+ int events = filedes[i].events;
+ PRBool fdHasEvent = PR_FALSE;
- if (osfd < 0) {
+ if (osfd < 0) {
continue; /* Skip this osfd. */
- }
+ }
- /*
- * Map the native poll flags to nspr poll flags.
- * POLLIN, POLLRDNORM ===> PR_POLL_READ
- * POLLOUT, POLLWRNORM ===> PR_POLL_WRITE
- * POLLPRI, POLLRDBAND ===> PR_POLL_EXCEPTION
- * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
- * are ignored.
- *
- * The output events POLLERR and POLLHUP are never turned on.
- * POLLNVAL may be turned on.
- */
-
- if (events & (POLLIN | POLLRDNORM)) {
- FD_SET(osfd, &rd);
- fdHasEvent = PR_TRUE;
- }
- if (events & (POLLOUT | POLLWRNORM)) {
- FD_SET(osfd, &wr);
- fdHasEvent = PR_TRUE;
- }
- if (events & (POLLPRI | POLLRDBAND)) {
- FD_SET(osfd, &ex);
- fdHasEvent = PR_TRUE;
- }
- if (fdHasEvent && osfd > maxfd) {
- maxfd = osfd;
- }
+ /*
+ * Map the poll events to the select fd_sets.
+ * POLLIN, POLLRDNORM ===> readable
+ * POLLOUT, POLLWRNORM ===> writable
+ * POLLPRI, POLLRDBAND ===> exception
+ * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
+ * are ignored.
+ *
+ * The output events POLLERR and POLLHUP are never turned on.
+ * POLLNVAL may be turned on.
+ */
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ FD_SET(osfd, &rd);
+ fdHasEvent = PR_TRUE;
+ }
+ if (events & (POLLOUT | POLLWRNORM)) {
+ FD_SET(osfd, &wr);
+ fdHasEvent = PR_TRUE;
+ }
+ if (events & (POLLPRI | POLLRDBAND)) {
+ FD_SET(osfd, &ex);
+ fdHasEvent = PR_TRUE;
+ }
+ if (fdHasEvent && osfd > maxfd) {
+ maxfd = osfd;
+ }
}
rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
/* Compute poll results */
if (rv > 0) {
- rv = 0;
+ rv = 0;
for (i = 0; i < nfds; i++) {
- PRBool fdHasEvent = PR_FALSE;
+ PRBool fdHasEvent = PR_FALSE;
- filedes[i].revents = 0;
+ filedes[i].revents = 0;
if (filedes[i].fd < 0) {
continue;
}
- if (FD_ISSET(filedes[i].fd, &rd)) {
- if (filedes[i].events & POLLIN) {
- filedes[i].revents |= POLLIN;
- }
- if (filedes[i].events & POLLRDNORM) {
- filedes[i].revents |= POLLRDNORM;
- }
- fdHasEvent = PR_TRUE;
- }
- if (FD_ISSET(filedes[i].fd, &wr)) {
- if (filedes[i].events & POLLOUT) {
- filedes[i].revents |= POLLOUT;
- }
- if (filedes[i].events & POLLWRNORM) {
- filedes[i].revents |= POLLWRNORM;
- }
- fdHasEvent = PR_TRUE;
- }
- if (FD_ISSET(filedes[i].fd, &ex)) {
- if (filedes[i].events & POLLPRI) {
- filedes[i].revents |= POLLPRI;
- }
- if (filedes[i].events & POLLRDBAND) {
- filedes[i].revents |= POLLRDBAND;
- }
- fdHasEvent = PR_TRUE;
- }
- if (fdHasEvent) {
- rv++;
+ if (FD_ISSET(filedes[i].fd, &rd)) {
+ if (filedes[i].events & POLLIN) {
+ filedes[i].revents |= POLLIN;
+ }
+ if (filedes[i].events & POLLRDNORM) {
+ filedes[i].revents |= POLLRDNORM;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (FD_ISSET(filedes[i].fd, &wr)) {
+ if (filedes[i].events & POLLOUT) {
+ filedes[i].revents |= POLLOUT;
+ }
+ if (filedes[i].events & POLLWRNORM) {
+ filedes[i].revents |= POLLWRNORM;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (FD_ISSET(filedes[i].fd, &ex)) {
+ if (filedes[i].events & POLLPRI) {
+ filedes[i].revents |= POLLPRI;
+ }
+ if (filedes[i].events & POLLRDBAND) {
+ filedes[i].revents |= POLLRDBAND;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (fdHasEvent) {
+ rv++;
}
}
- PR_ASSERT(rv > 0);
+ PR_ASSERT(rv > 0);
} else if (rv == -1 && errno == EBADF) {
- rv = 0;
+ rv = 0;
for (i = 0; i < nfds; i++) {
- filedes[i].revents = 0;
+ filedes[i].revents = 0;
if (filedes[i].fd < 0) {
continue;
}
- if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
- filedes[i].revents = POLLNVAL;
- rv++;
- }
+ if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
+ filedes[i].revents = POLLNVAL;
+ rv++;
+ }
}
- PR_ASSERT(rv > 0);
+ PR_ASSERT(rv > 0);
}
PR_ASSERT(-1 != timeout || rv != 0);
diff --git a/pr/src/md/unix/unix_errors.c b/pr/src/md/unix/unix_errors.c
index 82d30428..e080138a 100644
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -16,9 +16,10 @@
* Reserved.
*/
-#include "prtypes.h"
-#include "md/_unix_errors.h"
-#include "prerror.h"
+#include "primpl.h"
+#if defined(_PR_POLL_AVAILABLE)
+#include <sys/poll.h>
+#endif
#include <errno.h>
void _MD_unix_map_opendir_error(int err)
@@ -77,14 +78,11 @@ void _MD_unix_readdir_error(int err)
case EBADF:
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
break;
-#ifdef IRIX
-#ifdef IRIX5_3
-#else
+#ifdef EDIRCORRUPTED
case EDIRCORRUPTED:
PR_SetError(PR_DIRECTORY_CORRUPTED_ERROR, err);
break;
#endif
-#endif
#ifdef EOVERFLOW
case EOVERFLOW:
PR_SetError(PR_IO_ERROR, err);
@@ -655,6 +653,9 @@ void _MD_unix_map_close_error(int err)
case EBADF:
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
break;
+ case EFBIG:
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, err);
+ break;
case EINTR:
PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
break;
@@ -804,6 +805,9 @@ void _MD_unix_map_send_error(int err)
case EINVAL:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
#if !defined(SCO)
case ENOBUFS:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
@@ -911,6 +915,9 @@ void _MD_unix_map_writev_error(int err)
case EINTR:
PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
#ifdef ENOSR
case ENOSR:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
@@ -1382,20 +1389,31 @@ void _MD_unix_map_open_error(int err)
void _MD_unix_map_mmap_error(int err)
{
-
switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EAGAIN:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
case EBADF:
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
break;
- case EAGAIN:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EMFILE:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
break;
- case EACCES:
- PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ case ENODEV:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
break;
case ENOMEM:
PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
break;
+ case ENXIO:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -1432,6 +1450,7 @@ void _MD_unix_map_select_error(int err)
}
}
+#ifdef _PR_POLL_AVAILABLE
void _MD_unix_map_poll_error(int err)
{
PRErrorCode prerror;
@@ -1452,6 +1471,21 @@ void _MD_unix_map_poll_error(int err)
PR_SetError(prerror, err);
}
+void _MD_unix_map_poll_revents_error(int err)
+{
+
+ if (err & POLLNVAL)
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ else if (err & POLLHUP)
+ PR_SetError(PR_CONNECT_RESET_ERROR, EPIPE);
+ else if (err & POLLERR)
+ PR_SetError(PR_IO_ERROR, EIO);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+}
+#endif /* _PR_POLL_AVAILABLE */
+
+
void _MD_unix_map_flock_error(int err)
{
switch (err) {
diff --git a/pr/src/md/unix/unixware.c b/pr/src/md/unix/unixware.c
index 4bc410bf..76c9c751 100644
--- a/pr/src/md/unix/unixware.c
+++ b/pr/src/md/unix/unixware.c
@@ -91,6 +91,14 @@ _MD_ATOMIC_INCREMENT(PRInt32 *val)
}
void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+void
_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
flockfile(_uw_semf);
@@ -194,6 +202,12 @@ _MD_ATOMIC_INCREMENT(PRInt32 *val)
}
void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ TEST_THEN_ADD(ptr, val);
+}
+
+void
_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
TEST_THEN_ADD(val, 0xffffffff);
diff --git a/pr/src/md/unix/uxpoll.c b/pr/src/md/unix/uxpoll.c
new file mode 100644
index 00000000..a4f6b6fc
--- /dev/null
+++ b/pr/src/md/unix/uxpoll.c
@@ -0,0 +1,681 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#if defined(_PR_PTHREADS)
+#else /* defined(_PR_PTHREADS) */
+
+#include "primpl.h"
+
+#include <sys/time.h>
+
+#include <fcntl.h>
+#ifdef _PR_USE_POLL
+#include <sys/poll.h>
+#endif
+
+#if defined(_PR_USE_POLL)
+static PRInt32 NativeThreadPoll(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ /*
+ * This function is mostly duplicated from ptio.s's PR_Poll().
+ */
+ PRInt32 ready = 0;
+ /*
+ * For restarting poll() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has
+ * elapsed and how much of the timeout still remains.
+ */
+ PRIntn index, msecs;
+ struct pollfd *syspoll = NULL;
+ PRIntervalTime start, elapsed, remaining;
+
+ syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
+ if (NULL == syspoll)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ for (index = 0; index < npds; ++index)
+ {
+ PRFileDesc *bottom;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (pds[index].in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_WRITE,
+ &out_flags_read);
+ }
+ if (pds[index].in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_READ,
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one is ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will return without calling the system
+ * poll function. So zero the out_flags
+ * fields of all the poll descriptors before
+ * this one.
+ */
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1;
+ pds[index].out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pds[index].out_flags = 0; /* pre-condition */
+ /* now locate the NSPR layer at the bottom of the stack */
+ bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ syspoll[index].fd = bottom->secret->md.osfd;
+ syspoll[index].events = 0; /* pre-condition */
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (pds[index].in_flags & PR_POLL_EXCEPT)
+ syspoll[index].events |= POLLPRI;
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pds[index].out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ /* make poll() ignore this entry */
+ syspoll[index].fd = -1;
+ }
+ }
+
+ if (0 == ready)
+ {
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT: msecs = 0; break;
+ case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
+ default:
+ msecs = PR_IntervalToMilliseconds(timeout);
+ start = PR_IntervalNow();
+ }
+
+retry:
+ ready = _MD_POLL(syspoll, npds, msecs);
+ if (-1 == ready)
+ {
+ PRIntn oserror = errno;
+
+ if (EINTR == oserror)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0;
+ else
+ {
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ msecs = PR_IntervalToMilliseconds(remaining);
+ goto retry;
+ }
+ }
+ }
+ else _PR_MD_MAP_POLL_ERROR(oserror);
+ }
+ else if (ready > 0)
+ {
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (0 != syspoll[index].revents)
+ {
+ /*
+ ** Set up the out_flags so that it contains the
+ ** bits that the highest layer thinks are nice
+ ** to have. Then the client of that layer will
+ ** call the appropriate I/O function and maybe
+ ** the protocol will make progress.
+ */
+ if (syspoll[index].revents & POLLIN)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_READ)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_READ)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLOUT)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLPRI)
+ out_flags |= PR_POLL_EXCEPT;
+ if (syspoll[index].revents & POLLERR)
+ out_flags |= PR_POLL_ERR;
+ if (syspoll[index].revents & POLLNVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (syspoll[index].revents & POLLHUP)
+ out_flags |= PR_POLL_HUP;
+ }
+ }
+ pds[index].out_flags = out_flags;
+ }
+ }
+ }
+
+ PR_DELETE(syspoll);
+ return ready;
+
+} /* NativeThreadPoll */
+#endif /* defined(_PR_USE_POLL) */
+
+#if !defined(_PR_USE_POLL)
+static PRInt32 NativeThreadSelect(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ /*
+ * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
+ */
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
+
+ struct timeval tv, *tvp = NULL;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
+
+ remaining = timeout;
+ start = PR_IntervalNow();
+
+retry:
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = remaining - (ticksPerSecond * tv.tv_sec);
+ tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond;
+ tvp = &tv;
+ }
+
+ ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
+
+ if (ready == -1 && errno == EINTR)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ goto retry;
+ }
+ }
+ }
+
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ PRInt32 osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
+
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+ }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+ return ready;
+} /* NativeThreadSelect */
+#endif /* !defined(_PR_USE_POLL) */
+
+static PRInt32 LocalThreads(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRPollDesc *pd, *epd;
+ PRInt32 ready, pdcnt;
+ _PRUnixPollDesc *unixpds, *unixpd;
+
+ /*
+ * XXX
+ * PRPollDesc has a PRFileDesc field, fd, while the IOQ
+ * is a list of PRPollQueue structures, each of which contains
+ * a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
+ * the OS file descriptor, osfd, and not a PRFileDesc.
+ * So, we have allocate memory for _PRUnixPollDesc structures,
+ * copy the flags information from the pds list and have pq
+ * point to this list of _PRUnixPollDesc structures.
+ *
+ * It would be better if the memory allocation can be avoided.
+ */
+
+ unixpd = unixpds = (_PRUnixPollDesc*)
+ PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
+ if (NULL == unixpds)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+
+ ready = 0;
+ for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRFileDesc *bottom;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ unixpd->osfd = bottom->secret->md.osfd;
+ unixpd->in_flags = 0;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ }
+ if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ unixpd++; pdcnt++;
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ }
+
+ if (0 != ready)
+ {
+ /* no need to block */
+ PR_DELETE(unixpds);
+ return ready;
+ }
+
+ ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
+
+ /*
+ * Copy the out_flags from the _PRUnixPollDesc structures to the
+ * user's PRPollDesc structures and free the allocated memory
+ */
+ unixpd = unixpds;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ /*
+ * take errors from the poll operation,
+ * the R/W bits from the request
+ */
+ if (0 != unixpd->out_flags)
+ {
+ if (unixpd->out_flags & _PR_UNIX_POLL_READ)
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_WRITE)
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT)
+ out_flags |= PR_POLL_EXCEPT;
+ if (unixpd->out_flags & _PR_UNIX_POLL_ERR)
+ out_flags |= PR_POLL_ERR;
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (unixpd->out_flags & _PR_UNIX_POLL_HUP)
+ out_flags |= PR_POLL_HUP;
+ }
+ unixpd++;
+ }
+ pd->out_flags = out_flags;
+ }
+
+ PR_DELETE(unixpds);
+
+ return ready;
+} /* LocalThreads */
+
+#if defined(_PR_USE_POLL)
+#define NativeThreads NativeThreadPoll
+#else
+#define NativeThreads NativeThreadSelect
+#endif
+
+PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt32 rv = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (0 == npds) PR_Sleep(timeout);
+ else if (_PR_IS_NATIVE_THREAD(me))
+ rv = NativeThreads(pds, npds, timeout);
+ else rv = LocalThreads(pds, npds, timeout);
+
+ return rv;
+} /* _MD_pr_poll */
+
+#endif /* defined(_PR_PTHREADS) */
+
+/* pruxpoll.c */
+
diff --git a/pr/src/md/unix/uxproces.c b/pr/src/md/unix/uxproces.c
index ecbc14d7..c2b7eee5 100644
--- a/pr/src/md/unix/uxproces.c
+++ b/pr/src/md/unix/uxproces.c
@@ -23,6 +23,9 @@
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
+#if defined(AIX)
+#include <dlfcn.h> /* For dlopen, dlsym, dlclose */
+#endif
/*
* HP-UX 9 doesn't have the SA_RESTART flag.
@@ -98,6 +101,16 @@ static struct {
#ifdef _PR_SHARE_CLONES
struct pr_CreateProcOp *opHead, *opTail;
#endif
+
+#ifdef AIX
+ pid_t (*forkptr)(void); /* Newer versions of AIX (starting in 4.3.2)
+ * have f_fork, which is faster than the
+ * regular fork in a multithreaded process
+ * because it skips calling the fork handlers.
+ * So we look up the f_fork symbol to see if
+ * it's available and fall back on fork.
+ */
+#endif /* AIX */
} pr_wp;
#ifdef _PR_SHARE_CLONES
@@ -134,7 +147,11 @@ ForkAndExec(
return NULL;
}
+#ifdef AIX
+ process->md.pid = (*pr_wp.forkptr)();
+#else
process->md.pid = fork();
+#endif
if ((pid_t) -1 == process->md.pid) {
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
PR_DELETE(process);
@@ -578,6 +595,17 @@ static PRStatus _MD_InitProcesses()
#define _PR_NBIO_FLAG O_NONBLOCK
#endif
+#ifdef AIX
+ {
+ void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
+ pr_wp.forkptr = (pid_t (*)(void)) dlsym(handle, "f_fork");
+ if (!pr_wp.forkptr) {
+ pr_wp.forkptr = fork;
+ }
+ dlclose(handle);
+ }
+#endif /* AIX */
+
pr_wp.ml = PR_NewLock();
PR_ASSERT(NULL != pr_wp.ml);
diff --git a/pr/src/md/unix/uxwrap.c b/pr/src/md/unix/uxwrap.c
index 577c4411..9a26c90d 100644
--- a/pr/src/md/unix/uxwrap.c
+++ b/pr/src/md/unix/uxwrap.c
@@ -48,38 +48,26 @@
); \
PR_END_MACRO
-#define COPY_SET(_to, _from, _width) \
- PR_BEGIN_MACRO \
- memcpy(_to, _from, \
- ((_width + 8*sizeof(int)-1) / (8*sizeof(int))) \
- * sizeof(int) \
- ); \
- PR_END_MACRO
-
-/* An internal global variable defined in prfile.c */
-extern PRIOMethods _pr_fileMethods;
-
-
/* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */
static int _pr_xt_hack_fd = -1;
int PR_XGetXtHackFD(void)
{
- int fds[2];
+ int fds[2];
- if (_pr_xt_hack_fd == -1) {
- if (!pipe(fds)) {
- _pr_xt_hack_fd = fds[0];
- }
- }
- return _pr_xt_hack_fd;
- }
+ if (_pr_xt_hack_fd == -1) {
+ if (!pipe(fds)) {
+ _pr_xt_hack_fd = fds[0];
+ }
+ }
+ return _pr_xt_hack_fd;
+}
static int (*_pr_xt_hack_okayToReleaseXLock)(void) = 0;
void PR_SetXtHackOkayToReleaseXLockFn(int (*fn)(void))
{
- _pr_xt_hack_okayToReleaseXLock = fn;
+ _pr_xt_hack_okayToReleaseXLock = fn;
}
@@ -97,7 +85,7 @@ void PR_SetXtHackOkayToReleaseXLockFn(int (*fn)(void))
int select(size_t width, int *rl, int *wl, int *el, const struct timeval *tv)
#elif defined(AIX4_1)
int wrap_select(unsigned long width, void *rl, void *wl, void *el,
- struct timeval *tv)
+ struct timeval *tv)
#elif (defined(BSDI) && !defined(BSDI_2))
int select(int width, fd_set *rd, fd_set *wr, fd_set *ex,
const struct timeval *tv)
@@ -105,12 +93,9 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex,
int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
#endif
{
- int i;
- int npds;
- void *pollset;
- PRPollDesc *pd;
- PRFileDesc *prfd;
- PRFilePrivate *secret;
+ int osfd;
+ _PRUnixPollDesc *unixpds, *unixpd, *eunixpd;
+ PRInt32 pdcnt;
PRIntervalTime timeout;
int retVal;
#if defined(HPUX9) || defined(AIX4_1)
@@ -118,7 +103,6 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
fd_set *wr = (fd_set*) wl;
fd_set *ex = (fd_set*) el;
#endif
- fd_set r, w, x;
#if 0
/*
@@ -134,8 +118,9 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
}
#endif
- if (!_pr_initialized)
- _PR_ImplicitInitialization();
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
#ifndef _PR_LOCAL_THREADS_ONLY
if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {
@@ -144,39 +129,35 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
#endif
if (width < 0 || width > FD_SETSIZE) {
- errno = EINVAL;
- return -1;
+ errno = EINVAL;
+ return -1;
}
/* Compute timeout */
if (tv) {
- /*
- * These acceptable ranges for t_sec and t_usec are taken
- * from the select() man pages.
- */
- if (tv->tv_sec < 0 || tv->tv_sec > 100000000
- || tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
- errno = EINVAL;
- return -1;
- }
-
- /* Convert microseconds to ticks */
- timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec);
+ /*
+ * These acceptable ranges for t_sec and t_usec are taken
+ * from the select() man pages.
+ */
+ if (tv->tv_sec < 0 || tv->tv_sec > 100000000
+ || tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Convert microseconds to ticks */
+ timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec);
} else {
- /* tv being a NULL pointer means blocking indefinitely */
- timeout = PR_INTERVAL_NO_TIMEOUT;
+ /* tv being a NULL pointer means blocking indefinitely */
+ timeout = PR_INTERVAL_NO_TIMEOUT;
}
/* Check for no descriptors case (just doing a timeout) */
if ((!rd && !wr && !ex) || !width) {
- PR_Sleep(timeout);
- return 0;
+ PR_Sleep(timeout);
+ return 0;
}
- if (rd) { COPY_SET(&r, rd, width); }
- if (wr) { COPY_SET(&w, wr, width); }
- if (ex) { COPY_SET(&x, ex, width); }
-
/*
* Set up for PR_Poll(). The PRPollDesc array is allocated
* dynamically. If this turns out to have high performance
@@ -187,63 +168,59 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
* I allocate an array of size 'width', which is the maximum
* number of fds we may need to poll.
*/
- pollset = PR_CALLOC(width *
- (sizeof(PRPollDesc) + sizeof(PRFileDesc) + sizeof(PRFilePrivate)));
- if (!pollset) {
+ unixpds = (_PRUnixPollDesc *) PR_CALLOC(width * sizeof(_PRUnixPollDesc));
+ if (!unixpds) {
errno = ENOMEM;
return -1;
}
- pd = (PRPollDesc*)pollset;
- prfd = (PRFileDesc*)(&pd[width]);
- secret = (PRFilePrivate*)(&prfd[width]);
-
- for (npds = 0, i = 0; i < width; i++) {
- int in_flags = 0;
- if (rd && FD_ISSET(i, &r)) {
- in_flags |= PR_POLL_READ;
- }
- if (wr && FD_ISSET(i, &w)) {
- in_flags |= PR_POLL_WRITE;
- }
- if (ex && FD_ISSET(i, &x)) {
- in_flags |= PR_POLL_EXCEPT;
- }
- if (in_flags) {
- prfd[npds].secret = &secret[npds];
- prfd[npds].secret->state = _PR_FILEDESC_OPEN;
- prfd[npds].secret->md.osfd = i;
- prfd[npds].methods = &_pr_fileMethods;
-
- pd[npds].fd = &prfd[npds];
- pd[npds].in_flags = in_flags;
- pd[npds].out_flags = 0;
- npds += 1;
- }
+
+ pdcnt = 0;
+ unixpd = unixpds;
+ for (osfd = 0; osfd < width; osfd++) {
+ int in_flags = 0;
+ if (rd && FD_ISSET(osfd, rd)) {
+ in_flags |= _PR_UNIX_POLL_READ;
+ }
+ if (wr && FD_ISSET(osfd, wr)) {
+ in_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if (ex && FD_ISSET(osfd, ex)) {
+ in_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ if (in_flags) {
+ unixpd->osfd = osfd;
+ unixpd->in_flags = in_flags;
+ unixpd->out_flags = 0;
+ unixpd++;
+ pdcnt++;
+ }
}
- /* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */
- {
-
+ /*
+ * see comments in mozilla/cmd/xfe/mozilla.c (look for
+ * "PR_XGetXtHackFD")
+ */
+ {
int needToLockXAgain;
needToLockXAgain = 0;
- if (rd && (_pr_xt_hack_fd != -1) &&
- FD_ISSET(_pr_xt_hack_fd, &r) && PR_XIsLocked() &&
- (!_pr_xt_hack_okayToReleaseXLock || _pr_xt_hack_okayToReleaseXLock())) {
- PR_XUnlock();
- needToLockXAgain = 1;
+ if (rd && (_pr_xt_hack_fd != -1)
+ && FD_ISSET(_pr_xt_hack_fd, rd) && PR_XIsLocked()
+ && (!_pr_xt_hack_okayToReleaseXLock
+ || _pr_xt_hack_okayToReleaseXLock())) {
+ PR_XUnlock();
+ needToLockXAgain = 1;
}
/* This is the potentially blocking step */
- retVal = PR_Poll(pd, npds, timeout);
+ retVal = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
if (needToLockXAgain) {
- PR_XLock();
+ PR_XLock();
}
}
- if (retVal > 0)
- {
+ if (retVal > 0) {
/* Compute select results */
if (rd) ZAP_SET(rd, width);
if (wr) ZAP_SET(wr, width);
@@ -254,43 +231,55 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
* descriptors or the number of set bits in the three fd_set's.
*/
retVal = 0; /* we're going to recompute */
- for (i = 0; i < npds; ++i, pd++)
- {
- if (pd->out_flags) {
- int nbits = 0; /* The number of set bits on for this fd */
-
- if (pd->out_flags & PR_POLL_NVAL) {
- errno = EBADF;
- PR_LOG(_pr_io_lm, PR_LOG_ERROR,
- ("select returns EBADF for %d", pd->fd));
- retVal = -1;
- break;
- }
- if (rd && (pd->out_flags & PR_POLL_READ)) {
- FD_SET(pd->fd->secret->md.osfd, rd);
- nbits++;
- }
- if (wr && (pd->out_flags & PR_POLL_WRITE)) {
- FD_SET(pd->fd->secret->md.osfd, wr);
- nbits++;
- }
- if (ex && (pd->out_flags & PR_POLL_EXCEPT)) {
- FD_SET(pd->fd->secret->md.osfd, ex);
- nbits++;
- }
- PR_ASSERT(nbits > 0);
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ if (unixpd->out_flags) {
+ int nbits = 0; /* The number of set bits on for this fd */
+
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
+ errno = EBADF;
+ PR_LOG(_pr_io_lm, PR_LOG_ERROR,
+ ("select returns EBADF for %d", unixpd->osfd));
+ retVal = -1;
+ break;
+ }
+ /*
+ * If a socket has a pending error, it is considered
+ * both readable and writable. (See W. Richard Stevens,
+ * Unix Network Programming, Vol. 1, 2nd Ed., Section 6.3,
+ * pp. 153-154.) We also consider a socket readable if
+ * it has a hangup condition.
+ */
+ if (rd && (unixpd->in_flags & _PR_UNIX_POLL_READ)
+ && (unixpd->out_flags & (_PR_UNIX_POLL_READ
+ | _PR_UNIX_POLL_ERR | _PR_UNIX_POLL_HUP))) {
+ FD_SET(unixpd->osfd, rd);
+ nbits++;
+ }
+ if (wr && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
+ && (unixpd->out_flags & (_PR_UNIX_POLL_WRITE
+ | _PR_UNIX_POLL_ERR))) {
+ FD_SET(unixpd->osfd, wr);
+ nbits++;
+ }
+ if (ex && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
+ && (unixpd->out_flags & PR_POLL_EXCEPT)) {
+ FD_SET(unixpd->osfd, ex);
+ nbits++;
+ }
+ PR_ASSERT(nbits > 0);
#if defined(HPUX) || defined(SOLARIS) || defined(SUNOS4) || defined(OSF1) || defined(AIX)
retVal += nbits;
#else /* IRIX */
retVal += 1;
#endif
- }
+ }
}
}
PR_ASSERT(tv || retVal != 0);
PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal));
- PR_DELETE(pollset);
+ PR_DELETE(unixpds);
return retVal;
}
@@ -314,7 +303,7 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
*-----------------------------------------------------------------------
*/
-#include <poll.h>
+#include <sys/poll.h>
#if defined(AIX4_1)
int wrap_poll(void *listptr, unsigned long nfds, long timeout)
@@ -326,6 +315,8 @@ int poll(struct pollfd filedes[], unsigned int nfds, int timeout)
int poll(struct pollfd filedes[], int nfds, int timeout)
#elif defined(NETBSD)
int poll(struct pollfd *filedes, nfds_t nfds, int timeout)
+#elif defined(OPENBSD)
+int poll(struct pollfd *filedes, int nfds, int timeout)
#else
int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
#endif
@@ -333,13 +324,11 @@ int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
#ifdef AIX
struct pollfd *filedes = (struct pollfd *) listptr;
#endif
- void *pollset;
- PRPollDesc *pd;
- PRFileDesc *prfd;
- PRFilePrivate *secret;
- int i;
- PRUint32 ticks;
- PRInt32 retVal;
+ struct pollfd *pfd, *epfd;
+ _PRUnixPollDesc *unixpds, *unixpd, *eunixpd;
+ PRIntervalTime ticks;
+ PRInt32 pdcnt;
+ int ready;
/*
* Easy special case: zero timeout. Simply call the native
@@ -359,8 +348,7 @@ int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
#ifndef _PR_LOCAL_THREADS_ONLY
if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {
- retVal = _MD_POLL(filedes, nfds, timeout);
- return(retVal);
+ return _MD_POLL(filedes, nfds, timeout);
}
#endif
@@ -370,144 +358,155 @@ int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
#endif
if (timeout < 0 && timeout != -1) {
- errno = EINVAL;
- return -1;
+ errno = EINVAL;
+ return -1;
}
/* Convert timeout from miliseconds to ticks */
if (timeout == -1) {
- ticks = PR_INTERVAL_NO_TIMEOUT;
- } else if (timeout == 0) {
- ticks = PR_INTERVAL_NO_WAIT;
+ ticks = PR_INTERVAL_NO_TIMEOUT;
} else {
ticks = PR_MillisecondsToInterval(timeout);
}
/* Check for no descriptor case (just do a timeout) */
if (nfds == 0) {
- PR_Sleep(ticks);
- return 0;
+ PR_Sleep(ticks);
+ return 0;
}
- pollset = PR_CALLOC(nfds *
- (sizeof(PRPollDesc) + sizeof(PRFileDesc) + sizeof(PRFilePrivate)));
- if (!pollset) {
+ unixpds = (_PRUnixPollDesc *)
+ PR_MALLOC(nfds * sizeof(_PRUnixPollDesc));
+ if (NULL == unixpds) {
errno = EAGAIN;
return -1;
}
- pd = (PRPollDesc*)pollset;
- prfd = (PRFileDesc*)(&pd[nfds]);
- secret = (PRFilePrivate*)(&prfd[nfds]);
-
- for (i = 0; i < nfds; i++) {
- prfd[i].secret = &secret[i];
- prfd[i].secret->state = _PR_FILEDESC_OPEN;
- prfd[i].secret->md.osfd = filedes[i].fd;
- prfd[i].methods = &_pr_fileMethods;
-
- pd[i].fd = &prfd[i];
- pd[i].out_flags = 0;
-
- /*
- * poll() ignores negative fd's. We emulate this behavior
- * by making sure the in_flags for a negative fd is zero.
- */
- if (filedes[i].fd < 0) {
- pd[i].in_flags = 0;
- continue;
- }
+
+ pdcnt = 0;
+ epfd = filedes + nfds;
+ unixpd = unixpds;
+ for (pfd = filedes; pfd < epfd; pfd++) {
+ /*
+ * poll() ignores negative fd's.
+ */
+ if (pfd->fd >= 0) {
+ unixpd->osfd = pfd->fd;
#ifdef _PR_USE_POLL
- pd[i].in_flags = filedes[i].events;
+ unixpd->in_flags = pfd->events;
#else
- /*
- * Map the native poll flags to nspr20 poll flags.
- * POLLIN, POLLRDNORM ===> PR_POLL_READ
- * POLLOUT, POLLWRNORM ===> PR_POLL_WRITE
- * POLLPRI, POLLRDBAND ===> PR_POLL_EXCEPT
- * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
- * are ignored.
- *
- * The output events POLLERR and POLLHUP are never turned on.
- * POLLNVAL may be turned on.
- */
- pd[i].in_flags = 0;
- if (filedes[i].events & (POLLIN
+ /*
+ * Map the poll events to one of the three that can be
+ * represented by the select fd_sets:
+ * POLLIN, POLLRDNORM ===> readable
+ * POLLOUT, POLLWRNORM ===> writable
+ * POLLPRI, POLLRDBAND ===> exception
+ * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
+ * are ignored.
+ *
+ * The output events POLLERR and POLLHUP are never turned on.
+ * POLLNVAL may be turned on.
+ */
+ unixpd->in_flags = 0;
+ if (pfd->events & (POLLIN
#ifdef POLLRDNORM
- | POLLRDNORM
+ | POLLRDNORM
#endif
- )) {
- pd[i].in_flags |= PR_POLL_READ;
- }
- if (filedes[i].events & (POLLOUT
+ )) {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ }
+ if (pfd->events & (POLLOUT
#ifdef POLLWRNORM
- | POLLWRNORM
+ | POLLWRNORM
#endif
- )) {
- pd[i].in_flags |= PR_POLL_WRITE;
- }
- if (filedes[i].events & (POLLPRI
+ )) {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if (pfd->events & (POLLPRI
#ifdef POLLRDBAND
- | POLLRDBAND
+ | POLLRDBAND
#endif
- )) {
- pd[i].in_flags |= PR_POLL_EXCEPT;
- }
+ )) {
+ unixpd->in_flags |= PR_POLL_EXCEPT;
+ }
#endif /* _PR_USE_POLL */
+ unixpd->out_flags = 0;
+ unixpd++;
+ pdcnt++;
+ }
}
- retVal = PR_Poll(pd, nfds, ticks);
+ ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, ticks);
+ if (-1 == ready) {
+ if (PR_GetError() == PR_PENDING_INTERRUPT_ERROR) {
+ errno = EINTR; /* XXX we aren't interrupted by a signal, but... */
+ } else {
+ errno = PR_GetOSError();
+ }
+ }
+ if (ready <= 0) {
+ goto done;
+ }
- if (retVal > 0) {
- /* Set the revents bitmasks */
- for (i = 0; i < nfds; i++) {
- PR_ASSERT(filedes[i].fd >= 0 || pd[i].in_flags == 0);
- if (filedes[i].fd < 0) {
- continue; /* skip negative fd's */
- }
+ /*
+ * Copy the out_flags from the _PRUnixPollDesc structures to the
+ * user's pollfd structures and free the allocated memory
+ */
+ unixpd = unixpds;
+ for (pfd = filedes; pfd < epfd; pfd++) {
+ pfd->revents = 0;
+ if (pfd->fd >= 0) {
#ifdef _PR_USE_POLL
- filedes[i].revents = pd[i].out_flags;
+ pfd->revents = unixpd->out_flags;
#else
- filedes[i].revents = 0;
- if (0 == pd[i].out_flags) {
- continue;
- }
- if (pd[i].out_flags & PR_POLL_READ) {
- if (filedes[i].events & POLLIN)
- filedes[i].revents |= POLLIN;
+ if (0 != unixpd->out_flags) {
+ if (unixpd->out_flags & _PR_UNIX_POLL_READ) {
+ if (pfd->events & POLLIN) {
+ pfd->revents |= POLLIN;
+ }
#ifdef POLLRDNORM
- if (filedes[i].events & POLLRDNORM)
- filedes[i].revents |= POLLRDNORM;
+ if (pfd->events & POLLRDNORM) {
+ pfd->revents |= POLLRDNORM;
+ }
#endif
- }
- if (pd[i].out_flags & PR_POLL_WRITE) {
- if (filedes[i].events & POLLOUT)
- filedes[i].revents |= POLLOUT;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) {
+ if (pfd->events & POLLOUT) {
+ pfd->revents |= POLLOUT;
+ }
#ifdef POLLWRNORM
- if (filedes[i].events & POLLWRNORM)
- filedes[i].revents |= POLLWRNORM;
+ if (pfd->events & POLLWRNORM) {
+ pfd->revents |= POLLWRNORM;
+ }
#endif
- }
- if (pd[i].out_flags & PR_POLL_EXCEPT) {
- if (filedes[i].events & POLLPRI)
- filedes[i].revents |= POLLPRI;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (pfd->events & POLLPRI) {
+ pfd->revents |= POLLPRI;
+ }
#ifdef POLLRDBAND
- if (filedes[i].events & POLLRDBAND)
- filedes[i].revents |= POLLRDBAND;
+ if (pfd->events & POLLRDBAND) {
+ pfd->revents |= POLLRDBAND;
+ }
#endif
- }
- if (pd[i].out_flags & PR_POLL_ERR) {
- filedes[i].revents |= POLLERR;
- }
- if (pd[i].out_flags & PR_POLL_NVAL) {
- filedes[i].revents |= POLLNVAL;
- }
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_ERR) {
+ pfd->revents |= POLLERR;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
+ pfd->revents |= POLLNVAL;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_HUP) {
+ pfd->revents |= POLLHUP;
+ }
+ }
#endif /* _PR_USE_POLL */
+ unixpd++;
}
}
- PR_DELETE(pollset);
-
- return retVal;
+done:
+ PR_DELETE(unixpds);
+ return ready;
}
#endif /* !defined(LINUX) */
diff --git a/pr/src/md/windows/Makefile b/pr/src/md/windows/Makefile
index eaac7b56..c513a342 100644
--- a/pr/src/md/windows/Makefile
+++ b/pr/src/md/windows/Makefile
@@ -49,9 +49,11 @@ CSRCS = \
w95sock.c \
win32_errors.c \
w32poll.c \
+ w95dllmain.c \
$(NULL)
else
CSRCS = \
+ ntdllmn.c \
ntmisc.c \
ntsem.c \
ntinrval.c \
diff --git a/pr/src/md/windows/ntdllmn.c b/pr/src/md/windows/ntdllmn.c
new file mode 100644
index 00000000..c9736a6e
--- /dev/null
+++ b/pr/src/md/windows/ntdllmn.c
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * The DLL entry point (DllMain) for NSPR.
+ *
+ * The only reason we use DLLMain() now is 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 ntthread.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:
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c
index d3640995..160f2cf0 100644
--- a/pr/src/md/windows/ntio.c
+++ b/pr/src/md/windows/ntio.c
@@ -35,6 +35,7 @@
*/
#include "primpl.h"
+#include "pprmwait.h"
#include <direct.h>
static HANDLE _pr_completion_port;
@@ -45,12 +46,9 @@ static struct _MDLock _pr_recycle_lock;
static PRInt32 _pr_recycle_array[RECYCLE_SIZE];
static PRInt32 _pr_recycle_tail = 0;
-#ifdef _PR_USE_STATIC_TLS
__declspec(thread) PRThread *_pr_io_restarted_io = NULL;
-#else
DWORD _pr_io_restartedIOIndex; /* The thread local storage slot for each
* thread is initialized to NULL. */
-#endif
PRBool _nt_version_gets_lockfile_completion;
@@ -76,7 +74,6 @@ PRBool IsFileLocalInit();
PRInt32 IsFileLocal(HANDLE hFile);
#endif /* _NEED_351_FILE_LOCKING_HACK */
-static PRInt32 _md_Associate(HANDLE);
static PRInt32 _md_MakeNonblock(HANDLE);
/* The _nt_use_async flag is used to prevent nspr from using any async io.
@@ -189,7 +186,7 @@ _PR_MD_PAUSE_CPU(PRIntervalTime ticks)
unsigned long bytes, key;
int rv;
LPOVERLAPPED olp;
- PRThread *completed_io;
+ _MDOverlapped *mdOlp;
PRUint32 timeout;
if (_nt_idleCount > 0) {
@@ -259,84 +256,151 @@ _PR_MD_PAUSE_CPU(PRIntervalTime ticks)
if (olp == NULL)
return 0;
- completed_io = _PR_THREAD_MD_TO_PTR(olp);
- completed_io->md.blocked_io_status = rv;
- if (rv == 0)
- completed_io->md.blocked_io_error = GetLastError();
- completed_io->md.blocked_io_bytes = bytes;
-
- if ( !_PR_IS_NATIVE_THREAD(completed_io) ) {
- int pri = completed_io->priority;
- _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();
-
- /* The KEY_CVAR notification only occurs when a native thread
- * is notifying a user thread. For user-user notifications
- * the wakeup occurs by having the notifier place the thread
- * on the runq directly; for native-native notifications the
- * wakeup occurs by calling ReleaseSemaphore.
- */
- if ( key == KEY_CVAR ) {
- PR_ASSERT(completed_io->io_pending == PR_FALSE || completed_io->io_suspended == PR_TRUE);
-
- /* Thread has already been deleted from sleepQ */
-
- /* Switch CPU and add to runQ */
- completed_io->cpu = lockedCPU;
- completed_io->state = _PR_RUNNABLE;
- _PR_RUNQ_LOCK(lockedCPU);
- _PR_ADD_RUNQ(completed_io, lockedCPU, pri);
- _PR_RUNQ_UNLOCK(lockedCPU);
- } else {
- PR_ASSERT(key == KEY_IO);
- PR_ASSERT(completed_io->io_pending == PR_TRUE);
-
- _PR_THREAD_LOCK(completed_io);
-
- completed_io->io_pending = PR_FALSE;
-
- /* If io_suspended is true, then this IO has already resumed.
- * We don't need to do anything; because the thread is
- * already running.
- */
- if (completed_io->io_suspended == PR_FALSE) {
- if (completed_io->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) {
- _PR_SLEEPQ_LOCK(completed_io->cpu);
- _PR_DEL_SLEEPQ(completed_io, PR_TRUE);
- _PR_SLEEPQ_UNLOCK(completed_io->cpu);
-
- _PR_THREAD_UNLOCK(completed_io);
-
- completed_io->cpu = lockedCPU;
- completed_io->state = _PR_RUNNABLE;
+ mdOlp = (_MDOverlapped *)olp;
+
+ if (mdOlp->ioModel == _MD_MultiWaitIO) {
+ PRRecvWait *desc;
+ PRWaitGroup *group;
+ PRThread *thred = NULL;
+ PRMWStatus mwstatus;
+
+ desc = mdOlp->data.mw.desc;
+ PR_ASSERT(desc != NULL);
+ mwstatus = rv ? PR_MW_SUCCESS : PR_MW_FAILURE;
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)mwstatus, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING) {
+ if (mwstatus == PR_MW_SUCCESS) {
+ desc->bytesRecv = bytes;
+ } else {
+ mdOlp->data.mw.error = GetLastError();
+ }
+ }
+ group = mdOlp->data.mw.group;
+ PR_ASSERT(group != NULL);
+
+ _PR_MD_LOCK(&group->mdlock);
+ PR_APPEND_LINK(&mdOlp->data.mw.links, &group->io_ready);
+ PR_ASSERT(desc->fd != NULL);
+ NT_HashRemoveInternal(group, desc->fd);
+ if (!PR_CLIST_IS_EMPTY(&group->wait_list)) {
+ thred = _PR_THREAD_CONDQ_PTR(PR_LIST_HEAD(&group->wait_list));
+ PR_REMOVE_LINK(&thred->waitQLinks);
+ }
+ _PR_MD_UNLOCK(&group->mdlock);
+
+ if (thred) {
+ if (!_PR_IS_NATIVE_THREAD(thred)) {
+ int pri = thred->priority;
+ _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();
+ _PR_THREAD_LOCK(thred);
+ if (thred->flags & _PR_ON_PAUSEQ) {
+ _PR_SLEEPQ_LOCK(thred->cpu);
+ _PR_DEL_SLEEPQ(thred, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(thred->cpu);
+ _PR_THREAD_UNLOCK(thred);
+ thred->cpu = lockedCPU;
+ thred->state = _PR_RUNNABLE;
_PR_RUNQ_LOCK(lockedCPU);
- _PR_ADD_RUNQ(completed_io, lockedCPU, pri);
+ _PR_ADD_RUNQ(thred, lockedCPU, pri);
_PR_RUNQ_UNLOCK(lockedCPU);
} else {
- _PR_THREAD_UNLOCK(completed_io);
+ /*
+ * The thread was just interrupted and moved
+ * from the pause queue to the run queue.
+ */
+ _PR_THREAD_UNLOCK(thred);
}
} else {
- _PR_THREAD_UNLOCK(completed_io);
+ _PR_THREAD_LOCK(thred);
+ thred->state = _PR_RUNNABLE;
+ _PR_THREAD_UNLOCK(thred);
+ ReleaseSemaphore(thred->md.blocked_sema, 1, NULL);
}
}
} else {
- int old_count;
- PRBool fNeedRelease = PR_FALSE;
+ PRThread *completed_io;
+
+ PR_ASSERT(mdOlp->ioModel == _MD_BlockingIO);
+ completed_io = _PR_THREAD_MD_TO_PTR(mdOlp->data.mdThread);
+ completed_io->md.blocked_io_status = rv;
+ if (rv == 0)
+ completed_io->md.blocked_io_error = GetLastError();
+ completed_io->md.blocked_io_bytes = bytes;
+
+ if ( !_PR_IS_NATIVE_THREAD(completed_io) ) {
+ int pri = completed_io->priority;
+ _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();
+
+ /* The KEY_CVAR notification only occurs when a native thread
+ * is notifying a user thread. For user-user notifications
+ * the wakeup occurs by having the notifier place the thread
+ * on the runq directly; for native-native notifications the
+ * wakeup occurs by calling ReleaseSemaphore.
+ */
+ if ( key == KEY_CVAR ) {
+ PR_ASSERT(completed_io->io_pending == PR_FALSE || completed_io->io_suspended == PR_TRUE);
- /* For native threads, they are only notified through this loop
- * when completing IO. So, don't worry about this being a CVAR
- * notification, because that is not possible.
- */
- _PR_THREAD_LOCK(completed_io);
- completed_io->io_pending = PR_FALSE;
- if (completed_io->io_suspended == PR_FALSE) {
- completed_io->state = _PR_RUNNABLE;
- fNeedRelease = PR_TRUE;
- }
- _PR_THREAD_UNLOCK(completed_io);
- if (fNeedRelease) {
- rv = ReleaseSemaphore(completed_io->md.blocked_sema,
- 1, &old_count);
- PR_ASSERT(0 != rv);
+ /* Thread has already been deleted from sleepQ */
+
+ /* Switch CPU and add to runQ */
+ completed_io->cpu = lockedCPU;
+ completed_io->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(lockedCPU);
+ _PR_ADD_RUNQ(completed_io, lockedCPU, pri);
+ _PR_RUNQ_UNLOCK(lockedCPU);
+ } else {
+ PR_ASSERT(key == KEY_IO);
+ PR_ASSERT(completed_io->io_pending == PR_TRUE);
+
+ _PR_THREAD_LOCK(completed_io);
+
+ completed_io->io_pending = PR_FALSE;
+
+ /* If io_suspended is true, then this IO has already resumed.
+ * We don't need to do anything; because the thread is
+ * already running.
+ */
+ if (completed_io->io_suspended == PR_FALSE) {
+ if (completed_io->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) {
+ _PR_SLEEPQ_LOCK(completed_io->cpu);
+ _PR_DEL_SLEEPQ(completed_io, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(completed_io->cpu);
+
+ _PR_THREAD_UNLOCK(completed_io);
+
+ completed_io->cpu = lockedCPU;
+ completed_io->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(lockedCPU);
+ _PR_ADD_RUNQ(completed_io, lockedCPU, pri);
+ _PR_RUNQ_UNLOCK(lockedCPU);
+ } else {
+ _PR_THREAD_UNLOCK(completed_io);
+ }
+ } else {
+ _PR_THREAD_UNLOCK(completed_io);
+ }
+ }
+ } else {
+ int old_count;
+ PRBool fNeedRelease = PR_FALSE;
+
+ /* For native threads, they are only notified through this loop
+ * when completing IO. So, don't worry about this being a CVAR
+ * notification, because that is not possible.
+ */
+ _PR_THREAD_LOCK(completed_io);
+ completed_io->io_pending = PR_FALSE;
+ if (completed_io->io_suspended == PR_FALSE) {
+ completed_io->state = _PR_RUNNABLE;
+ fNeedRelease = PR_TRUE;
+ }
+ _PR_THREAD_UNLOCK(completed_io);
+ if (fNeedRelease) {
+ rv = ReleaseSemaphore(completed_io->md.blocked_sema,
+ 1, &old_count);
+ PR_ASSERT(0 != rv);
+ }
}
}
@@ -400,13 +464,7 @@ _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
} else {
PRInt32 is;
- /* XXXMB - This is barely safe, but works. We should find a
- * way to make all callers of PR_MD_WAIT zero the overlapped buffer
- * themselves...
- */
- if (thread->state != _PR_IO_WAIT)
- memset(&(thread->md.overlapped), 0, sizeof(OVERLAPPED));
- if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
_PR_MD_SWITCH_CONTEXT(thread);
}
@@ -477,11 +535,11 @@ _NT_ResumeIO(PRThread *thread, PRIntervalTime ticks)
PRBool fWait = PR_TRUE;
if (!_PR_IS_NATIVE_THREAD(thread)) {
-#ifdef _PR_USE_STATIC_TLS
- _pr_io_restarted_io = thread;
-#else
- TlsSetValue(_pr_io_restartedIOIndex, thread);
-#endif
+ if (_pr_use_static_tls) {
+ _pr_io_restarted_io = thread;
+ } else {
+ TlsSetValue(_pr_io_restartedIOIndex, thread);
+ }
} else {
_PR_THREAD_LOCK(thread);
if (!thread->io_pending)
@@ -534,7 +592,7 @@ _PR_MD_WAKEUP_WAITER(PRThread *thread)
/* The thread should not be in any queue */
PR_ASSERT(thread->queueCount == 0);
if ( PostQueuedCompletionStatus(_pr_completion_port, 0,
- KEY_CVAR, &(thread->md.overlapped)) == FALSE)
+ KEY_CVAR, &(thread->md.overlapped.overlapped)) == FALSE)
return PR_FAILURE;
}
return PR_SUCCESS;
@@ -675,7 +733,7 @@ _md_put_recycled_socket(SOCKET newsock)
* Associates a file with the completion port.
* Returns 0 on failure, 1 on success.
*/
-static PRInt32
+PRInt32
_md_Associate(HANDLE file)
{
HANDLE port;
@@ -873,7 +931,10 @@ _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
FD_SET((SOCKET)osfd, &wd);
rv = select(osfd + 1, NULL, &wd, NULL, tvp);
if (rv > 0) {
- rv = 0;
+ /*
+ * Call Sleep(0) to work around a Winsock timing bug.
+ */
+ Sleep(0);
} else if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
return(-1);
@@ -1021,6 +1082,11 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
return _nt_nonblock_accept(fd, (struct sockaddr_in *)raddr, rlen, timeout);
}
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
if (!fd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)osfd);
PR_ASSERT(0 != rv);
@@ -1039,10 +1105,8 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
if (accept_sock == INVALID_SOCKET)
return -1;
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
- PR_ASSERT(me->io_suspended == PR_FALSE);
-
me->io_pending = PR_TRUE;
me->io_fd = osfd;
me->state = _PR_IO_WAIT;
@@ -1053,7 +1117,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
INET_ADDR_PADDED,
INET_ADDR_PADDED,
&bytes,
- &(me->md.overlapped));
+ &(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) {
/* Argh! The IO failed */
@@ -1110,7 +1174,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
PRInt32
_PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
void *buf, PRInt32 amount, PRIntervalTime timeout,
- PRBool update, _PR_AcceptTimeoutCallback callback,
+ PRBool fast, _PR_AcceptTimeoutCallback callback,
void *callbackArg)
{
PRInt32 sock = sd->secret->md.osfd;
@@ -1132,12 +1196,16 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
*/
PR_ASSERT(nd->secret->state == _PR_FILEDESC_OPEN);
*newSock = nd->secret->md.osfd;
- nd->secret->state = _PR_FILEDESC_CLOSED;
PR_FreeFileDesc(nd);
}
return bytes;
}
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
if (!sd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)sock);
PR_ASSERT(0 != rv);
@@ -1148,10 +1216,8 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
if (*newSock == INVALID_SOCKET)
return -1;
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
- PR_ASSERT(me->io_suspended == PR_FALSE);
-
me->io_pending = PR_TRUE;
me->io_fd = sock;
me->state = _PR_IO_WAIT;
@@ -1162,7 +1228,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
INET_ADDR_PADDED,
INET_ADDR_PADDED,
&bytes,
- &(me->md.overlapped));
+ &(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) {
me->io_pending = PR_FALSE;
@@ -1249,7 +1315,7 @@ retry:
return -1;
}
- if (update)
+ if (!fast)
_PR_MD_UPDATE_ACCEPT_CONTEXT((SOCKET)*newSock, (SOCKET)sock);
/* IO is done */
@@ -1285,6 +1351,11 @@ _PR_MD_TRANSMITFILE(PRFileDesc *sock, PRFileDesc *file, const void *headers, PRI
return _PR_EmulateTransmitFile(sock, file, headers, hlen, flags, timeout);
}
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
if (!sock->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)sock->secret->md.osfd);
PR_ASSERT(0 != rv);
@@ -1302,9 +1373,7 @@ _PR_MD_TRANSMITFILE(PRFileDesc *sock, PRFileDesc *file, const void *headers, PRI
me->md.xmit_bufs->Tail = (void *)NULL;
me->md.xmit_bufs->TailLength = 0;
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
-
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
tflags = 0;
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET)
@@ -1317,7 +1386,7 @@ _PR_MD_TRANSMITFILE(PRFileDesc *sock, PRFileDesc *file, const void *headers, PRI
(HANDLE)file->secret->md.osfd,
(DWORD)0,
(DWORD)0,
- (LPOVERLAPPED)&(me->md.overlapped),
+ (LPOVERLAPPED)&(me->md.overlapped.overlapped),
(TRANSMIT_FILE_BUFFERS *)me->md.xmit_bufs,
(DWORD)tflags);
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
@@ -1376,15 +1445,18 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
return _nt_nonblock_recv(fd, buf, amount, timeout);
}
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
if (!fd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)osfd);
PR_ASSERT(0 != rv);
fd->secret->md.io_model_committed = PR_TRUE;
}
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
-
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
me->io_pending = PR_TRUE;
me->io_fd = osfd;
@@ -1393,7 +1465,7 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
buf,
amount,
&bytes,
- &(me->md.overlapped));
+ &(me->md.overlapped.overlapped));
if ( (rv == 0) && (GetLastError() != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
@@ -1450,15 +1522,18 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
return _nt_nonblock_send(fd, (char *)buf, amount, timeout);
}
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
if (!fd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)osfd);
PR_ASSERT(0 != rv);
fd->secret->md.io_model_committed = PR_TRUE;
}
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
-
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
me->io_pending = PR_TRUE;
me->io_fd = osfd;
@@ -1467,7 +1542,7 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
buf,
amount,
&bytes,
- &(me->md.overlapped));
+ &(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
@@ -1777,11 +1852,14 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
if (_nt_use_async && !fd->secret->md.nonoverlapped) {
PRThread *me = _PR_MD_CURRENT_THREAD();
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
- me->md.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
+ me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
me->io_pending = PR_TRUE;
me->io_fd = f;
@@ -1790,7 +1868,7 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
(LPVOID)buf,
len,
&bytes,
- &me->md.overlapped);
+ &me->md.overlapped.overlapped);
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
@@ -1857,14 +1935,18 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len)
PRInt32 f = fd->secret->md.osfd;
PRInt32 bytes;
int rv, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
if (_nt_use_async && !fd->secret->md.nonoverlapped) {
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
- me->md.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
+ me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
me->io_pending = PR_TRUE;
me->io_fd = f;
@@ -1873,7 +1955,7 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len)
buf,
len,
&bytes,
- &(me->md.overlapped));
+ &(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
@@ -1953,23 +2035,44 @@ _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int whence)
PRInt64
_PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, int whence)
{
- PRInt64 result;
- PRInt32 rv, low = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
+ PRUint64 result;
+ PRUint32 position, uhi;
+ PRInt32 low = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
- rv = SetFilePointer((HANDLE)fd->secret->md.osfd, low, &hi, whence);
+ position = SetFilePointer((HANDLE)fd->secret->md.osfd, low, &hi, whence);
/*
- * If the lpDistanceToMoveHigh argument (third argument) is
- * NULL, SetFilePointer returns 0xffffffff on failure.
+ * The lpDistanceToMoveHigh argument (third argument) is not
+ * NULL. Therefore, a -1 (unsigned) result is ambiguious. If
+ * the result just happens to be -1, also test to see if the
+ * last error is non-zero. If it is, the operation failed.
+ * Otherwise, the -1 is just the low half of the 64 bit position.
*/
- if (-1 == rv)
+ if (0xffffffff == position)
{
- _PR_MD_MAP_LSEEK_ERROR(GetLastError());
- return -1;
+ PRInt32 oserr = GetLastError();
+ if (0 != oserr)
+ {
+ _PR_MD_MAP_LSEEK_ERROR(oserr);
+ return -1;
+ }
}
- result = (hi << 32) + rv;
- return result;
+ /*
+ ** All this 'cause we keep extending the sign of rv into
+ ** the high bits of the result. We just know that the final
+ ** position of the file must be positive and probably nowhere
+ ** close to the maximum value of a PRUint64.
+ */
+ uhi = (PRUint32)hi;
+ PR_ASSERT((PRInt32)uhi >= 0);
+ result = uhi;
+ PR_ASSERT((PRInt64)result >= 0);
+ result = (result << 32);
+ PR_ASSERT((PRInt64)result >= 0);
+ result += position;
+ PR_ASSERT((PRInt64)result >= 0);
+ return (PRInt64)result;
}
/*
@@ -2601,9 +2704,12 @@ _PR_MD_LOCKFILE(PRInt32 f)
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
me->state = _PR_IO_WAIT;
me->io_pending = PR_TRUE;
@@ -2612,7 +2718,7 @@ _PR_MD_LOCKFILE(PRInt32 f)
0,
0x7fffffff,
0,
- &me->md.overlapped);
+ &me->md.overlapped.overlapped);
/* HACK AROUND NT BUG
* NT 3.51 has a bug. In NT 3.51, if LockFileEx returns true, you
@@ -2676,9 +2782,12 @@ _PR_MD_TLOCKFILE(PRInt32 f)
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
me->state = _PR_IO_WAIT;
me->io_pending = PR_TRUE;
@@ -2687,7 +2796,7 @@ _PR_MD_TLOCKFILE(PRInt32 f)
0,
0x7fffffff,
0,
- &me->md.overlapped);
+ &me->md.overlapped.overlapped);
if ( rv == FALSE && ((err = GetLastError()) != ERROR_IO_PENDING)) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
@@ -2730,15 +2839,18 @@ _PR_MD_UNLOCKFILE(PRInt32 f)
PRInt32 rv;
PRThread *me = _PR_MD_CURRENT_THREAD();
- memset(&(me->md.overlapped), 0, sizeof(OVERLAPPED));
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
- PR_ASSERT(me->io_suspended == PR_FALSE);
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
rv = UnlockFileEx((HANDLE)f,
0,
0x7fffffff,
0,
- &me->md.overlapped);
+ &me->md.overlapped.overlapped);
if (rv)
return PR_SUCCESS;
@@ -3750,7 +3862,7 @@ static PRInt32 pt_SendTo(
op.arg2.buffer = (void*)buf;
op.arg3.amount = amount;
op.arg4.flags = flags;
- op.arg5.addr = addr;
+ op.arg5.addr = (PRNetAddr*)addr;
op.timeout = timeout;
op.result.code = 0; /* initialize the number sent */
op.function = pt_sendto_cont;
diff --git a/pr/src/md/windows/ntmisc.c b/pr/src/md/windows/ntmisc.c
index 28eff1e9..869bc897 100644
--- a/pr/src/md/windows/ntmisc.c
+++ b/pr/src/md/windows/ntmisc.c
@@ -354,6 +354,7 @@ PRProcess * _PR_CreateWindowsProcess(
char *cmdLine = NULL;
char *envBlock = NULL;
char **newEnvp;
+ char *cwd = NULL; /* current working directory */
PRProcess *proc = NULL;
proc = PR_NEW(PRProcess);
@@ -415,6 +416,7 @@ PRProcess * _PR_CreateWindowsProcess(
if (redirected) {
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
}
+ cwd = attr->currentDirectory;
}
retVal = CreateProcess(NULL,
@@ -431,7 +433,7 @@ PRProcess * _PR_CreateWindowsProcess(
* string is in the form:
* name=value
* XXX: usually NULL */
- attr->currentDirectory, /* current drive and directory */
+ cwd, /* current drive and directory */
&startupInfo,
&procInfo
);
@@ -648,4 +650,70 @@ PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
}
#pragma warning(default: 4035)
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val)
+{
+ __asm
+ {
+ mov ecx, intp
+ mov eax, val
+ mov ebx, val
+ lock xadd dword ptr [ecx], eax
+ add eax, ebx
+ }
+}
+#pragma warning(default: 4035)
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#pragma warning(disable: 4035)
+void
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+ __asm
+ {
+ mov ebx, stack
+ mov ecx, stack_elem
+retry: mov eax,[ebx]
+ cmp eax,-1
+ je retry
+ mov eax,-1
+ xchg dword ptr [ebx], eax
+ cmp eax,-1
+ je retry
+ mov [ecx],eax
+ mov [ebx],ecx
+ }
+}
+#pragma warning(default: 4035)
+
+#pragma warning(disable: 4035)
+PRStackElem *
+PR_StackPop(PRStack *stack)
+{
+ __asm
+ {
+ mov ebx, stack
+retry: mov eax,[ebx]
+ cmp eax,-1
+ je retry
+ mov eax,-1
+ xchg dword ptr [ebx], eax
+ cmp eax,-1
+ je retry
+ cmp eax,0
+ je empty
+ mov ecx,[eax]
+ mov [ebx],ecx
+ mov [eax],0
+ jmp done
+empty:
+ mov [ebx],eax
+done:
+ }
+}
+#pragma warning(default: 4035)
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
+
#endif /* x86 processors */
diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c
index d751581b..1f6de5ac 100644
--- a/pr/src/md/windows/ntthread.c
+++ b/pr/src/md/windows/ntthread.c
@@ -25,46 +25,34 @@ extern void _PR_Win32InitTimeZone(void); /* defined in ntmisc.c */
PRLock *_pr_schedLock = NULL;
_PRInterruptTable _pr_interruptTable[] = { { 0 } };
-#ifdef _PR_USE_STATIC_TLS
+BOOL _pr_use_static_tls = TRUE;
__declspec(thread) PRThread *_pr_current_fiber;
__declspec(thread) PRThread *_pr_fiber_last_run;
__declspec(thread) _PRCPU *_pr_current_cpu;
__declspec(thread) PRUintn _pr_ints_off;
-#else /* _PR_USE_STATIC_TLS */
DWORD _pr_currentFiberIndex;
DWORD _pr_lastFiberIndex;
DWORD _pr_currentCPUIndex;
DWORD _pr_intsOffIndex;
-#endif /* _PR_USE_STATIC_TLS */
_MDLock _nt_idleLock;
PRCList _nt_idleList;
PRUint32 _nt_idleCount;
-#ifdef _PR_USE_STATIC_TLS
-
extern __declspec(thread) PRThread *_pr_io_restarted_io;
-
-/* Must check the restarted_io *before* decrementing no_sched to 0 */
-#define POST_SWITCH_WORK() \
- if (_pr_io_restarted_io) \
- _nt_handle_restarted_io(_pr_io_restarted_io); \
- _PR_MD_LAST_THREAD()->no_sched = 0;
-
-#else /* _PR_USE_STATIC_TLS */
-
extern DWORD _pr_io_restartedIOIndex;
/* Must check the restarted_io *before* decrementing no_sched to 0 */
#define POST_SWITCH_WORK() \
-PR_BEGIN_MACRO \
- PRThread *restarted_io = (PRThread *) TlsGetValue(_pr_io_restartedIOIndex); \
- if (restarted_io) \
- _nt_handle_restarted_io(restarted_io); \
- _PR_MD_LAST_THREAD()->no_sched = 0; \
-PR_END_MACRO
-
-#endif /* _PR_USE_STATIC_TLS */
+ PR_BEGIN_MACRO \
+ PRThread *restarted_io = \
+ (_pr_use_static_tls ? _pr_io_restarted_io \
+ : (PRThread *) TlsGetValue(_pr_io_restartedIOIndex)); \
+ if (restarted_io) { \
+ _nt_handle_restarted_io(restarted_io); \
+ } \
+ _PR_MD_LAST_THREAD()->no_sched = 0; \
+ PR_END_MACRO
void
_nt_handle_restarted_io(PRThread *restarted_io)
@@ -94,11 +82,11 @@ _nt_handle_restarted_io(PRThread *restarted_io)
_PR_THREAD_UNLOCK(restarted_io);
-#ifdef _PR_USE_STATIC_TLS
- _pr_io_restarted_io = NULL;
-#else
- TlsSetValue(_pr_io_restartedIOIndex, NULL);
-#endif
+ if (_pr_use_static_tls) {
+ _pr_io_restarted_io = NULL;
+ } else {
+ TlsSetValue(_pr_io_restartedIOIndex, NULL);
+ }
}
void
@@ -117,26 +105,26 @@ _PR_MD_EARLY_INIT()
}
#endif
-#ifndef _PR_USE_STATIC_TLS
- _pr_currentFiberIndex = TlsAlloc();
- _pr_lastFiberIndex = TlsAlloc();
- _pr_currentCPUIndex = TlsAlloc();
- _pr_intsOffIndex = TlsAlloc();
- _pr_io_restartedIOIndex = TlsAlloc();
-#endif
+ if (!_pr_use_static_tls) {
+ _pr_currentFiberIndex = TlsAlloc();
+ _pr_lastFiberIndex = TlsAlloc();
+ _pr_currentCPUIndex = TlsAlloc();
+ _pr_intsOffIndex = TlsAlloc();
+ _pr_io_restartedIOIndex = TlsAlloc();
+ }
}
void _PR_MD_CLEANUP_BEFORE_EXIT(void)
{
WSACleanup();
-#ifndef _PR_USE_STATIC_TLS
- TlsFree(_pr_currentFiberIndex);
- TlsFree(_pr_lastFiberIndex);
- TlsFree(_pr_currentCPUIndex);
- TlsFree(_pr_intsOffIndex);
- TlsFree(_pr_io_restartedIOIndex);
-#endif
+ if (!_pr_use_static_tls) {
+ TlsFree(_pr_currentFiberIndex);
+ TlsFree(_pr_lastFiberIndex);
+ TlsFree(_pr_currentCPUIndex);
+ TlsFree(_pr_intsOffIndex);
+ TlsFree(_pr_io_restartedIOIndex);
+ }
}
void
@@ -162,6 +150,8 @@ _PR_MD_INIT_PRIMORDIAL_THREAD(PRThread *thread)
PRStatus
_PR_MD_INIT_THREAD(PRThread *thread)
{
+ thread->md.overlapped.ioModel = _MD_BlockingIO;
+ thread->md.overlapped.data.mdThread = &thread->md;
/* Create the blocking IO semaphore */
thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);
if (thread->md.blocked_sema == NULL)
@@ -479,3 +469,18 @@ _PR_MD_RESUME_THREAD(PRThread *thread)
}
}
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+ return thread;
+}
+
diff --git a/pr/src/md/windows/w16callb.c b/pr/src/md/windows/w16callb.c
index d25f7c19..9c9a4a79 100644
--- a/pr/src/md/windows/w16callb.c
+++ b/pr/src/md/windows/w16callb.c
@@ -233,7 +233,7 @@ int PR_MD_fprintf(FILE *fPtr, const char *fmt, ...)
}
else
{
- fwrite(buffer, 0, strlen(buffer), fPtr); /* XXX Is this a sec. hole? */
+ fwrite(buffer, 1, strlen(buffer), fPtr); /* XXX Is this a sec. hole? */
}
va_end(args);
diff --git a/pr/src/md/windows/w16mem.c b/pr/src/md/windows/w16mem.c
index f1fe6a08..dac82384 100644
--- a/pr/src/md/windows/w16mem.c
+++ b/pr/src/md/windows/w16mem.c
@@ -46,7 +46,6 @@ PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
return PR_FAILURE;
}
- seg->access = PR_SEGMENT_RDWR;
seg->size = size;
return PR_SUCCESS;
diff --git a/pr/src/md/windows/w32poll.c b/pr/src/md/windows/w32poll.c
index e71fd936..5b73124d 100644
--- a/pr/src/md/windows/w32poll.c
+++ b/pr/src/md/windows/w32poll.c
@@ -45,55 +45,153 @@ _PR_MD_select_thread(void *cdata)
#endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */
-PRInt32
-_PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
+ int ready, err;
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
PRPollDesc *pd, *epd;
- int n, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
- fd_set rd, wt, ex;
struct timeval tv, *tvp = NULL;
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ ** Is it an empty set? If so, just sleep for the timeout and return
+ */
+ if (0 == npds)
+ {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
FD_ZERO(&rd);
FD_ZERO(&wt);
FD_ZERO(&ex);
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
SOCKET osfd;
- PRInt16 in_flags = pd->in_flags;
- PRFileDesc *bottom = pd->fd;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
- if ((NULL == bottom) || (in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = (SOCKET) bottom->secret->md.osfd;
-
- if (in_flags & PR_POLL_READ) {
- FD_SET(osfd, &rd);
- }
- if (in_flags & PR_POLL_WRITE) {
- FD_SET(osfd, &wt);
- }
- if (in_flags & PR_POLL_EXCEPT) {
- FD_SET(osfd, &ex);
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE),
+ &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ),
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now (buffered input) */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ osfd = (SOCKET) bottom->secret->md.osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
}
}
- if (timeout != PR_INTERVAL_NO_TIMEOUT) {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
+
+ if (0 != ready) return ready; /* no need to block */
+
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = timeout / ticksPerSecond;
+ tv.tv_usec = timeout - (ticksPerSecond * tv.tv_sec);
+ tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond;
tvp = &tv;
}
#if defined(_PR_GLOBAL_THREADS_ONLY)
- n = _MD_SELECT(0, &rd, &wt, &ex, tvp);
+ ready = _MD_SELECT(0, &rd, &wt, &ex, tvp);
#else
if (_PR_IS_NATIVE_THREAD(me)) {
- n = _MD_SELECT(0, &rd, &wt, &ex, tvp);
- } else {
+ ready = _MD_SELECT(0, &rd, &wt, &ex, tvp);
+ }
+ else
+ {
+ /*
+ ** Creating a new thread on each call to Poll()!!
+ ** I guess web server doesn't use non-block I/O.
+ */
PRThread *selectThread;
struct select_data_s data;
data.status = 0;
@@ -103,87 +201,88 @@ _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
data.ex = &ex;
data.tv = tvp;
- selectThread = PR_CreateThread(PR_USER_THREAD,
- _PR_MD_select_thread,
- &data,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_JOINABLE_THREAD,
- 0);
- if (selectThread == NULL) {
- return -1;
- }
+ selectThread = PR_CreateThread(
+ PR_USER_THREAD, _PR_MD_select_thread, &data,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (selectThread == NULL) return -1;
+
PR_JoinThread(selectThread);
- n = data.status;
- if (n == SOCKET_ERROR) {
- WSASetLastError(data.error);
- }
+ ready = data.status;
+ if (ready == SOCKET_ERROR) WSASetLastError(data.error);
}
#endif
- if (n > 0) {
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- SOCKET osfd;
- PRInt16 in_flags = pd->in_flags;
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
PRInt16 out_flags = 0;
- PRFileDesc *bottom = pd->fd;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ SOCKET osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
- if ((NULL == bottom) || (in_flags == 0)) {
- pd->out_flags = 0;
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- osfd = (SOCKET) bottom->secret->md.osfd;
+ osfd = (SOCKET) bottom->secret->md.osfd;
- if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
- out_flags |= PR_POLL_READ;
- }
- if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
- out_flags |= PR_POLL_WRITE;
- }
- if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
- out_flags |= PR_POLL_EXCEPT;
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
}
pd->out_flags = out_flags;
- if (out_flags) {
- n++;
- }
+ if (out_flags) ready++;
}
- PR_ASSERT(n > 0);
- } else if (n == SOCKET_ERROR) {
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready == SOCKET_ERROR)
+ {
err = WSAGetLastError();
- if (err == WSAENOTSOCK) {
+ if (err == WSAENOTSOCK)
+ {
/* Find the bad fds */
- n = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++) {
- int optval;
- int optlen = sizeof(optval);
- PRFileDesc *bottom = pd->fd;
-
+ int optval;
+ int optlen = sizeof(optval);
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
pd->out_flags = 0;
- if ((NULL == bottom) || (pd->in_flags == 0)) {
- continue;
- }
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
- SO_TYPE, (char *) &optval, &optlen) == -1) {
- PR_ASSERT(WSAGetLastError() == WSAENOTSOCK);
- if (WSAGetLastError() == WSAENOTSOCK) {
- pd->out_flags = PR_POLL_NVAL;
- n++;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
+ {
+ PR_ASSERT(WSAGetLastError() == WSAENOTSOCK);
+ if (WSAGetLastError() == WSAENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
}
}
}
- PR_ASSERT(n > 0);
- } else {
- _PR_MD_MAP_SELECT_ERROR(err);
+ PR_ASSERT(ready > 0);
}
+ else _PR_MD_MAP_SELECT_ERROR(err);
}
- return n;
+ return ready;
}
diff --git a/pr/src/md/windows/w95dllmain.c b/pr/src/md/windows/w95dllmain.c
new file mode 100644
index 00000000..ae83ec44
--- /dev/null
+++ b/pr/src/md/windows/w95dllmain.c
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * The DLL entry point (DllMain) for NSPR.
+ *
+ * This is used to detach threads that were automatically attached by
+ * nspr.
+ */
+
+#include <windows.h>
+#include <primpl.h>
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+PRThread *me;
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c
index c5fbea4c..75030f55 100644
--- a/pr/src/md/windows/w95sock.c
+++ b/pr/src/md/windows/w95sock.c
@@ -22,6 +22,15 @@
#include "primpl.h"
+#define READ_FD 1
+#define WRITE_FD 2
+#define CONNECT_FD 3
+
+static PRInt32 socket_io_wait(
+ PRInt32 osfd,
+ PRInt32 fd_type,
+ PRIntervalTime timeout);
+
/* --- SOCKET IO --------------------------------------------------------- */
@@ -30,27 +39,23 @@ PRInt32
_PR_MD_SOCKET(int af, int type, int flags)
{
SOCKET sock;
- PRUint32 one = 1;
- PRInt32 rv;
- PRInt32 err;
+ u_long one = 1;
sock = socket(af, type, flags);
if (sock == INVALID_SOCKET )
{
- int rv = WSAGetLastError();
- closesocket(sock);
- _PR_MD_MAP_SOCKET_ERROR(rv);
- return (PRInt32)INVALID_SOCKET;
+ _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
+ return (PRInt32)sock;
}
/*
** Make the socket Non-Blocking
*/
- rv = ioctlsocket( sock, FIONBIO, &one);
- if ( rv != 0 )
+ if (ioctlsocket( sock, FIONBIO, &one) != 0)
{
- err = WSAGetLastError();
+ PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError());
+ closesocket(sock);
return -1;
}
@@ -64,11 +69,11 @@ _PR_MD_SOCKET(int af, int type, int flags)
PRInt32
_MD_CloseSocket(PRInt32 osfd)
{
- PRInt32 rv = SOCKET_ERROR;
+ PRInt32 rv;
rv = closesocket((SOCKET) osfd );
- if (rv < 0)
- _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
+ if (rv < 0)
+ _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
return rv;
}
@@ -79,90 +84,39 @@ _MD_SocketAvailable(PRFileDesc *fd)
PRInt32 result;
if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
return -1;
}
return result;
}
-PRInt32
-_MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
- PRIntervalTime timeout )
+PRInt32 _MD_Accept(
+ PRFileDesc *fd,
+ PRNetAddr *raddr,
+ PRUint32 *rlen,
+ PRIntervalTime timeout )
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- fd_set rd;
- struct timeval tv, *tvp;
- FD_ZERO(&rd);
- FD_SET((SOCKET)osfd, &rd);
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ while ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
{
- while ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
- {
- if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- if ((rv = select(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- break;
- }
- }
- else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- break;
- }
- }
- return(rv);
- }
- else if (timeout == PR_INTERVAL_NO_WAIT)
- {
- if ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
+ err = WSAGetLastError();
+ if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking))
{
- if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
- && (!fd->secret->nonblocking))
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
{
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- else
- {
- _PR_MD_MAP_ACCEPT_ERROR(err);
+ return(-1);
}
}
- return(rv);
- }
- else
- {
-retry:
- if ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
+ else
{
- if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
-
- rv = select(osfd + 1, &rd, NULL, NULL, tvp);
- if (rv > 0) {
- goto retry;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- } else {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- }
- } else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ break;
}
}
return(rv);
-} /* end _MD_Accept() */
-
+} /* end _MD_accept() */
PRInt32
_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
@@ -170,64 +124,25 @@ _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv;
- int err, len;
- fd_set wd, ex;
- struct timeval tv, *tvp;
+ int err;
if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
{
err = WSAGetLastError();
if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK))
{
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- tvp = NULL;
- else
+ rv = socket_io_wait(osfd, CONNECT_FD, timeout);
+ if ( rv < 0 )
{
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
+ return(-1);
}
-
- FD_ZERO(&wd);
- FD_SET((SOCKET)osfd, &wd);
- FD_ZERO(&ex);
- FD_SET((SOCKET)osfd, &ex);
- rv = select(osfd + 1, NULL, &wd, &ex, tvp);
- if (rv > 0)
+ else
{
- if (FD_ISSET((SOCKET)osfd, &ex))
- {
- Sleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) == SOCKET_ERROR)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
- return -1;
- }
- if (err != 0)
- _PR_MD_MAP_CONNECT_ERROR(err);
- else
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- if (FD_ISSET((SOCKET)osfd, &wd))
- {
- /* it's connected */
- return 0;
- }
+ PR_ASSERT(rv > 0);
+ /* it's connected */
+ return(0);
}
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return(-1);
- } else if (rv < 0)
- {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- return(-1);
- }
- }
+ }
_PR_MD_MAP_CONNECT_ERROR(err);
}
return rv;
@@ -242,9 +157,9 @@ _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
if (rv == SOCKET_ERROR) {
- _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
+ _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
return -1;
- }
+ }
return 0;
}
@@ -256,42 +171,21 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- struct timeval tv, *tvp;
- fd_set rd;
while ((rv = recv( osfd, buf, amount, 0)) == -1)
{
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking))
{
- FD_ZERO(&rd);
- FD_SET((SOCKET)osfd, &rd);
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
+ rv = socket_io_wait(osfd, READ_FD, timeout);
+ if ( rv < 0 )
{
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
}
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- }
}
else
{
- _PR_MD_MAP_RECV_ERROR(err);
+ _PR_MD_MAP_RECV_ERROR(err);
break;
}
} /* end while() */
@@ -304,8 +198,6 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- struct timeval tv, *tvp;
- fd_set wd;
PRInt32 bytesSent = 0;
while(bytesSent < amount )
@@ -315,62 +207,29 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking))
{
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET((SOCKET)osfd, &wd);
- if ((rv = select( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- break;
- }
- if (rv == 0)
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
{
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
+ return -1;
}
}
- else {
- _PR_MD_MAP_SEND_ERROR(err);
+ else
+ {
+ _PR_MD_MAP_SEND_ERROR(err);
return -1;
- }
+ }
}
bytesSent += rv;
if (fd->secret->nonblocking)
{
break;
}
- if ((rv >= 0) && (bytesSent < amount ))
+ if (bytesSent < amount)
{
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET((SOCKET)osfd, &wd);
- if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- break;
- }
- if (rv == 0)
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
{
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
+ return -1;
}
}
}
@@ -383,8 +242,6 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- struct timeval tv, *tvp;
- fd_set wd;
PRInt32 bytesSent = 0;
while(bytesSent < amount)
@@ -395,62 +252,29 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking))
{
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
{
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET((SOCKET)osfd, &wd);
- if ((rv = select(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
+ return -1;
}
}
- else {
- _PR_MD_MAP_SENDTO_ERROR(err);
+ else
+ {
+ _PR_MD_MAP_SENDTO_ERROR(err);
return -1;
- }
+ }
}
bytesSent += rv;
if (fd->secret->nonblocking)
{
break;
}
- if ((rv >= 0) && (bytesSent < amount ))
+ if (bytesSent < amount)
{
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv < 0)
{
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET((SOCKET)osfd, &wd);
- if ((rv = select( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
+ return -1;
}
}
}
@@ -463,8 +287,6 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- struct timeval tv, *tvp;
- fd_set rd;
while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr,
addrlen)) == -1)
@@ -472,33 +294,15 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking))
{
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
+ rv = socket_io_wait(osfd, READ_FD, timeout);
+ if ( rv < 0)
{
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&rd);
- FD_SET((SOCKET)osfd, &rd);
- if ((rv = select(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
- {
- _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
- } else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- }
+ }
}
else
{
- _PR_MD_MAP_RECVFROM_ERROR(err);
+ _PR_MD_MAP_RECVFROM_ERROR(err);
break;
}
}
@@ -546,9 +350,9 @@ _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
PRInt32 rv;
rv = shutdown(fd->secret->md.osfd, how);
- if (rv < 0)
- _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
- return rv;
+ if (rv < 0)
+ _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
+ return rv;
}
PRStatus
@@ -557,12 +361,12 @@ _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
PRInt32 rv;
rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
}
PRStatus
@@ -571,12 +375,12 @@ _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
PRInt32 rv;
rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
}
PRStatus
@@ -585,12 +389,12 @@ _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval,
PRInt32 rv;
rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
}
PRStatus
@@ -599,16 +403,210 @@ _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* op
PRInt32 rv;
rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
- return PR_FAILURE;
- }
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
}
void
_MD_MakeNonblock(PRFileDesc *f)
{
- return; // do nothing!
+ return; /* do nothing */
}
+
+
+
+/*
+ * socket_io_wait --
+ *
+ * Wait for socket i/o, periodically checking for interrupt.
+ *
+ * This function returns 1 on success. On failure, it returns
+ * -1 and sets the error codes. It never returns 0.
+ */
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+
+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;
+ 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:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ FD_ZERO(&ex);
+ do {
+ FD_SET(osfd, &rd_wr);
+ FD_SET(osfd, &ex);
+ switch( fd_type )
+ {
+ case READ_FD:
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ break;
+ case WRITE_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ break;
+ case CONNECT_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, &ex, &tv);
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ } /* end switch() */
+ if (rv == -1 )
+ {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ }
+ if ( rv > 0 && fd_type == CONNECT_FD )
+ {
+ /*
+ * Call Sleep(0) to work around a Winsock timing bug.
+ */
+ Sleep(0);
+ if (FD_ISSET((SOCKET)osfd, &ex))
+ {
+ len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &len) == SOCKET_ERROR)
+ {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (err != 0)
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ if (FD_ISSET((SOCKET)osfd, &rd_wr))
+ {
+ /* it's connected */
+ return 1;
+ }
+ PR_ASSERT(0);
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0);
+ break;
+ default:
+ remaining = timeout;
+ FD_ZERO(&rd_wr);
+ 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.
+ */
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ 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);
+ FD_SET(osfd, &ex);
+ switch( fd_type )
+ {
+ case READ_FD:
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ break;
+ case WRITE_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ break;
+ case CONNECT_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, &ex, &tv);
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ } /* end switch() */
+ if (rv == -1)
+ {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ }
+ if ( rv > 0 && fd_type == CONNECT_FD )
+ {
+ /*
+ * Call Sleep(0) to work around a Winsock timing bug.
+ */
+ Sleep(0);
+ if (FD_ISSET((SOCKET)osfd, &ex))
+ {
+ len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &len) == SOCKET_ERROR)
+ {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (err != 0)
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ if (FD_ISSET((SOCKET)osfd, &rd_wr))
+ {
+ /* it's connected */
+ return 1;
+ }
+ PR_ASSERT(0);
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ 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 (elapsed >= remaining) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = remaining - elapsed;
+ }
+ }
+ } while (rv == 0 );
+ break;
+ }
+ return(rv);
+} /* end socket_io_wait() */
diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c
index 41da9922..89103bb2 100644
--- a/pr/src/md/windows/w95thred.c
+++ b/pr/src/md/windows/w95thred.c
@@ -242,3 +242,16 @@ _PR_MD_RESUME_THREAD(PRThread *thread)
}
}
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+}
diff --git a/pr/src/md/windows/win32_errors.c b/pr/src/md/windows/win32_errors.c
index 884d8ce1..1899a1be 100644
--- a/pr/src/md/windows/win32_errors.c
+++ b/pr/src/md/windows/win32_errors.c
@@ -17,9 +17,24 @@
*/
#include "prerror.h"
+#include "prlog.h"
#include <errno.h>
#include <windows.h>
+/*
+ * On Win32, we map three kinds of error codes:
+ * - GetLastError(): for Win32 functions
+ * - WSAGetLastError(): for Winsock functions
+ * - errno: for standard C library functions
+ *
+ * We do not check for WSAEINPROGRESS and WSAEINTR because we do not
+ * use blocking Winsock 1.1 calls.
+ *
+ * Except for the 'socket' call, we do not check for WSAEINITIALISED.
+ * It is assumed that if Winsock is not initialized, that fact will
+ * be detected at the time we create new sockets.
+ */
+
void _MD_win32_map_opendir_error(PRInt32 err)
{
switch (err) {
@@ -121,9 +136,11 @@ void _MD_win32_map_delete_error(PRInt32 err)
break;
case ERROR_DRIVE_LOCKED:
case ERROR_LOCKED:
- case ERROR_SHARING_VIOLATION:
PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
break;
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_BUSY_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -350,6 +367,7 @@ void _MD_win32_map_read_error(PRInt32 err)
case ERROR_INVALID_HANDLE:
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
break;
+ case ERROR_NOACCESS:
case ERROR_INVALID_ADDRESS:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
@@ -370,21 +388,14 @@ void _MD_win32_map_read_error(PRInt32 err)
break;
case ERROR_DRIVE_LOCKED:
case ERROR_LOCKED:
- case ERROR_SHARING_VIOLATION:
PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
break;
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_BUSY_ERROR, err);
+ break;
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case WSAENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case WSAEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -421,9 +432,11 @@ void _MD_win32_map_transmitfile_error(PRInt32 err)
break;
case ERROR_DRIVE_LOCKED:
case ERROR_LOCKED:
- case ERROR_SHARING_VIOLATION:
PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
break;
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_BUSY_ERROR, err);
+ break;
case ERROR_FILENAME_EXCED_RANGE:
PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
break;
@@ -463,6 +476,9 @@ void _MD_win32_map_write_error(PRInt32 err)
case ERROR_STACK_OVERFLOW:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case ERROR_INVALID_PARAMETER:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
case ERROR_DISK_CORRUPT:
case ERROR_DISK_OPERATION_FAILED:
case ERROR_FILE_CORRUPT:
@@ -472,9 +488,11 @@ void _MD_win32_map_write_error(PRInt32 err)
break;
case ERROR_DRIVE_LOCKED:
case ERROR_LOCKED:
- case ERROR_SHARING_VIOLATION:
PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
break;
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_BUSY_ERROR, err);
+ break;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
case ERROR_INVALID_USER_BUFFER:
@@ -490,28 +508,6 @@ void _MD_win32_map_write_error(PRInt32 err)
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case WSAENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case WSAEMSGSIZE:
- case WSAEINVAL:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
- break;
- case WSAENOBUFS:
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
- break;
- case WSAECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case WSAEISCONN:
- PR_SetError(PR_IS_CONNECTED_ERROR, err);
- break;
- case WSAEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -559,6 +555,9 @@ void _MD_win32_map_fsync_error(PRInt32 err)
}
}
+/*
+ * For both CloseHandle() and closesocket().
+ */
void _MD_win32_map_close_error(PRInt32 err)
{
switch (err) {
@@ -572,6 +571,15 @@ void _MD_win32_map_close_error(PRInt32 err)
case ERROR_PATH_BUSY:
PR_SetError(PR_IO_ERROR, err);
break;
+ case WSAENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -580,18 +588,32 @@ void _MD_win32_map_close_error(PRInt32 err)
void _MD_win32_map_socket_error(PRInt32 err)
{
+ PR_ASSERT(err != WSANOTINITIALISED);
switch (err) {
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
case WSAEPROTONOSUPPORT:
PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
break;
case WSAEACCES:
PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
break;
+ case WSAEMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
case WSAENOBUFS:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
break;
+ case WSAEAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEPROTOTYPE:
+ case WSAESOCKTNOSUPPORT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -604,8 +626,8 @@ void _MD_win32_map_recv_error(PRInt32 err)
case WSAEWOULDBLOCK:
PR_SetError(PR_WOULD_BLOCK_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
@@ -613,9 +635,30 @@ void _MD_win32_map_recv_error(PRInt32 err)
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case WSAENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case WSAESHUTDOWN:
+ PR_SetError(PR_SOCKET_SHUTDOWN_ERROR, err);
+ break;
+ case WSAEMSGSIZE:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case WSAECONNRESET:
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case WSAECONNABORTED:
+ case WSAETIMEDOUT:
+ case WSAENETRESET:
+ PR_SetError(PR_CONNECT_ABORTED_ERROR, err);
+ break;
+ case WSAEOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -628,18 +671,39 @@ void _MD_win32_map_recvfrom_error(PRInt32 err)
case WSAEWOULDBLOCK:
PR_SetError(PR_WOULD_BLOCK_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case WSAECONNRESET:
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAETIMEDOUT:
+ PR_SetError(PR_CONNECT_ABORTED_ERROR, err);
+ break;
+ case WSAESHUTDOWN:
+ PR_SetError(PR_SOCKET_SHUTDOWN_ERROR, err);
+ break;
+ case WSAEMSGSIZE:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case WSAEOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -652,9 +716,6 @@ void _MD_win32_map_send_error(PRInt32 err)
case WSAEWOULDBLOCK:
PR_SetError(PR_WOULD_BLOCK_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
@@ -665,18 +726,36 @@ void _MD_win32_map_send_error(PRInt32 err)
case WSAENOBUFS:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
break;
- case WSAECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case WSAEISCONN:
- PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ case WSAENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case WSAECONNRESET:
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAETIMEDOUT:
+ PR_SetError(PR_CONNECT_ABORTED_ERROR, err);
+ break;
+ case WSAESHUTDOWN:
+ PR_SetError(PR_SOCKET_SHUTDOWN_ERROR, err);
+ break;
+ case WSAEHOSTUNREACH:
+ PR_SetError(PR_HOST_UNREACHABLE_ERROR, err);
+ break;
+ case WSAEOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -689,31 +768,56 @@ void _MD_win32_map_sendto_error(PRInt32 err)
case WSAEWOULDBLOCK:
PR_SetError(PR_WOULD_BLOCK_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
case WSAEMSGSIZE:
+ case WSAEDESTADDRREQ:
case WSAEINVAL:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
break;
case WSAENOBUFS:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
break;
- case WSAECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case WSAEISCONN:
- PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ case WSAENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case WSAECONNRESET:
case ERROR_NETNAME_DELETED:
PR_SetError(PR_CONNECT_RESET_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAETIMEDOUT:
+ PR_SetError(PR_CONNECT_ABORTED_ERROR, err);
+ break;
+ case WSAESHUTDOWN:
+ PR_SetError(PR_SOCKET_SHUTDOWN_ERROR, err);
+ break;
+ case WSAEHOSTUNREACH:
+ PR_SetError(PR_HOST_UNREACHABLE_ERROR, err);
+ break;
+ case WSAENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case WSAEAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case WSAEADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -726,9 +830,6 @@ void _MD_win32_map_accept_error(PRInt32 err)
case WSAEWOULDBLOCK:
PR_SetError(PR_WOULD_BLOCK_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
@@ -742,7 +843,13 @@ void _MD_win32_map_accept_error(PRInt32 err)
PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
break;
case WSAENOBUFS:
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_STATE_ERROR, err);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -781,9 +888,6 @@ void _MD_win32_map_connect_error(PRInt32 err)
case WSAEINVAL:
PR_SetError(PR_ALREADY_INITIATED_ERROR, err);
break;
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAEADDRNOTAVAIL:
PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
break;
@@ -811,6 +915,15 @@ void _MD_win32_map_connect_error(PRInt32 err)
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case WSAEACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -820,9 +933,6 @@ void _MD_win32_map_connect_error(PRInt32 err)
void _MD_win32_map_bind_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
@@ -835,12 +945,15 @@ void _MD_win32_map_bind_error(PRInt32 err)
case WSAEADDRINUSE:
PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
break;
- case WSAEACCES:
- PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
- break;
case WSAEINVAL:
PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -850,15 +963,30 @@ void _MD_win32_map_bind_error(PRInt32 err)
void _MD_win32_map_listen_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
case WSAEOPNOTSUPP:
PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_STATE_ERROR, err);
+ break;
+ case WSAEISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case WSAENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case WSAEADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case WSAEMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -868,15 +996,18 @@ void _MD_win32_map_listen_error(PRInt32 err)
void _MD_win32_map_shutdown_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
case WSAENOTCONN:
PR_SetError(PR_NOT_CONNECTED_ERROR, err);
break;
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
break;
@@ -886,17 +1017,17 @@ void _MD_win32_map_shutdown_error(PRInt32 err)
void _MD_win32_map_getsockname_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
- case WSAENOBUFS:
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAEINVAL:
+ PR_SetError(PR_INVALID_STATE_ERROR, err);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -908,9 +1039,6 @@ void _MD_win32_map_getpeername_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
@@ -920,8 +1048,8 @@ void _MD_win32_map_getpeername_error(PRInt32 err)
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
- case WSAENOBUFS:
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -932,20 +1060,18 @@ void _MD_win32_map_getpeername_error(PRInt32 err)
void _MD_win32_map_getsockopt_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
+ case WSAEINVAL:
case WSAENOPROTOOPT:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
- case WSAEINVAL:
- PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -956,20 +1082,24 @@ void _MD_win32_map_getsockopt_error(PRInt32 err)
void _MD_win32_map_setsockopt_error(PRInt32 err)
{
switch (err) {
- case WSAEBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
case WSAENOTSOCK:
PR_SetError(PR_NOT_SOCKET_ERROR, err);
break;
+ case WSAEINVAL:
case WSAENOPROTOOPT:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
break;
case WSAEFAULT:
PR_SetError(PR_ACCESS_FAULT_ERROR, err);
break;
- case WSAEINVAL:
- PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ case WSAENETDOWN:
+ PR_SetError(PR_NETWORK_DOWN_ERROR, err);
+ break;
+ case WSAENETRESET:
+ PR_SetError(PR_CONNECT_ABORTED_ERROR, err);
+ break;
+ case WSAENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -1066,6 +1196,9 @@ void _MD_win32_map_select_error(PRInt32 err)
case WSAEFAULT:
prerror = PR_ACCESS_FAULT_ERROR;
break;
+ case WSAENETDOWN:
+ prerror = PR_NETWORK_DOWN_ERROR;
+ break;
default:
prerror = PR_UNKNOWN_ERROR;
}
@@ -1088,9 +1221,11 @@ void _MD_win32_map_lockf_error(PRInt32 err)
break;
case ERROR_DRIVE_LOCKED:
case ERROR_LOCKED:
- case ERROR_SHARING_VIOLATION:
PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
break;
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_BUSY_ERROR, err);
+ break;
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_OUTOFMEMORY:
PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
diff --git a/pr/src/memory/prseg.c b/pr/src/memory/prseg.c
index c32c5225..86399186 100644
--- a/pr/src/memory/prseg.c
+++ b/pr/src/memory/prseg.c
@@ -29,7 +29,7 @@ void _PR_InitSegs(void)
** This memory is not part of the malloc heap. If "vaddr" is not NULL
** then PR tries to allocate the segment at the desired virtual address.
*/
-PR_IMPLEMENT(PRSegment*) PR_NewSegment(PRUint32 size, void *vaddr)
+PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr)
{
PRSegment *seg;
@@ -54,141 +54,8 @@ PR_IMPLEMENT(PRSegment*) PR_NewSegment(PRUint32 size, void *vaddr)
/*
** Free a memory segment.
*/
-PR_IMPLEMENT(void) PR_DestroySegment(PRSegment *seg)
+void _PR_DestroySegment(PRSegment *seg)
{
_PR_MD_FREE_SEGMENT(seg);
PR_DELETE(seg);
}
-
-/* XXX Fix the following to make machine-independent */
-#ifdef XP_UNIX
-#include <sys/mman.h>
-#endif
-
-#ifndef PROT_NONE
-#define PROT_NONE 0
-#endif
-
-extern PRInt32 _pr_zero_fd;
-
-/*
-** Attempt to grow/shrink the given segment.
-*/
-PR_IMPLEMENT(PRUint32) PR_GrowSegment(PRSegment *seg, PRInt32 delta)
-{
- char *oldend, *newend;
-#if 0
-#ifdef XP_UNIX
- int prot;
- void *rv = (void *) -1;
-#endif
-#endif /* 0 */
-
- if (!(seg->flags & _PR_SEG_VM)) {
- return 0;
- }
-
- oldend = (char*)seg->vaddr + seg->size;
- if (delta > 0) {
-#if 0
-
- /*
- * CANNOT use MAP_FIXED because it will replace any existing mappings
- */
- /* Growing the segment */
- delta = ((delta + _pr_pageSize - 1) >> _pr_pageShift) << _pr_pageShift;
- newend = oldend + delta;
-#ifdef XP_UNIX
- prot = PROT_READ|PROT_WRITE;
- rv = mmap(oldend, delta, prot,
-#ifdef OSF1
- /* XXX need to pick a vaddr to use */
- MAP_PRIVATE|MAP_FIXED,
-#else
- MAP_SHARED|MAP_FIXED,
-#endif
- _pr_zero_fd, 0);
-#endif /* XP_UNIX */
- if (rv == (void*)-1) {
- /* Can't extend the heap */
- return 0;
- }
- seg->size = seg->size + delta;
-#endif /* 0 */
- } else if (delta < 0) {
- /* Shrinking the segment */
- delta = -delta;
- delta = (delta >> _pr_pageShift) << _pr_pageShift; /* trunc */
- if ((PRUint32)delta >= seg->size) {
- /* XXX what to do? */
- return 0;
- }
- newend = oldend - delta;
- if (newend < oldend) {
-#ifdef XP_UNIX
- (void) munmap(oldend, newend - oldend);
- seg->size = seg->size + delta;
-#endif
- }
- }
- return delta;
-}
-
-/*
-** Change the mapping on a segment.
-** "how" == PR_SEGMENT_NONE: the segment becomes unmapped
-** "how" == PR_SEGMENT_RDONLY: the segment becomes mapped and readable
-** "how" == PR_SEGMENT_RDWR: the segment becomes mapped read/write
-**
-** If a segment can be read then it is also possible to execute code in
-** it.
-*/
-PR_IMPLEMENT(void) PR_MapSegment(PRSegment *seg, PRSegmentAccess how)
-{
- if (seg->access == how) return;
- seg->access = how;
-
-#ifdef XP_UNIX
-#ifndef RHAPSODY
- if (seg->flags & _PR_SEG_VM) {
- int prot;
- switch (how) {
- case PR_SEGMENT_NONE:
- prot = PROT_NONE;
- break;
- case PR_SEGMENT_RDONLY:
- prot = PROT_READ;
- break;
- case PR_SEGMENT_RDWR:
- prot = PROT_READ|PROT_WRITE;
- break;
- }
- (void) mprotect(seg->vaddr, seg->size, prot);
- }
-#endif
-#endif
-}
-
-/*
-** Return the size of the segment
-*/
-PR_IMPLEMENT(size_t) PR_GetSegmentSize(PRSegment *seg)
-{
- return seg->size;
-}
-
-/*
-** Return the virtual address of the segment
-*/
-PR_IMPLEMENT(void*) PR_GetSegmentVaddr(PRSegment *seg)
-{
- return seg->vaddr;
-}
-
-/*
-** Return a segments current access rights
-*/
-PR_IMPLEMENT(PRSegmentAccess) PR_GetSegmentAccess(PRSegment *seg)
-{
- return seg->access;
-}
diff --git a/pr/src/misc/Makefile b/pr/src/misc/Makefile
index 015fc259..313021c8 100644
--- a/pr/src/misc/Makefile
+++ b/pr/src/misc/Makefile
@@ -28,9 +28,10 @@ OPTIMIZER =
endif
endif
-CSRCS = \
+CSRCS = \
pralarm.c \
pratom.c \
+ prcountr.c \
prdtoa.c \
prenv.c \
prerror.c \
@@ -39,9 +40,11 @@ CSRCS = \
prlog2.c \
prlong.c \
prnetdb.c \
+ prolock.c \
prsystem.c \
prtime.c \
prthinfo.c \
+ prtrace.c \
$(NULL)
TARGETS = $(OBJS)
diff --git a/pr/src/misc/pratom.c b/pr/src/misc/pratom.c
index 78ba8173..d69bb6b0 100644
--- a/pr/src/misc/pratom.c
+++ b/pr/src/misc/pratom.c
@@ -62,6 +62,20 @@ _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
}
PRInt32
+_PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(monitor);
+ rv = ((*ptr) += val);
+ PR_Unlock(monitor);
+ return rv;
+}
+
+PRInt32
_PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
{
PRInt32 rv;
@@ -115,3 +129,94 @@ PR_AtomicSet(PRInt32 *val, PRInt32 newval)
return _PR_MD_ATOMIC_SET(val, newval);
}
+PR_IMPLEMENT(PRInt32)
+PR_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+{
+ return _PR_MD_ATOMIC_ADD(ptr, val);
+}
+/*
+ * For platforms, which don't support the CAS (compare-and-swap) instruction
+ * (or an equivalent), the stack operations are implemented by use of PRLock
+ */
+
+PR_IMPLEMENT(PRStack *)
+PR_CreateStack(const char *stack_name)
+{
+PRStack *stack;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+
+ if ((stack = PR_NEW(PRStack)) == NULL) {
+ return NULL;
+ }
+ if (stack_name) {
+ stack->prstk_name = (char *) PR_Malloc(strlen(stack_name) + 1);
+ if (stack->prstk_name == NULL) {
+ PR_DELETE(stack);
+ return NULL;
+ }
+ strcpy(stack->prstk_name, stack_name);
+ } else
+ stack->prstk_name = NULL;
+
+#ifndef _PR_HAVE_ATOMIC_CAS
+ stack->prstk_lock = PR_NewLock();
+ if (stack->prstk_lock == NULL) {
+ PR_Free(stack->prstk_name);
+ PR_DELETE(stack);
+ return NULL;
+ }
+#endif /* !_PR_HAVE_ATOMIC_CAS */
+
+ stack->prstk_head.prstk_elem_next = NULL;
+
+ return stack;
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_DestroyStack(PRStack *stack)
+{
+ if (stack->prstk_head.prstk_elem_next != NULL) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (stack->prstk_name)
+ PR_Free(stack->prstk_name);
+#ifndef _PR_HAVE_ATOMIC_CAS
+ PR_DestroyLock(stack->prstk_lock);
+#endif /* !_PR_HAVE_ATOMIC_CAS */
+ PR_DELETE(stack);
+
+ return PR_SUCCESS;
+}
+
+#ifndef _PR_HAVE_ATOMIC_CAS
+
+PR_IMPLEMENT(void)
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+ PR_Lock(stack->prstk_lock);
+ stack_elem->prstk_elem_next = stack->prstk_head.prstk_elem_next;
+ stack->prstk_head.prstk_elem_next = stack_elem;
+ PR_Unlock(stack->prstk_lock);
+ return;
+}
+
+PR_IMPLEMENT(PRStackElem *)
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+
+ PR_Lock(stack->prstk_lock);
+ element = stack->prstk_head.prstk_elem_next;
+ if (element != NULL) {
+ stack->prstk_head.prstk_elem_next = element->prstk_elem_next;
+ element->prstk_elem_next = NULL; /* debugging aid */
+ }
+ PR_Unlock(stack->prstk_lock);
+ return element;
+}
+#endif /* !_PR_HAVE_ATOMIC_CAS */
diff --git a/pr/src/misc/prcountr.c b/pr/src/misc/prcountr.c
new file mode 100644
index 00000000..33e85d82
--- /dev/null
+++ b/pr/src/misc/prcountr.c
@@ -0,0 +1,510 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** prcountr.c -- NSPR Instrumentation Counters
+**
+** Implement the interface defined in prcountr.h
+**
+** Design Notes:
+**
+** The Counter Facility (CF) has a single anchor: qNameList.
+** The anchor is a PRCList. qNameList is a list of links in QName
+** structures. From qNameList any QName structure and its
+** associated RName structure can be located.
+**
+** For each QName, a list of RName structures is anchored at
+** rnLink in the QName structure.
+**
+** The counter itself is embedded in the RName structure.
+**
+** For manipulating the counter database, single lock is used to
+** protect the entire list: counterLock.
+**
+** A PRCounterHandle, defined in prcountr.h, is really a pointer
+** to a RName structure. References by PRCounterHandle are
+** dead-reconed to the RName structure. The PRCounterHandle is
+** "overloaded" for traversing the QName structures; only the
+** function PR_FindNextQnameHandle() uses this overloading.
+**
+**
+** ToDo (lth): decide on how to lock or atomically update
+** individual counters. Candidates are: the global lock; a lock
+** per RName structure; Atomic operations (Note that there are
+** not adaquate atomic operations (yet) to achieve this goal). At
+** this writing (6/19/98) , the update of the counter variable in
+** a QName structure is unprotected.
+**
+*/
+
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#include "prcountr.h"
+#include "prclist.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include <string.h>
+
+/*
+**
+*/
+typedef struct QName
+{
+ PRCList link;
+ PRCList rNameList;
+ char name[PRCOUNTER_NAME_MAX+1];
+} QName;
+
+/*
+**
+*/
+typedef struct RName
+{
+ PRCList link;
+ QName *qName;
+ PRLock *lock;
+ volatile PRUint32 counter;
+ char name[PRCOUNTER_NAME_MAX+1];
+ char desc[PRCOUNTER_DESC_MAX+1];
+} RName;
+
+
+/*
+** Define the Counter Facility database
+*/
+static PRLock *counterLock;
+static PRCList qNameList;
+static PRLogModuleInfo *lm;
+
+/*
+** _PR_CounterInitialize() -- Initialize the Counter Facility
+**
+*/
+static void _PR_CounterInitialize( void )
+{
+ /*
+ ** This function should be called only once
+ */
+ PR_ASSERT( counterLock == NULL );
+
+ counterLock = PR_NewLock();
+ PR_INIT_CLIST( &qNameList );
+ lm = PR_NewLogModule("counters");
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete"));
+
+ return;
+} /* end _PR_CounterInitialize() */
+
+/*
+** PR_CreateCounter() -- Create a counter
+**
+** ValidateArguments
+** Lock
+** if (qName not already in database)
+** NewQname
+** if (rName already in database )
+** Assert
+** else NewRname
+** NewCounter
+** link 'em up
+** Unlock
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_CreateCounter(
+ const char *qName,
+ const char *rName,
+ const char *description
+)
+{
+ QName *qnp;
+ RName *rnp;
+ PRBool matchQname = PR_FALSE;
+
+ /* Self initialize, if necessary */
+ if ( counterLock == NULL )
+ _PR_CounterInitialize();
+
+ /* Validate input arguments */
+ PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX );
+ PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX );
+ PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX );
+
+ /* Lock the Facility */
+ PR_Lock( counterLock );
+
+ /* Do we already have a matching QName? */
+ if (!PR_CLIST_IS_EMPTY( &qNameList ))
+ {
+ qnp = (QName *) PR_LIST_HEAD( &qNameList );
+ do {
+ if ( strcmp(qnp->name, qName) == 0)
+ {
+ matchQname = PR_TRUE;
+ break;
+ }
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+ } while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
+ }
+ /*
+ ** If we did not find a matching QName,
+ ** allocate one and initialize it.
+ ** link it onto the qNameList.
+ **
+ */
+ if ( matchQname != PR_TRUE )
+ {
+ qnp = PR_NEWZAP( QName );
+ PR_ASSERT( qnp != NULL );
+ PR_INIT_CLIST( &qnp->link );
+ PR_INIT_CLIST( &qnp->rNameList );
+ strcpy( qnp->name, qName );
+ PR_APPEND_LINK( &qnp->link, &qNameList );
+ }
+
+ /* Do we already have a matching RName? */
+ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ {
+ rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
+ do {
+ /*
+ ** No duplicate RNames are allowed within a QName
+ **
+ */
+ PR_ASSERT( strcmp(rnp->name, rName));
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+ } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
+ }
+
+ /* Get a new RName structure; initialize its members */
+ rnp = PR_NEWZAP( RName );
+ PR_ASSERT( rnp != NULL );
+ PR_INIT_CLIST( &rnp->link );
+ strcpy( rnp->name, rName );
+ strcpy( rnp->desc, description );
+ rnp->lock = PR_NewLock();
+ if ( rnp->lock == NULL )
+ {
+ PR_ASSERT(0);
+ }
+
+ PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
+ rnp->qName = qnp; /* point the RName to the QName */
+
+ /* Unlock the Facility */
+ PR_Unlock( counterLock );
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t",
+ qName, qnp, rName, rnp ));
+
+ return((PRCounterHandle)rnp);
+} /* end PR_CreateCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyCounter(
+ PRCounterHandle handle
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s",
+ qnp->name, rnp->name));
+
+ /* Lock the Facility */
+ PR_Lock( counterLock );
+
+ /*
+ ** Remove RName from the list of RNames in QName
+ ** and free RName
+ */
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p",
+ rnp->name, rnp));
+ PR_REMOVE_LINK( &rnp->link );
+ PR_Free( rnp->lock );
+ PR_DELETE( rnp );
+
+ /*
+ ** If this is the last RName within QName
+ ** remove QName from the qNameList and free it
+ */
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p",
+ qnp->name, qnp));
+ PR_REMOVE_LINK( &qnp->link );
+ PR_DELETE( qnp );
+ }
+
+ /* Unlock the Facility */
+ PR_Unlock( counterLock );
+ return;
+} /* end PR_DestroyCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_GetCounterHandleFromName(
+ const char *qName,
+ const char *rName
+)
+{
+ const char *qn, *rn, *desc;
+ PRCounterHandle qh, rh;
+ RName *rnp = NULL;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t"
+ "QName: %s, RName: %s", qName, rName ));
+
+ qh = PR_FindNextCounterQname( NULL );
+ while (qh != NULL)
+ {
+ rh = PR_FindNextCounterRname( NULL, qh );
+ while ( rh != NULL )
+ {
+ PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc );
+ if ( (strcmp( qName, qn ) == 0)
+ && (strcmp( rName, rn ) == 0 ))
+ {
+ rnp = (RName *)rh;
+ goto foundIt;
+ }
+ rh = PR_FindNextCounterRname( rh, qh );
+ }
+ qh = PR_FindNextCounterQname( NULL );
+ }
+
+foundIt:
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
+ return(rh);
+} /* end PR_GetCounterHandleFromName() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetCounterNameFromHandle(
+ PRCounterHandle handle,
+ const char **qName,
+ const char **rName,
+ const char **description
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ *qName = qnp->name;
+ *rName = rnp->name;
+ *description = rnp->desc;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: "
+ "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
+ qnp, rnp, qnp->name, rnp->name, rnp->desc ));
+
+ return;
+} /* end PR_GetCounterNameFromHandle() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_IncrementCounter(
+ PRCounterHandle handle
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter++;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_IncrementCounter() */
+
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DecrementCounter(
+ PRCounterHandle handle
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter--;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_DecrementCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_AddToCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter += value;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_AddToCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SubtractFromCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter -= value;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_SubtractFromCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRUint32)
+ PR_GetCounter(
+ PRCounterHandle handle
+)
+{
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return(((RName *)handle)->counter);
+} /* end PR_GetCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SetCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ ((RName *)handle)->counter = value;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_SetCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_FindNextCounterQname(
+ PRCounterHandle handle
+)
+{
+ QName *qnp = (QName *)handle;
+
+ if ( PR_CLIST_IS_EMPTY( &qNameList ))
+ qnp = NULL;
+ else if ( qnp == NULL )
+ qnp = (QName *)PR_LIST_HEAD( &qNameList );
+ else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
+ qnp = NULL;
+ else
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p",
+ handle, qnp ));
+
+ return((PRCounterHandle)qnp);
+} /* end PR_FindNextCounterQname() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_FindNextCounterRname(
+ PRCounterHandle rhandle,
+ PRCounterHandle qhandle
+)
+{
+ RName *rnp = (RName *)rhandle;
+ QName *qnp = (QName *)qhandle;
+
+
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ rnp = NULL;
+ else if ( rnp == NULL )
+ rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
+ else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
+ rnp = NULL;
+ else
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
+ rhandle, qhandle, rnp ));
+
+ return((PRCounterHandle)rnp);
+} /* end PR_FindNextCounterRname() */
+
+
+#else /* !(defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)) */
+/*
+** NSPR Counters are not defined in this case
+**
+**
+*/
+#endif /* defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) */
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pr/src/misc/prdtoa.c b/pr/src/misc/prdtoa.c
index ef3d50a0..3fadb2b1 100644
--- a/pr/src/misc/prdtoa.c
+++ b/pr/src/misc/prdtoa.c
@@ -1842,7 +1842,7 @@ quorem(Bigint *b, Bigint *S)
*/
PR_IMPLEMENT(PRStatus)
-PR_dtoa(double d, int mode, int ndigits,
+PR_dtoa(PRFloat64 d, int mode, int ndigits,
int *decpt, int *sign, char **rve, char *buf, PRSize bufsize)
{
/* Arguments ndigits, decpt, sign are similar to those
diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c
index 7c52b38b..4178e3ee 100644
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -45,8 +45,8 @@ PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
PRUint32 _pr_utid;
-PRUintn _pr_userActive;
-PRUintn _pr_systemActive;
+PRInt32 _pr_userActive;
+PRInt32 _pr_systemActive;
PRUintn _pr_maxPTDs;
#ifdef _PR_LOCAL_THREADS_ONLY
@@ -66,29 +66,27 @@ PRLock *_pr_terminationCVLock;
PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */
static void _PR_InitCallOnce(void);
-static void _PR_InitStuff(void);
-/************************************************************************/
-/**************************IDENTITY AND VERSIONING***********************/
-/************************************************************************/
+PRBool _pr_initialized = PR_FALSE;
+
+
PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
{
/*
** This is the secret handshake algorithm. Right now it requires
- ** an exact match. Later it should get more tricky.
+ ** an exact match. Later it should get more clever.
*/
+ if (!_pr_initialized) _PR_ImplicitInitialization();
return ((0 == strcmp(importedVersion, PR_VERSION)) ? PR_TRUE : PR_FALSE);
} /* PR_VersionCheck */
-PRBool _pr_initialized = PR_FALSE;
-
PR_IMPLEMENT(PRBool) PR_Initialized(void)
{
return _pr_initialized;
}
-static void _PR_InitStuff()
+static void _PR_InitStuff(void)
{
if (_pr_initialized) return;
_pr_initialized = PR_TRUE;
@@ -108,13 +106,14 @@ static void _PR_InitStuff()
/* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */
_PR_MD_EARLY_INIT();
- _PR_InitAtomic();
_PR_InitLocks();
+ _PR_InitAtomic();
_PR_InitSegs();
_PR_InitStacks();
_PR_InitTPD();
_PR_InitEnv();
_PR_InitLayerCache();
+ _PR_InitClock();
_pr_sleeplock = PR_NewLock();
PR_ASSERT(NULL != _pr_sleeplock);
@@ -143,13 +142,13 @@ static void _PR_InitStuff()
_PR_InitCMon();
_PR_InitIO();
_PR_InitNet();
- _PR_InitClock();
#ifdef PR_LOGGING
_PR_InitLog();
#endif
_PR_InitLinker();
_PR_InitCallOnce();
_PR_InitDtoa();
+ _PR_InitMW();
_PR_MD_FINAL_INIT();
}
@@ -176,6 +175,16 @@ PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
#endif
}
+PR_IMPLEMENT(void) PR_EnableClockInterrupts(void)
+{
+#if !defined(_PR_PTHREADS)
+ if (!_pr_initialized) {
+ _PR_InitStuff();
+ }
+ _PR_MD_ENABLE_CLOCK_INTERRUPTS();
+#endif
+}
+
PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
{
#if !defined(_PR_PTHREADS)
@@ -285,7 +294,6 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL));
if ((NULL != me) && (me->flags & _PR_PRIMORDIAL))
{
-
PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
/*
@@ -303,6 +311,14 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
}
PR_Unlock(_pr_activeLock);
+#ifdef IRIX
+ _PR_MD_PRE_CLEANUP(me);
+ /*
+ * The primordial thread must now be running on the primordial cpu
+ */
+ PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0));
+#endif
+
#if defined(WIN16)
_PR_ShutdownLinker();
#endif
@@ -316,6 +332,7 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
#ifdef PR_LOGGING
_PR_LogCleanup();
#endif
+ _PR_CleanupFdCache();
/*
* This part should look like the end of _PR_NativeRunThread
diff --git a/pr/src/misc/prolock.c b/pr/src/misc/prolock.c
new file mode 100644
index 00000000..08123640
--- /dev/null
+++ b/pr/src/misc/prolock.c
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** prolock.c -- NSPR Ordered Lock
+**
+** Implement the API defined in prolock.h
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#include "prolock.h"
+#include "prlog.h"
+#include "prerror.h"
+
+PR_IMPLEMENT(PROrderedLock *)
+ PR_CreateOrderedLock(
+ PRInt32 order,
+ const char *name
+)
+{
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+} /* end PR_CreateOrderedLock() */
+
+
+PR_IMPLEMENT(void)
+ PR_DestroyOrderedLock(
+ PROrderedLock *lock
+)
+{
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+} /* end PR_DestroyOrderedLock() */
+
+
+PR_IMPLEMENT(void)
+ PR_LockOrderedLock(
+ PROrderedLock *lock
+)
+{
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+} /* end PR_LockOrderedLock() */
+
+
+PR_IMPLEMENT(PRStatus)
+ PR_UnlockOrderedLock(
+ PROrderedLock *lock
+)
+{
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+} /* end PR_UnlockOrderedLock() */
+
+#else /* ! defined(FORCE_NSPR_ORDERED_LOCK) */
+/*
+** NSPR Ordered Lock is not defined when !DEBUG and !FORCE_NSPR_ORDERED_LOCK
+**
+*/
+
+#endif /* defined(FORCE_NSPR_ORDERED_LOCK */
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pr/src/misc/prthinfo.c b/pr/src/misc/prthinfo.c
index 6f6ad1e7..e53fc3f2 100644
--- a/pr/src/misc/prthinfo.c
+++ b/pr/src/misc/prthinfo.c
@@ -126,13 +126,10 @@ PR_ThreadScanStackPointers(PRThread* t,
/*
** Mark all of the per-thread-data items attached to this thread
+ **
+ ** The execution environment better be accounted for otherwise it
+ ** will be collected
*/
-
-#if defined(_PR_PTHREADS)
-/* PR_ASSERT(!"I can't do this!"); */
-#else /* defined(_PR_PTHREADS) */
-
- /* the execution environment better be accounted for otherwise it will be collected */
status = scanFun(t, (void**)&t->environment, 1, scanClosure);
if (status != PR_SUCCESS)
return status;
@@ -143,8 +140,7 @@ PR_ThreadScanStackPointers(PRThread* t,
if (status != PR_SUCCESS)
return status;
}
-#endif /* defined(_PR_PTHREADS) */
-
+
return PR_SUCCESS;
}
@@ -173,7 +169,7 @@ PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure)
return PR_EnumerateThreads(pr_ScanStack, &data);
}
-PR_PUBLIC_API(PRUword)
+PR_IMPLEMENT(PRUword)
PR_GetStackSpaceLeft(PRThread* t)
{
PRThread *current = PR_CurrentThread();
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index 59ea80d4..25bccf79 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -524,16 +524,23 @@ PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params)
#include <time.h>
-#if (defined(OSF1) && !defined(OSF1V4)) || defined(HPUX10_10) \
- || defined(HPUX10_20)
+#if defined(HAVE_INT_LOCALTIME_R)
+
+/*
+ * In this case we could define the macro as
+ * #define MT_safe_localtime(timer, result) \
+ * (localtime_r(timer, result) == 0 ? result : NULL)
+ * I chose to compare the return value of localtime_r with -1 so
+ * that I can catch the cases where localtime_r returns a pointer
+ * to struct tm. The macro definition above would not be able to
+ * detect such mistakes because it is legal to compare a pointer
+ * with 0.
+ */
#define MT_safe_localtime(timer, result) \
- (localtime_r(timer, result) == 0 ? result : NULL)
+ (localtime_r(timer, result) == -1 ? NULL: result)
-#elif (defined(SOLARIS) && defined(_REENTRANT)) || defined(IRIX) \
- || (defined(AIX) && !defined(AIX4_1) && defined(_THREAD_SAFE)) \
- || defined(OSF1V4) \
- || defined(HPUX10_30) || defined(HPUX11)
+#elif defined(HAVE_POINTER_LOCALTIME_R)
#define MT_safe_localtime localtime_r
@@ -1623,12 +1630,12 @@ PR_FormatTime(char *buf, int buflen, const char *fmt, const PRExplodedTime *tm)
a.tm_isdst = tm->tm_params.tp_dst_offset ? 1 : 0;
/*
- * On SunOS 4, struct tm has two additional fields: tm_zone
- * and tm_gmtoff. The following code attempts to obtain values for
- * these two fields.
+ * On some platforms, for example SunOS 4, struct tm has two additional
+ * fields: tm_zone and tm_gmtoff. The following code attempts to obtain
+ * values for these two fields.
*/
-#if defined(SUNOS4) || defined(MKLINUX) || (__GLIBC__ >= 2)
+#if defined(SUNOS4) || (__GLIBC__ >= 2)
if (mktime(&a) == -1) {
PR_snprintf(buf, buflen, "can't get timezone");
return 0;
diff --git a/pr/src/misc/prtrace.c b/pr/src/misc/prtrace.c
new file mode 100644
index 00000000..c2a64b6c
--- /dev/null
+++ b/pr/src/misc/prtrace.c
@@ -0,0 +1,912 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** prtrace.c -- NSPR Trace Instrumentation
+**
+** Implement the API defined in prtrace.h
+**
+**
+**
+*/
+
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#include <string.h>
+#include "prtrace.h"
+#include "prclist.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prenv.h"
+#include "prmem.h"
+#include "prerror.h"
+
+
+#define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 )
+#define DEFAULT_BUFFER_SEGMENTS 2
+
+/*
+** Enumerate states in a RName structure
+*/
+typedef enum TraceState
+{
+ Running = 1,
+ Suspended = 2
+} TraceState;
+
+/*
+** Define QName structure
+*/
+typedef struct QName
+{
+ PRCList link;
+ PRCList rNameList;
+ char name[PRTRACE_NAME_MAX+1];
+} QName;
+
+/*
+** Define RName structure
+*/
+typedef struct RName
+{
+ PRCList link;
+ PRLock *lock;
+ QName *qName;
+ TraceState state;
+ char name[PRTRACE_NAME_MAX+1];
+ char desc[PRTRACE_DESC_MAX+1];
+} RName;
+
+
+/*
+** The Trace Facility database
+**
+*/
+static PRLogModuleInfo *lm;
+
+static PRLock *traceLock; /* Facility Lock */
+static PRCList qNameList; /* anchor to all QName structures */
+static TraceState traceState = Running;
+
+/*
+** in-memory trace buffer controls
+*/
+static PRTraceEntry *tBuf; /* pointer to buffer */
+static PRInt32 bufSize; /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */
+static volatile PRInt32 next; /* index to next PRTraceEntry */
+static PRInt32 last; /* index of highest numbered trace entry */
+
+/*
+** Real-time buffer capture controls
+*/
+static PRInt32 fetchLastSeen = 0;
+static PRBool fetchLostData = PR_FALSE;
+
+/*
+** Buffer write-to-file controls
+*/
+static PRLock *logLock; /* Sync lock */
+static PRCondVar *logCVar; /* Sync Condidtion Variable */
+/*
+** Inter-thread state communication.
+** Controling thread writes to logOrder under protection of logCVar
+** the logging thread reads logOrder and sets logState on Notify.
+**
+** logSegments, logCount, logLostData must be read and written under
+** protection of logLock, logCVar.
+**
+*/
+static enum LogState
+{
+ LogNotRunning, /* Initial state */
+ LogReset, /* Causes logger to re-calc controls */
+ LogActive, /* Logging in progress, set only by log thread */
+ LogSuspend, /* Suspend Logging */
+ LogResume, /* Resume Logging => LogActive */
+ LogStop /* Stop the log thread */
+} logOrder, logState, localState; /* controlling state variables */
+static PRInt32 logSegments; /* Number of buffer segments */
+static PRInt32 logEntries; /* number of Trace Entries in the buffer */
+static PRInt32 logEntriesPerSegment; /* number of PRTraceEntries per buffer segment */
+static PRInt32 logSegSize; /* size of buffer segment */
+static PRInt32 logCount; /* number of segments pending output */
+static PRInt32 logLostData; /* number of lost log buffer segments */
+
+/*
+** end Trace Database
+**
+*/
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void NewTraceBuffer( PRInt32 size )
+{
+ /*
+ ** calculate the size of the buffer
+ ** round down so that each segment has the same number of
+ ** trace entries
+ */
+ logSegments = DEFAULT_BUFFER_SEGMENTS;
+ logEntries = size / sizeof(PRTraceEntry);
+ logEntriesPerSegment = logEntries / logSegments;
+ logEntries = logSegments * logEntriesPerSegment;
+ bufSize = logEntries * sizeof(PRTraceEntry);
+ logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);
+ PR_ASSERT( bufSize != 0);
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",
+ logSegments, logEntries, logEntriesPerSegment, logSegSize ));
+
+
+ tBuf = PR_Malloc( bufSize );
+ if ( tBuf == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRTrace: Failed to get trace buffer"));
+ PR_ASSERT( 0 );
+ }
+ else
+ {
+ PR_LOG( lm, PR_LOG_NOTICE,
+ ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));
+ }
+
+ next = 0;
+ last = logEntries -1;
+ logCount = 0;
+ logLostData = PR_TRUE; /* not really on first call */
+ logOrder = LogReset;
+
+} /* end NewTraceBuffer() */
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void _PR_InitializeTrace( void )
+{
+ /* The lock pointer better be null on this call */
+ PR_ASSERT( traceLock == NULL );
+
+ traceLock = PR_NewLock();
+ PR_ASSERT( traceLock != NULL );
+
+ PR_Lock( traceLock );
+
+ PR_INIT_CLIST( &qNameList );
+
+ lm = PR_NewLogModule("trace");
+
+ bufSize = DEFAULT_TRACE_BUFSIZE;
+ NewTraceBuffer( bufSize );
+
+ /* Initialize logging controls */
+ logLock = PR_NewLock();
+ logCVar = PR_NewCondVar( logLock );
+
+ PR_Unlock( traceLock );
+ return;
+} /* end _PR_InitializeTrace() */
+
+/*
+** Create a Trace Handle
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_CreateTrace(
+ const char *qName, /* QName for this trace handle */
+ const char *rName, /* RName for this trace handle */
+ const char *description /* description for this trace handle */
+)
+{
+ QName *qnp;
+ RName *rnp;
+ PRBool matchQname = PR_FALSE;
+
+ /* Self initialize, if necessary */
+ if ( traceLock == NULL )
+ _PR_InitializeTrace();
+
+ /* Validate input arguments */
+ PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );
+ PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );
+ PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );
+
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));
+
+ /* Lock the Facility */
+ PR_Lock( traceLock );
+
+ /* Do we already have a matching QName? */
+ if (!PR_CLIST_IS_EMPTY( &qNameList ))
+ {
+ qnp = (QName *) PR_LIST_HEAD( &qNameList );
+ do {
+ if ( strcmp(qnp->name, qName) == 0)
+ {
+ matchQname = PR_TRUE;
+ break;
+ }
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+ } while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
+ }
+ /*
+ ** If we did not find a matching QName,
+ ** allocate one and initialize it.
+ ** link it onto the qNameList.
+ **
+ */
+ if ( matchQname != PR_TRUE )
+ {
+ qnp = PR_NEWZAP( QName );
+ PR_ASSERT( qnp != NULL );
+ PR_INIT_CLIST( &qnp->link );
+ PR_INIT_CLIST( &qnp->rNameList );
+ strcpy( qnp->name, qName );
+ PR_APPEND_LINK( &qnp->link, &qNameList );
+ }
+
+ /* Do we already have a matching RName? */
+ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ {
+ rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
+ do {
+ /*
+ ** No duplicate RNames are allowed within a QName
+ **
+ */
+ PR_ASSERT( strcmp(rnp->name, rName));
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+ } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
+ }
+
+ /* Get a new RName structure; initialize its members */
+ rnp = PR_NEWZAP( RName );
+ PR_ASSERT( rnp != NULL );
+ PR_INIT_CLIST( &rnp->link );
+ strcpy( rnp->name, rName );
+ strcpy( rnp->desc, description );
+ rnp->lock = PR_NewLock();
+ rnp->state = Running;
+ if ( rnp->lock == NULL )
+ {
+ PR_ASSERT(0);
+ }
+
+ PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
+ rnp->qName = qnp; /* point the RName to the QName */
+
+ /* Unlock the Facility */
+ PR_Unlock( traceLock );
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",
+ qName, qnp, rName, rnp ));
+
+ return((PRTraceHandle)rnp);
+} /* end PR_CreateTrace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyTrace(
+ PRTraceHandle handle /* Handle to be destroyed */
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s",
+ qnp->name, rnp->name));
+
+ /* Lock the Facility */
+ PR_Lock( traceLock );
+
+ /*
+ ** Remove RName from the list of RNames in QName
+ ** and free RName
+ */
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p",
+ rnp->name, rnp));
+ PR_REMOVE_LINK( &rnp->link );
+ PR_Free( rnp->lock );
+ PR_DELETE( rnp );
+
+ /*
+ ** If this is the last RName within QName
+ ** remove QName from the qNameList and free it
+ */
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p",
+ qnp->name, qnp));
+ PR_REMOVE_LINK( &qnp->link );
+ PR_DELETE( qnp );
+ }
+
+ /* Unlock the Facility */
+ PR_Unlock( traceLock );
+ return;
+} /* end PR_DestroyTrace() */
+
+/*
+** Create a TraceEntry in the trace buffer
+*/
+PR_IMPLEMENT(void)
+ PR_Trace(
+ PRTraceHandle handle, /* use this trace handle */
+ PRUint32 userData0, /* User supplied data word 0 */
+ PRUint32 userData1, /* User supplied data word 1 */
+ PRUint32 userData2, /* User supplied data word 2 */
+ PRUint32 userData3, /* User supplied data word 3 */
+ PRUint32 userData4, /* User supplied data word 4 */
+ PRUint32 userData5, /* User supplied data word 5 */
+ PRUint32 userData6, /* User supplied data word 6 */
+ PRUint32 userData7 /* User supplied data word 7 */
+)
+{
+ PRTraceEntry *tep;
+ PRInt32 mark;
+
+ if ( (traceState == Suspended )
+ || ( ((RName *)handle)->state == Suspended ))
+ return;
+
+ /*
+ ** Get the next trace entry slot w/ minimum delay
+ */
+ PR_Lock( traceLock );
+
+ tep = &tBuf[next++];
+ if ( next > last )
+ next = 0;
+ if ( fetchLostData == PR_FALSE && next == fetchLastSeen )
+ fetchLostData = PR_TRUE;
+
+ mark = next;
+
+ PR_Unlock( traceLock );
+
+ /*
+ ** We have a trace entry. Fill it in.
+ */
+ tep->thread = PR_GetCurrentThread();
+ tep->handle = handle;
+ tep->time = PR_Now();
+ tep->userData[0] = userData0;
+ tep->userData[1] = userData1;
+ tep->userData[2] = userData2;
+ tep->userData[3] = userData3;
+ tep->userData[4] = userData4;
+ tep->userData[5] = userData5;
+ tep->userData[6] = userData6;
+ tep->userData[7] = userData7;
+
+ /* When buffer segment is full, signal trace log thread to run */
+ if (( mark % logEntriesPerSegment) == 0 )
+ {
+ PR_Lock( logLock );
+ logCount++;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ /*
+ ** Gh0D! This is awful!
+ ** Anyway, to minimize lost trace data segments,
+ ** I inserted the PR_Sleep(0) to cause a context switch
+ ** so that the log thread could run.
+ ** I know, it perturbs the universe and may cause
+ ** funny things to happen in the optimized builds.
+ ** Take it out, loose data; leave it in risk Heisenberg.
+ */
+ /* PR_Sleep(0); */
+ }
+
+ return;
+} /* end PR_Trace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+)
+{
+ RName * rnp;
+
+ switch ( command )
+ {
+ case PRTraceBufSize :
+ PR_Lock( traceLock );
+ PR_Free( tBuf );
+ bufSize = *(PRInt32 *)value;
+ NewTraceBuffer( bufSize );
+ PR_Unlock( traceLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));
+ break;
+
+ case PRTraceEnable :
+ rnp = *(RName **)value;
+ rnp->state = Running;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceEnable: %p", rnp));
+ break;
+
+ case PRTraceDisable :
+ rnp = *(RName **)value;
+ rnp->state = Suspended;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceDisable: %p", rnp));
+ break;
+
+ case PRTraceSuspend :
+ traceState = Suspended;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceSuspend"));
+ break;
+
+ case PRTraceResume :
+ traceState = Running;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceResume"));
+ break;
+
+ case PRTraceSuspendRecording :
+ PR_Lock( logLock );
+ logOrder = LogSuspend;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceSuspendRecording"));
+ break;
+
+ case PRTraceResumeRecording :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceResumeRecording"));
+ if ( logState != LogSuspend )
+ break;
+ PR_Lock( logLock );
+ logOrder = LogResume;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ break;
+
+ case PRTraceStopRecording :
+ PR_Lock( logLock );
+ logOrder = LogStop;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceStopRecording"));
+ break;
+
+ case PRTraceLockHandles :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceLockTraceHandles"));
+ PR_Lock( traceLock );
+ break;
+
+ case PRTraceUnLockHandles :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceUnLockHandles"));
+ PR_Lock( traceLock );
+ break;
+
+ default:
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRSetTraceOption: Invalid command %ld", command ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return;
+} /* end PR_SetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+)
+{
+ switch ( command )
+ {
+ case PRTraceBufSize :
+ *((PRInt32 *)value) = bufSize;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize ));
+ break;
+
+ default:
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRGetTraceOption: Invalid command %ld", command ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return;
+} /* end PR_GetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_GetTraceHandleFromName(
+ const char *qName, /* QName search argument */
+ const char *rName /* RName search argument */
+)
+{
+ const char *qn, *rn, *desc;
+ PRTraceHandle qh, rh;
+ RName *rnp = NULL;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t"
+ "QName: %s, RName: %s", qName, rName ));
+
+ qh = PR_FindNextTraceQname( NULL );
+ while (qh != NULL)
+ {
+ rh = PR_FindNextTraceRname( NULL, qh );
+ while ( rh != NULL )
+ {
+ PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc );
+ if ( (strcmp( qName, qn ) == 0)
+ && (strcmp( rName, rn ) == 0 ))
+ {
+ rnp = (RName *)rh;
+ goto foundIt;
+ }
+ rh = PR_FindNextTraceRname( rh, qh );
+ }
+ qh = PR_FindNextTraceQname( NULL );
+ }
+
+foundIt:
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
+ return(rh);
+} /* end PR_GetTraceHandleFromName() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetTraceNameFromHandle(
+ PRTraceHandle handle, /* handle as search argument */
+ const char **qName, /* pointer to associated QName */
+ const char **rName, /* pointer to associated RName */
+ const char **description /* pointer to associated description */
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ *qName = qnp->name;
+ *rName = rnp->name;
+ *description = rnp->desc;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: "
+ "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
+ qnp, rnp, qnp->name, rnp->name, rnp->desc ));
+
+ return;
+} /* end PR_GetTraceNameFromHandle() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_FindNextTraceQname(
+ PRTraceHandle handle
+)
+{
+ QName *qnp = (QName *)handle;
+
+ if ( PR_CLIST_IS_EMPTY( &qNameList ))
+ qnp = NULL;
+ else if ( qnp == NULL )
+ qnp = (QName *)PR_LIST_HEAD( &qNameList );
+ else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
+ qnp = NULL;
+ else
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p",
+ handle, qnp ));
+
+ return((PRTraceHandle)qnp);
+} /* end PR_FindNextTraceQname() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_FindNextTraceRname(
+ PRTraceHandle rhandle,
+ PRTraceHandle qhandle
+)
+{
+ RName *rnp = (RName *)rhandle;
+ QName *qnp = (QName *)qhandle;
+
+
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ rnp = NULL;
+ else if ( rnp == NULL )
+ rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
+ else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
+ rnp = NULL;
+ else
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
+ rhandle, qhandle, rnp ));
+
+ return((PRTraceHandle)rnp);
+} /* end PR_FindNextTraceRname() */
+
+/*
+**
+*/
+static PRFileDesc * InitializeRecording( void )
+{
+ char *logFileName;
+ PRFileDesc *logFile;
+
+ /* Self initialize, if necessary */
+ if ( traceLock == NULL )
+ _PR_InitializeTrace();
+
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: begins"));
+
+ logLostData = 0; /* reset at entry */
+ logState = LogReset;
+
+ /* Get the filename for the logfile from the environment */
+ logFileName = PR_GetEnv( "NSPR_TRACE_LOG" );
+ if ( logFileName == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Environment variable not defined. Exiting"));
+ return NULL;
+ }
+
+ /* Open the logfile */
+ logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 );
+ if ( logFile == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld",
+ logFileName, PR_GetOSError()));
+ return NULL;
+ }
+ return logFile;
+} /* end InitializeRecording() */
+
+/*
+**
+*/
+static void ProcessOrders( void )
+{
+ switch ( logOrder )
+ {
+ case LogReset :
+ logOrder = logState = localState;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogReset"));
+ break;
+
+ case LogSuspend :
+ localState = logOrder = logState = LogSuspend;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogSuspend"));
+ break;
+
+ case LogResume :
+ localState = logOrder = logState = LogActive;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogResume"));
+ break;
+
+ case LogStop :
+ logOrder = logState = LogStop;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogStop"));
+ break;
+
+ default :
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Invalid logOrder: %ld", logOrder ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return ;
+} /* end ProcessOrders() */
+
+/*
+**
+*/
+static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount )
+{
+ PRInt32 rc;
+
+
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount));
+ rc = PR_Write( logFile, buf , amount );
+ if ( rc == -1 )
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() ));
+ else if ( rc != amount )
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc));
+ else
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount));
+
+ return;
+} /* end WriteTraceSegment() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_RecordTraceEntries(
+ void
+)
+{
+ PRFileDesc *logFile;
+ PRInt32 lostSegments;
+ PRInt32 currentSegment = 0;
+ void *buf;
+ PRBool doWrite;
+
+ logFile = InitializeRecording();
+ if ( logFile == NULL )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: Failed to initialize"));
+ return;
+ }
+
+ /* Do this until told to stop */
+ while ( logState != LogStop )
+ {
+
+ PR_Lock( logLock );
+
+ while ( (logCount == 0) && ( logOrder == logState ) )
+ PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT );
+
+ /* Handle state transitions */
+ if ( logOrder != logState )
+ ProcessOrders();
+
+ /* recalculate local controls */
+ if ( logCount )
+ {
+ lostSegments = logCount - logSegments;
+ if ( lostSegments > 0 )
+ {
+ logLostData += ( logCount - logSegments );
+ logCount = (logCount % logSegments);
+ currentSegment = logCount;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: LostData segments: %ld", logLostData));
+ }
+ else
+ {
+ logCount--;
+ }
+
+ buf = tBuf + ( logEntriesPerSegment * currentSegment );
+ if (++currentSegment >= logSegments )
+ currentSegment = 0;
+ doWrite = PR_TRUE;
+ }
+ else
+ doWrite = PR_FALSE;
+
+ PR_Unlock( logLock );
+
+ if ( doWrite == PR_TRUE )
+ {
+ if ( localState != LogSuspend )
+ WriteTraceSegment( logFile, buf, logSegSize );
+ else
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: PR_Write(): is suspended" ));
+ }
+
+ } /* end while(logState...) */
+
+ PR_Close( logFile );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: exiting"));
+ return;
+} /* end PR_RecordTraceEntries() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRIntn)
+ PR_GetTraceEntries(
+ PRTraceEntry *buffer, /* where to write output */
+ PRInt32 count, /* number to get */
+ PRInt32 *found /* number you got */
+)
+{
+ PRInt32 rc;
+ PRInt32 copied = 0;
+
+ PR_Lock( traceLock );
+
+ /*
+ ** Depending on where the LastSeen and Next indices are,
+ ** copy the trace buffer in one or two pieces.
+ */
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen));
+
+ if ( fetchLastSeen <= next )
+ {
+ while (( count-- > 0 ) && (fetchLastSeen < next ))
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+ }
+ else /* copy in 2 parts */
+ {
+ while ( count-- > 0 && fetchLastSeen <= last )
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ fetchLastSeen = 0;
+
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+
+ while ( count-- > 0 && fetchLastSeen < next )
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+ }
+
+ *found = copied;
+ rc = ( fetchLostData == PR_TRUE )? 1 : 0;
+ fetchLostData = PR_FALSE;
+
+ PR_Unlock( traceLock );
+ return rc;
+} /* end PR_GetTraceEntries() */
+
+#else /* !defined(FORCE_NSPR_TRACE) */
+/*
+** The trace facility is not defined when !DEBUG and !FORCE_NSPR_TRACE
+**
+*/
+
+#endif /* defined(FORCE_NSPR_TRACE) */
+
+/* end prtrace.c */
diff --git a/pr/src/prvrsion.c b/pr/src/prvrsion.c
new file mode 100644
index 00000000..588669d7
--- /dev/null
+++ b/pr/src/prvrsion.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pr_bld.h"
+#if !defined(_BUILD_TIME)
+#define _BUILD_TIME 0
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+
+static PRVersionDescription prVersionDescription_libnsrp21 =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "License information: http://www.mozilla.org/NPL/",
+ /* specialString */ ""
+};
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void)
+{
+ return &prVersionDescription_libnsrp21;
+} /* versionEntryPointType */
+
+/* prvrsion.c */
+
diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c
index fbfa5a6d..e813b91d 100644
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -41,7 +41,7 @@
/* Linux (except glibc) and FreeBSD don't have poll */
#if !(defined(LINUX) && !(defined(__GLIBC__) && __GLIBC__ >= 2)) \
&& !defined(FREEBSD)
-#include <poll.h>
+#include <sys/poll.h>
#endif
#ifdef AIX
/* To pick up sysconf() */
@@ -75,7 +75,7 @@
#elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \
|| defined(OSF1) || defined(SOLARIS) \
|| defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \
- || defined(FREEBSD) || defined(NETBSD)
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)
#define _PRSelectFdSetArg_t fd_set *
#else
#error "Cannot determine architecture"
@@ -87,9 +87,6 @@ static pthread_condattr_t _pt_cvar_attr;
static PRLock *_pr_flock_lock; /* For PR_LockFile() etc. */
static PRLock *_pr_rename_lock; /* For PR_Rename() */
-extern struct _PT_Bookeeping pt_book; /* defined in ptthread.c */
-extern PRIntn pt_schedpriv; /* defined in ptthread.c */
-
/**************************************************************************/
/* These two functions are only used in assertions. */
@@ -125,89 +122,6 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
#endif /* DEBUG */
/*****************************************************************************/
-/*****************************************************************************/
-/************************** File descriptor caching **************************/
-/*****************************************************************************/
-/*****************************************************************************/
-
-typedef struct _PT_Fd_Cache
-{
- PRLock *ml;
- PRIntn count;
- PRIntn limit;
- PRFileDesc *fd;
-} _PT_Fd_Cache;
-static _PT_Fd_Cache pt_fd_cache;
-
-/*
-** Get a FileDescriptor from the cache if one exists. If not allocate
-** a new one from the heap.
-*/
-static PRFileDesc *pt_Getfd(void)
-{
- PRFileDesc *fd;
- do
- {
- fd = pt_fd_cache.fd; /* quick, unsafe check */
- if (NULL == fd)
- {
- fd = PR_NEWZAP(PRFileDesc);
- if (NULL == fd) goto finished;
- fd->secret = PR_NEWZAP(PRFilePrivate);
- if (NULL == fd->secret)
- {
- PR_DELETE(fd);
- goto finished;
- }
- }
- else
- {
- PRFilePrivate *secret;
- PR_Lock(pt_fd_cache.ml);
- fd = pt_fd_cache.fd; /* safer extraction */
- if (NULL != fd)
- {
- pt_fd_cache.count -= 1;
- pt_fd_cache.fd = fd->higher;
- fd->higher = NULL;
- }
- PR_Unlock(pt_fd_cache.ml);
- secret = fd->secret;
- memset(fd, 0, sizeof(PRFileDesc));
- memset(secret, 0, sizeof(PRFilePrivate));
- fd->secret = secret;
- }
- } while (NULL == fd);
-finished:
- return fd;
-} /* pt_Getfd */
-
-/*
-** Return a file descriptor to the cache unless there are too many in
-** there already. If put in cache, clear the fields first.
-*/
-static void pt_Putfd(PRFileDesc *fd)
-{
- PR_ASSERT(_PR_FILEDESC_CLOSED == fd->secret->state);
- PR_ASSERT(pt_fd_cache.count < pt_fd_cache.limit);
-
- fd->secret->state = _PR_FILEDESC_FREED;
- if (pt_fd_cache.count > pt_fd_cache.limit)
- {
- PR_DELETE(fd->secret);
- PR_DELETE(fd);
- }
- else
- {
- PR_Lock(pt_fd_cache.ml);
- pt_fd_cache.count += 1;
- fd->higher = pt_fd_cache.fd;
- pt_fd_cache.fd = fd;
- PR_Unlock(pt_fd_cache.ml);
- }
-} /* pt_Putfd */
-
-/*****************************************************************************/
/************************* I/O Continuation machinery ************************/
/*****************************************************************************/
@@ -302,14 +216,15 @@ static struct pt_TimedQueue
PTDebug pt_debug; /* this is shared between several modules */
-PR_IMPLEMENT(PTDebug) PT_GetStats() { return pt_debug; }
+PR_IMPLEMENT(void) PT_GetStats(PTDebug* here) { *here = pt_debug; }
PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
{
+ PTDebug stats;
char buffer[100];
PRExplodedTime tod;
PRInt64 elapsed, aMil;
- PTDebug stats = PT_GetStats(); /* a copy */
+ PT_GetStats(&stats); /* a copy */
PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);
(void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
@@ -574,6 +489,7 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
PRIntn pollingListNeeded; /* # entries needed this time */
static struct pollfd *pollingList = 0; /* list built for polling */
static PRIntn pollingSlotsAllocated = 0;/* # entries available in list */
+ static pt_Continuation **pollingOps = 0;/* list paralleling polling list */
PR_Unlock(pt_tq.ml); /* don't need that silly lock for a bit */
@@ -599,15 +515,24 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
* We are not holding the pt_tq.ml lock now, so more items may
* get added to pt_tq during this window of time. We hope
* that 10 more spaces in the polling list should be enough.
+ *
+ * The space allocated is for both a vector that parallels the
+ * polling list, providing pointers directly into the operation's
+ * table and the polling list itself. There is a guard element
+ * between the two structures.
*/
pollingListNeeded += 10;
if (pollingListNeeded > pollingSlotsAllocated)
{
- if (NULL != pollingList) PR_DELETE(pollingList);
- pollingList = (struct pollfd*)PR_MALLOC(
- pollingListNeeded * sizeof(struct pollfd));
- PR_ASSERT(NULL != pollingList);
+ if (NULL != pollingOps) PR_Free(pollingOps);
+ pollingOps = (pt_Continuation**)PR_Malloc(
+ sizeof(pt_Continuation**) + pollingListNeeded *
+ (sizeof(struct pollfd) + sizeof(pt_Continuation*)));
+ PR_ASSERT(NULL != pollingOps);
pollingSlotsAllocated = pollingListNeeded;
+ pollingOps[pollingSlotsAllocated] = (pt_Continuation*)-1;
+ pollingList = (struct pollfd*)(&pollingOps[pollingSlotsAllocated + 1]);
+
}
#if defined(DEBUG)
@@ -662,6 +587,8 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
#endif
break;
}
+ PR_ASSERT((pt_Continuation*)-1 == pollingOps[pollingSlotsAllocated]);
+ pollingOps[pollingListUsed] = op;
pollingList[pollingListUsed].revents = 0;
pollingList[pollingListUsed].fd = op->arg1.osfd;
pollingList[pollingListUsed].events = op->event;
@@ -694,16 +621,18 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
* the end of the list. That means that more items got added
* to the list than we anticipated. So, forget this iteration,
* go around the horn again.
+ *
* One would hope this doesn't happen all that often.
*/
if (NULL != op) continue; /* make it rethink things */
+ PR_ASSERT((pt_Continuation*)-1 == pollingOps[pollingSlotsAllocated]);
+
rv = poll(pollingList, pollingListUsed, msecs);
if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
continue; /* go around the loop again */
- PR_Lock(pt_tq.ml);
if (rv > 0)
{
/*
@@ -718,42 +647,45 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
* the polling list.
*/
- op = pt_tq.head;
for (pollIndex = 0; pollIndex < pollingListUsed; ++pollIndex)
{
- PR_ASSERT(NULL != op);
- if (0 != pollingList[pollIndex].revents)
+ PRIntn fd = pollingList[pollIndex].fd;
+ PRInt16 events = pollingList[pollIndex].events;
+ PRInt16 revents = pollingList[pollIndex].revents;
+
+ op = pollingOps[pollIndex]; /* this is the operation */
+
+ /* (ref: Bug #153459)
+ ** In case of POLLERR we let the operation retry in hope
+ ** of getting a more definitive OS error.
+ */
+ if ((revents & POLLNVAL) /* busted in all cases */
+ || ((events & POLLOUT) && (revents & POLLHUP))) /* write op & hup */
{
- /*
- * This one wants attention. Redo the operation.
- * We know that there can only be more elements
- * in the op list than we knew about when we created
- * the poll list. Therefore, we might have to skip
- * a few ops to find the right one to operate on.
- */
- while ((pollingList[pollIndex].fd != op->arg1.osfd)
- || (pollingList[pollIndex].events != op->event))
- {
- PR_ASSERT(NULL != op->next); /* it has to be in there */
- op = op->next; /* keep advancing down the list */
- }
-
- /*
- * Skip over all those not in progress. They'll be
- * pruned next time we build a polling list. Call
- * the continuation function. If it reports completion,
- * finish off the operation.
- */
- if ((pt_continuation_pending == op->status)
- && (op->function(op, pollingList[pollIndex].revents)))
- {
- next_op = pt_FinishTimedInternal(op);
- if (op == my_op) goto recycle;
- else op = next_op;
- }
- continue;
+ PR_Lock(pt_tq.ml);
+ op->result.code = -1;
+ if (POLLNVAL & revents) op->syserrno = EBADF;
+ else if (POLLHUP & revents) op->syserrno = EPIPE;
+ (void)pt_FinishTimedInternal(op);
+ if (op == my_op) goto recycle;
+ PR_Unlock(pt_tq.ml);
+ }
+ else if ((0 != revents)
+ && (pt_continuation_pending == op->status)
+ && (op->function(op, revents)))
+ {
+ /*
+ * Only good?(?) revents left. Operations not pending
+ * will be pruned next time we build a list. This operation
+ * will be pruned if the continueation indicates it is
+ * finished.
+ */
+
+ PR_Lock(pt_tq.ml);
+ (void)pt_FinishTimedInternal(op);
+ if (op == my_op) goto recycle;
+ PR_Unlock(pt_tq.ml);
}
- op = op->next; /* progress to next operation */
}
}
@@ -763,6 +695,7 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
* wire are lucky, but none the less, valid.
*/
now = PR_IntervalNow();
+ PR_Lock(pt_tq.ml);
while ((NULL != pt_tq.head)
&& (PR_INTERVAL_NO_TIMEOUT != pt_tq.head->timeout))
{
@@ -783,9 +716,11 @@ static void pt_ContinuationThreadInternal(pt_Continuation *my_op)
*/
if (op == my_op) goto recycle; /* exit w/o unlocking */
}
- PR_Unlock(pt_tq.ml); /* unlock and go back around again */
+ PR_Unlock(pt_tq.ml);
}
+ PR_NOT_REACHED("This is a while(true) loop /w no breaks");
+
recycle:
/*
** Recycling the continuation thread.
@@ -805,6 +740,7 @@ recycle:
** the lock held as well. Seems odd, doesn't it?
*/
+ /* $$$ should this be called with the lock held? $$$ */
PR_SetThreadPriority(pt_tq.thread, priority); /* reset back to caller's */
PR_ASSERT((NULL == pt_tq.head) == (0 == pt_tq.op_count));
@@ -827,7 +763,6 @@ recycle:
static PRIntn pt_Continue(pt_Continuation *op)
{
- PRIntn rc;
PRStatus rv;
PRThread *self = PR_GetCurrentThread();
/* lazy allocation of the thread's cv */
@@ -944,8 +879,13 @@ static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)
* not (and probably will not) satisfy the request. The only
* error we continue is EWOULDBLOCK|EAGAIN.
*/
+#if defined(SOLARIS)
+ op->result.code = read(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+#else
op->result.code = recv(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
+#endif
op->syserrno = errno;
return ((-1 == op->result.code) &&
(EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
@@ -954,6 +894,7 @@ static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)
static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)
{
+ PRIntn bytes;
/*
* We want to write the entire amount out, no matter how many
* tries it takes. Keep advancing the buffer and the decrementing
@@ -961,8 +902,12 @@ static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)
* (which should be the original amount) when finished (or an
* error).
*/
- PRIntn bytes = send(
+#if defined(SOLARIS)
+ bytes = write(op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+#else
+ bytes = send(
op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
+#endif
op->syserrno = errno;
if (bytes > 0) /* this is progress */
{
@@ -980,6 +925,7 @@ static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)
static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents)
{
+ PRIntn bytes;
/*
* We want to write the entire amount out, no matter how many
* tries it takes. Keep advancing the buffer and the decrementing
@@ -987,8 +933,7 @@ static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents)
* (which should be the original amount) when finished (or an
* error).
*/
- PRIntn bytes = write(
- op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+ bytes = write(op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
op->syserrno = errno;
if (bytes > 0) /* this is progress */
{
@@ -1006,6 +951,8 @@ static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents)
static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents)
{
+ PRIntn bytes;
+ struct iovec *iov = (struct iovec*)op->arg2.buffer;
/*
* Same rules as write, but continuing seems to be a bit more
* complicated. As the number of bytes sent grows, we have to
@@ -1013,8 +960,7 @@ static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents)
* modify an individual vector parms or we might have to eliminate
* a pair altogether.
*/
- struct iovec *iov = (struct iovec*)op->arg2.buffer;
- PRIntn bytes = writev(op->arg1.osfd, iov, op->arg3.amount);
+ bytes = writev(op->arg1.osfd, iov, op->arg3.amount);
op->syserrno = errno;
if (bytes > 0) /* this is progress */
{
@@ -1116,11 +1062,6 @@ static PRBool pt_hpux_transmitfile_cont(pt_Continuation *op, PRInt16 revents)
void _PR_InitIO()
{
PRIntn rv;
- _pr_stdin = pt_SetMethods(0, PR_DESC_FILE);
- _pr_stdout = pt_SetMethods(1, PR_DESC_FILE);
- _pr_stderr = pt_SetMethods(2, PR_DESC_FILE);
-
- PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);
pt_tq.ml = PR_NewLock();
PR_ASSERT(NULL != pt_tq.ml);
@@ -1138,11 +1079,14 @@ void _PR_InitIO()
_pr_flock_lock = PR_NewLock();
PR_ASSERT(NULL != _pr_flock_lock);
_pr_rename_lock = PR_NewLock();
- PR_ASSERT(NULL != _pr_rename_lock);
+ PR_ASSERT(NULL != _pr_rename_lock);
+
+ _PR_InitFdCache(); /* do that */
- pt_fd_cache.ml = PR_NewLock();
- PR_ASSERT(NULL != pt_fd_cache.ml);
- pt_fd_cache.limit = FD_SETSIZE;
+ _pr_stdin = pt_SetMethods(0, PR_DESC_FILE);
+ _pr_stdout = pt_SetMethods(1, PR_DESC_FILE);
+ _pr_stderr = pt_SetMethods(2, PR_DESC_FILE);
+ PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);
} /* _PR_InitIO */
PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
@@ -1194,9 +1138,9 @@ static void pt_MapError(void (*mapper)(PRIntn), PRIntn syserrno)
static PRStatus pt_Close(PRFileDesc *fd)
{
- PRIntn syserrno, rv = 0;
- if ((NULL == fd) || (NULL == fd->secret) ||
- (_PR_FILEDESC_OPEN != fd->secret->state))
+ if ((NULL == fd) || (NULL == fd->secret)
+ || ((_PR_FILEDESC_OPEN != fd->secret->state)
+ && (_PR_FILEDESC_CLOSED != fd->secret->state)))
{
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
return PR_FAILURE;
@@ -1205,17 +1149,14 @@ static PRStatus pt_Close(PRFileDesc *fd)
if (_PR_FILEDESC_OPEN == fd->secret->state)
{
+ if (-1 == close(fd->secret->md.osfd))
+ {
+ pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno);
+ return PR_FAILURE;
+ }
fd->secret->state = _PR_FILEDESC_CLOSED;
- rv = close(fd->secret->md.osfd);
- syserrno = errno;
- }
-
- pt_Putfd(fd);
- if (-1 == rv)
- {
- pt_MapError(_PR_MD_MAP_CLOSE_ERROR, syserrno);
- return PR_FAILURE;
}
+ _PR_Putfd(fd);
return PR_SUCCESS;
} /* pt_Close */
@@ -1223,7 +1164,7 @@ static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
{
PRInt32 syserrno, bytes = -1;
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
bytes = read(fd->secret->md.osfd, buf, amount);
syserrno = errno;
@@ -1251,7 +1192,7 @@ static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
PRInt32 syserrno, bytes = -1;
PRBool fNeedContinue = PR_FALSE;
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
bytes = write(fd->secret->md.osfd, buf, amount);
syserrno = errno;
@@ -1381,38 +1322,53 @@ static PRInt32 pt_Writev(
static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
{
- PRIntn how;
- off_t pos = -1;
-
- if (pt_TestAbort()) return pos;
-
- switch (whence)
- {
- case PR_SEEK_SET: how = SEEK_SET; break;
- case PR_SEEK_CUR: how = SEEK_CUR; break;
- case PR_SEEK_END: how = SEEK_END; break;
- default:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return pos;
- }
- pos = lseek(fd->secret->md.osfd, offset, how);
- if (pos == -1)
- pt_MapError(_PR_MD_MAP_LSEEK_ERROR, errno);
- return pos;
+ return _PR_MD_LSEEK(fd, offset, whence);
} /* pt_Seek */
static PRInt64 pt_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
{
- PRInt64 on;
- PRInt32 off, position = -1;
- LL_L2I(off, offset); /* possible loss of bits */
- LL_I2L(on, off); /* get back original or notice we didn't */
- if (LL_EQ(on, offset)) position = pt_Seek(fd, off, whence);
- LL_I2L(on, position); /* might not have worked */
- return on;
+ return _PR_MD_LSEEK64(fd, offset, whence);
} /* pt_Seek64 */
-static PRInt32 pt_Available(PRFileDesc *fd)
+static PRInt32 pt_Available_f(PRFileDesc *fd)
+{
+ PRInt32 result, cur, end;
+
+ cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
+
+ if (cur >= 0)
+ end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
+
+ if ((cur < 0) || (end < 0)) {
+ return -1;
+ }
+
+ result = end - cur;
+ _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
+
+ return result;
+} /* pt_Available_f */
+
+static PRInt64 pt_Available64_f(PRFileDesc *fd)
+{
+ PRInt64 result, cur, end;
+ PRInt64 minus_one;
+
+ LL_I2L(minus_one, -1);
+ cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
+
+ if (LL_GE_ZERO(cur))
+ end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
+
+ if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
+
+ LL_SUB(result, end, cur);
+ (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
+
+ return result;
+} /* pt_Available64_f */
+
+static PRInt32 pt_Available_s(PRFileDesc *fd)
{
PRInt32 rv, bytes = -1;
if (pt_TestAbort()) return bytes;
@@ -1422,71 +1378,32 @@ static PRInt32 pt_Available(PRFileDesc *fd)
if (rv == -1)
pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno);
return bytes;
-} /* pt_Available */
+} /* pt_Available_s */
-static PRInt64 pt_Available64(PRFileDesc *fd)
+static PRInt64 pt_Available64_s(PRFileDesc *fd)
{
PRInt64 rv;
- PRInt32 avail = pt_Available(fd);
- LL_I2L(rv, avail);
+ LL_I2L(rv, pt_Available_s(fd));
return rv;
-} /* pt_Available64 */
-
-static PRStatus pt_Synch(PRFileDesc *fd)
-{
- return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;
-} /* pt_Synch */
+} /* pt_Available64_s */
static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info)
{
- PRInt32 rv;
- struct stat sb;
- PRInt64 s, s2us;
-
- if ((rv = fstat(fd->secret->md.osfd, &sb)) == 0 )
- {
- if (info)
- {
- if (S_IFREG & sb.st_mode)
- info->type = PR_FILE_FILE ;
- else if (S_IFDIR & sb.st_mode)
- info->type = PR_FILE_DIRECTORY;
- else
- info->type = PR_FILE_OTHER;
- info->size = sb.st_size;
-#if defined(IRIX) && defined(HAVE_LONG_LONG)
- info->modifyTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_mtim.tv_sec);
- info->creationTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_ctim.tv_sec);
- info->modifyTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_mtime);
- info->creationTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_ctime);
-#else
- LL_I2L(s, sb.st_mtime);
- LL_I2L(s2us, PR_USEC_PER_SEC);
- LL_MUL(s, s, s2us);
- info->modifyTime = s;
- LL_I2L(s, sb.st_ctime);
- LL_MUL(s, s, s2us);
- info->creationTime = s;
-#endif
- }
- }
- return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, info);
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
} /* pt_FileInfo */
static PRStatus pt_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
{
- PRFileInfo info32;
- PRStatus rv = pt_FileInfo(fd, &info32);
- if (PR_SUCCESS == rv)
- {
- info->type = info32.type;
- info->creationTime = info32.creationTime;
- info->modifyTime = info32.modifyTime;
- LL_I2L(info->size, info32.size);
- }
- return rv;
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO64(fd, info);
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
} /* pt_FileInfo64 */
+static PRStatus pt_Synch(PRFileDesc *fd)
+{
+ return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_Synch */
+
static PRStatus pt_Fsync(PRFileDesc *fd)
{
PRIntn rv = -1;
@@ -1598,11 +1515,16 @@ static PRFileDesc* pt_Accept(
if (osfd < 0) goto failed;
}
}
-#ifdef AIX
+#ifdef _PR_HAVE_SOCKADDR_LEN
/* mask off the first byte of struct sockaddr (the length field) */
if (addr)
- addr->inet.family &= 0x00ff;
+ {
+ *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+ addr->raw.family = ntohs(addr->raw.family);
#endif
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP);
if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */
else
@@ -1696,9 +1618,15 @@ static PRInt32 pt_Recv(
{
PRInt32 syserrno, bytes = -1;
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
+ /* recv() is a much slower call on pre-2.6 Solaris than read(). */
+#if defined(SOLARIS)
+ PR_ASSERT(0 == flags);
+ bytes = read(fd->secret->md.osfd, buf, amount);
+#else
bytes = recv(fd->secret->md.osfd, buf, amount, flags);
+#endif
syserrno = errno;
if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
@@ -1744,9 +1672,19 @@ static PRInt32 pt_Send(
#define PT_SENDBUF_CAST
#endif
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
+ /*
+ * On pre-2.6 Solaris, send() is much slower than write().
+ * On 2.6 and beyond, with in-kernel sockets, send() and
+ * write() are fairly equivalent in performance.
+ */
+#if defined(SOLARIS)
+ PR_ASSERT(0 == flags);
+ bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount);
+#else
bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);
+#endif
syserrno = errno;
if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )
@@ -1801,7 +1739,7 @@ static PRInt32 pt_SendTo(
PRInt32 syserrno, bytes = -1;
PRBool fNeedContinue = PR_FALSE;
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
bytes = sendto(
@@ -1841,7 +1779,7 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
PRInt32 syserrno, bytes = -1;
pt_SockLen addr_len = sizeof(PRNetAddr);
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return bytes;
bytes = recvfrom(
fd->secret->md.osfd, buf, amount, flags,
@@ -1869,10 +1807,19 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
bytes = pt_Continue(&op);
syserrno = op.syserrno;
}
-#ifdef AIX
- /* mask off the first byte of struct sockaddr (the length field) */
- if (addr) addr->inet.family &= 0x00ff;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (bytes >= 0)
+ {
+ /* mask off the first byte of struct sockaddr (the length field) */
+ if (addr)
+ {
+ *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+ addr->raw.family = ntohs(addr->raw.family);
#endif
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
if (bytes < 0)
pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno);
return bytes;
@@ -1974,6 +1921,12 @@ static PRInt32 pt_TransmitFile(
PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
{
if (pt_TestAbort()) return -1;
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
#ifdef HPUX11
return pt_HPUXTransmitFile(sd, fd, headers, hlen, flags, timeout);
@@ -1993,31 +1946,30 @@ static PRInt32 pt_AcceptRead(
PRInt32 rv = -1;
PRNetAddr remote;
PRFileDesc *accepted = NULL;
- PRIntervalTime start, elapsed;
if (pt_TestAbort()) return rv;
-
- if (PR_INTERVAL_NO_TIMEOUT != timeout) start = PR_IntervalNow();
- if ((accepted = PR_Accept(sd, &remote, timeout)) == NULL) return rv;
-
- if (PR_INTERVAL_NO_TIMEOUT != timeout)
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking)
{
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- goto failed;
- }
- else timeout = timeout - elapsed;
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return rv;
}
+ /*
+ ** The timeout does not apply to the accept portion of the
+ ** operation - it waits indefinitely.
+ */
+ accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == accepted) return rv;
+
rv = PR_Recv(accepted, buf, amount, 0, timeout);
if (rv >= 0)
{
/* copy the new info out where caller can see it */
- *nd = accepted;
- *raddr = (PRNetAddr *)((char*)buf + amount);
+ PRPtrdiff aligned = (PRPtrdiff)buf + amount + sizeof(void*) - 1;
+ *raddr = (PRNetAddr*)(aligned & ~(sizeof(void*) - 1));
memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
+ *nd = accepted;
return rv;
}
@@ -2035,14 +1987,20 @@ static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
rv = getsockname(
fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
-#ifdef AIX
- /* mask off the first byte of struct sockaddr (the length field) */
- if (addr) addr->inet.family &= 0x00ff;
-#endif
if (rv == -1) {
pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno);
return PR_FAILURE;
} else {
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ /* mask off the first byte of struct sockaddr (the length field) */
+ if (addr)
+ {
+ *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+ addr->raw.family = ntohs(addr->raw.family);
+#endif
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
return PR_SUCCESS;
@@ -2059,14 +2017,20 @@ static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
rv = getpeername(
fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
-#ifdef AIX
- /* mask off the first byte of struct sockaddr (the length field) */
- if (addr) addr->inet.family &= 0x00ff;
-#endif
if (rv == -1) {
pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno);
return PR_FAILURE;
} else {
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ /* mask off the first byte of struct sockaddr (the length field) */
+ if (addr)
+ {
+ *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+ addr->raw.family = ntohs(addr->raw.family);
+#endif
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
return PR_SUCCESS;
@@ -2409,8 +2373,8 @@ static PRIOMethods _pr_file_methods = {
pt_Close,
pt_Read,
pt_Write,
- pt_Available,
- pt_Available64,
+ pt_Available_f,
+ pt_Available64_f,
pt_Fsync,
pt_Seek,
pt_Seek64,
@@ -2440,8 +2404,8 @@ static PRIOMethods _pr_tcp_methods = {
pt_Close,
pt_Read,
pt_Write,
- pt_Available,
- pt_Available64,
+ pt_Available_s,
+ pt_Available64_s,
pt_Synch,
(PRSeekFN)_PR_InvalidInt,
(PRSeek64FN)_PR_InvalidInt64,
@@ -2473,8 +2437,8 @@ static PRIOMethods _pr_udp_methods = {
pt_Close,
pt_Read,
pt_Write,
- pt_Available,
- pt_Available64,
+ pt_Available_s,
+ pt_Available64_s,
pt_Synch,
(PRSeekFN)_PR_InvalidInt,
(PRSeek64FN)_PR_InvalidInt64,
@@ -2506,7 +2470,8 @@ static PRIOMethods _pr_udp_methods = {
#endif
#if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \
- || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD)
+ || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD) \
+ || defined(OPENBSD)
#define _PR_FCNTL_FLAGS O_NONBLOCK
#else
#error "Can't determine architecture"
@@ -2515,7 +2480,7 @@ static PRIOMethods _pr_udp_methods = {
static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type)
{
PRInt32 flags, one = 1;
- PRFileDesc *fd = pt_Getfd();
+ PRFileDesc *fd = _PR_Getfd();
if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
else
@@ -2566,7 +2531,7 @@ PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
PRInt32 osfd, const PRIOMethods *methods)
{
- PRFileDesc *fd = pt_Getfd();
+ PRFileDesc *fd = _PR_Getfd();
/*
* Assert that the file descriptor is small enough to fit in the
@@ -2661,7 +2626,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
PR_Lock(_pr_rename_lock);
}
- osfd = open(name, osflags, mode);
+ osfd = _md_iovector._open64(name, osflags, mode);
syserrno = errno;
if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
@@ -2720,39 +2685,18 @@ PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
{
- PRInt32 rv;
- struct stat sb;
- PRInt64 s, s2us;
+ PRInt32 rv = _PR_MD_GETFILEINFO(fn, info);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+} /* PR_GetFileInfo */
- if (pt_TestAbort()) return PR_FAILURE;
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
+{
+ PRInt32 rv;
- if ((rv = stat(fn, &sb)) == 0 )
- {
- if (info)
- {
- if (S_IFREG & sb.st_mode)
- info->type = PR_FILE_FILE ;
- else if (S_IFDIR & sb.st_mode)
- info->type = PR_FILE_DIRECTORY;
- else
- info->type = PR_FILE_OTHER;
- info->size = sb.st_size;
-#if defined(IRIX) && defined(HAVE_LONG_LONG)
- info->modifyTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_mtim.tv_sec);
- info->creationTime = (PR_USEC_PER_SEC * (PRInt64)sb.st_ctim.tv_sec);
-#else
- LL_I2L(s, sb.st_mtime);
- LL_I2L(s2us, PR_USEC_PER_SEC);
- LL_MUL(s, s, s2us);
- info->modifyTime = s;
- LL_I2L(s, sb.st_ctime);
- LL_MUL(s, s, s2us);
- info->creationTime = s;
-#endif
- }
- }
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ rv = _PR_MD_GETFILEINFO64(fn, info);
return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
-} /* PR_GetFileInfo */
+} /* PR_GetFileInfo64 */
PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
{
@@ -2791,8 +2735,13 @@ PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir)
if (NULL != dir->md.d)
{
- closedir(dir->md.d);
+ if (closedir(dir->md.d) == -1)
+ {
+ _PR_MD_MAP_CLOSEDIR_ERROR(errno);
+ return PR_FAILURE;
+ }
dir->md.d = NULL;
+ PR_DELETE(dir);
}
return PR_SUCCESS;
} /* PR_CloseDir */
@@ -2863,6 +2812,8 @@ PR_IMPLEMENT(PRInt32) PR_Poll(
*/
PRIntervalTime start, elapsed, remaining;
+ if (pt_TestAbort()) return -1;
+
if (0 == npds) PR_Sleep(timeout);
else
{
@@ -2876,39 +2827,100 @@ PR_IMPLEMENT(PRInt32) PR_Poll(
}
for (index = 0; index < npds; ++index)
{
- PRFileDesc *bottom = pds[index].fd;
- PRInt16 polling_flags = pds[index].in_flags;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
- /* 'bottom' is really 'top' until we make it the bottom */
- if (NULL != bottom)
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
{
- polling_flags = (bottom->methods->poll)(
- bottom, polling_flags, &pds[index].out_flags);
-
- if (0 != (polling_flags & pds[index].out_flags))
- ready += 1; /* this one is ready right now */
+ if (pds[index].in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_WRITE,
+ &out_flags_read);
+ }
+ if (pds[index].in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_READ,
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one is ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will return without calling the system
+ * poll function. So zero the out_flags
+ * fields of all the poll descriptors before
+ * this one.
+ */
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1;
+ pds[index].out_flags = out_flags_read | out_flags_write;
+ }
else
{
/* now locate the NSPR layer at the bottom of the stack */
- bottom = PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(
+ pds[index].fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottom); /* what to do about that? */
+ pds[index].out_flags = 0; /* pre-condition */
if ((NULL != bottom)
&& (_PR_FILEDESC_OPEN == bottom->secret->state))
{
- syspoll[index].fd = bottom->secret->md.osfd;
- pds[index].out_flags = 0; /* init the result */
- syspoll[index].events = 0;
- if (polling_flags & PR_POLL_READ)
- syspoll[index].events |= POLLIN;
- if (polling_flags & PR_POLL_WRITE)
- syspoll[index].events |= POLLOUT;
- if (polling_flags & PR_POLL_EXCEPT)
- syspoll[index].events |= POLLPRI;
+ if (0 == ready)
+ {
+ syspoll[index].fd = bottom->secret->md.osfd;
+ syspoll[index].events = 0;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (pds[index].in_flags & PR_POLL_EXCEPT)
+ syspoll[index].events |= POLLPRI;
+ }
}
else
{
+ if (0 == ready)
+ {
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
ready += 1; /* this will cause an abrupt return */
- pds[index].out_flags = POLLNVAL; /* bogii */
+ pds[index].out_flags = PR_POLL_NVAL; /* bogii */
}
}
}
@@ -2941,6 +2953,7 @@ retry:
goto retry;
else if (timeout == PR_INTERVAL_NO_WAIT)
ready = 0; /* don't retry, just time out */
+ else
{
elapsed = (PRIntervalTime) (PR_IntervalNow()
- start);
@@ -2963,21 +2976,48 @@ retry:
{
for (index = 0; index < npds; ++index)
{
- if (pds[index].fd == NULL) continue;
- PR_ASSERT(0 == pds[index].out_flags);
- if (0 != syspoll[index].revents)
+ PRInt16 out_flags = 0;
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
{
- if (syspoll[index].revents & POLLIN)
- pds[index].out_flags |= PR_POLL_READ;
- if (syspoll[index].revents & POLLOUT)
- pds[index].out_flags |= PR_POLL_WRITE;
- if (syspoll[index].revents & POLLPRI)
- pds[index].out_flags |= PR_POLL_EXCEPT;
- if (syspoll[index].revents & POLLERR)
- pds[index].out_flags |= PR_POLL_ERR;
- if (syspoll[index].revents & POLLNVAL)
- pds[index].out_flags |= PR_POLL_NVAL;
+ if (0 != syspoll[index].revents)
+ {
+ if (syspoll[index].revents & POLLIN)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_READ)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_READ)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLOUT)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLPRI)
+ out_flags |= PR_POLL_EXCEPT;
+ if (syspoll[index].revents & POLLERR)
+ out_flags |= PR_POLL_ERR;
+ if (syspoll[index].revents & POLLNVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (syspoll[index].revents & POLLHUP)
+ out_flags |= PR_POLL_HUP;
+ }
}
+ pds[index].out_flags = out_flags;
}
}
}
@@ -3281,13 +3321,13 @@ PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
static PRBool unwarned = PR_TRUE;
if (unwarned) unwarned = _PR_Obsolete("PR_Stat", "PR_GetFileInfo");
- if (pt_TestAbort()) return PR_FAILURE;
+ if (pt_TestAbort()) return -1;
if (-1 == stat(name, buf)) {
pt_MapError(_PR_MD_MAP_STAT_ERROR, errno);
- return PR_FAILURE;
+ return -1;
} else {
- return PR_SUCCESS;
+ return 0;
}
}
#endif /* ! NO_NSPR_10_SUPPORT */
diff --git a/pr/src/pthreads/ptmisc.c b/pr/src/pthreads/ptmisc.c
index 669b7822..188a471a 100644
--- a/pr/src/pthreads/ptmisc.c
+++ b/pr/src/pthreads/ptmisc.c
@@ -32,7 +32,6 @@
void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")}
void _PR_InitStacks(void) {PT_LOG("_PR_InitStacks")}
-void _PR_InitTPD(void) {PT_LOG("_PR_InitTPD")}
PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
{PT_LOG("PR_SetConcurrency")}
diff --git a/pr/src/pthreads/ptsynch.c b/pr/src/pthreads/ptsynch.c
index 128486eb..b49cdc3f 100644
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -31,6 +31,7 @@
#include <pthread.h>
#include <sys/time.h>
+static pthread_mutexattr_t _pt_mattr;
static pthread_condattr_t _pt_cvar_attr;
#if defined(DEBUG)
@@ -50,7 +51,16 @@ static pthread_t pt_zero_tid; /* a null pthread_t (pthread_t is a struct
void _PR_InitLocks(void)
{
- int rv = PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
+ int rv;
+ rv = PTHREAD_MUTEXATTR_INIT(&_pt_mattr);
+ PR_ASSERT(0 == rv);
+
+#if defined(AIX)
+ rv = pthread_mutexattr_setkind_np(&_pt_mattr, MUTEX_FAST_NP);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
PR_ASSERT(0 == rv);
_PR_MD_INIT_LOCKS();
}
@@ -131,12 +141,7 @@ PR_IMPLEMENT(PRLock*) PR_NewLock(void)
lock = PR_NEWZAP(PRLock);
if (lock != NULL)
{
- pthread_mutexattr_t mattr;
- rv = PTHREAD_MUTEXATTR_INIT(&mattr);
- PR_ASSERT(0 == rv);
- rv = PTHREAD_MUTEX_INIT(lock->mutex, mattr);
- PR_ASSERT(0 == rv);
- rv = PTHREAD_MUTEXATTR_DESTROY(&mattr);
+ rv = PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr);
PR_ASSERT(0 == rv);
}
#if defined(DEBUG)
@@ -399,33 +404,37 @@ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
{
- PRMonitor *ml;
+ PRMonitor *mon;
+ PRCondVar *cvar;
if (!_pr_initialized) _PR_ImplicitInitialization();
- ml = PR_NEWZAP(PRMonitor);
- if (ml != NULL)
+ cvar = PR_NEWZAP(PRCondVar);
+ if (NULL == cvar)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ mon = PR_NEWZAP(PRMonitor);
+ if (mon != NULL)
{
int rv;
- pthread_mutexattr_t mattr;
- rv = PTHREAD_MUTEXATTR_INIT(&mattr);
- PR_ASSERT(0 == rv);
- rv += PTHREAD_MUTEX_INIT(ml->lock.mutex, mattr);
- PR_ASSERT(0 == rv);
- rv += PTHREAD_MUTEXATTR_DESTROY(&mattr);
+ rv = PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr);
PR_ASSERT(0 == rv);
- rv += PTHREAD_COND_INIT(ml->cvar.cv, _pt_cvar_attr);
+ mon->cvar = cvar;
+ rv = PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr);
PR_ASSERT(0 == rv);
- ml->entryCount = 0;
- ml->cvar.lock = &ml->lock;
+ mon->entryCount = 0;
+ mon->cvar->lock = &mon->lock;
if (0 != rv)
{
- PR_DELETE(ml);
- ml = NULL;
+ PR_DELETE(mon);
+ PR_DELETE(cvar);
+ mon = NULL;
}
}
- return ml;
+ return mon;
} /* PR_NewMonitor */
PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
@@ -439,7 +448,7 @@ PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
{
int rv;
PR_ASSERT(mon != NULL);
- rv = pthread_cond_destroy(&mon->cvar.cv); PR_ASSERT(0 == rv);
+ PR_DestroyCondVar(mon->cvar);
rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
#if defined(DEBUG)
memset(mon, 0xaf, sizeof(PRMonitor));
@@ -539,7 +548,7 @@ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
PTHREAD_ZERO_THR_HANDLE(mon->owner);
- rv = PR_WaitCondVar(&mon->cvar, timeout);
+ rv = PR_WaitCondVar(mon->cvar, timeout);
/* reinstate the intresting information */
mon->entryCount = saved_entries;
@@ -558,7 +567,7 @@ PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
/* and it better be by us */
PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
- pt_PostNotifyToCvar(&mon->cvar, PR_FALSE);
+ pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
return PR_SUCCESS;
} /* PR_Notify */
@@ -573,7 +582,7 @@ PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
/* and it better be by us */
PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
- pt_PostNotifyToCvar(&mon->cvar, PR_TRUE);
+ pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
return PR_SUCCESS;
} /* PR_NotifyAll */
diff --git a/pr/src/pthreads/ptthread.c b/pr/src/pthreads/ptthread.c
index d3b7679f..bea53f56 100644
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -29,6 +29,7 @@
#include "prpdce.h"
#include <pthread.h>
+#include <unistd.h>
#include <string.h>
#include <signal.h>
@@ -38,18 +39,33 @@
* EPERM means that privilege is not available.
*/
-PRIntn pt_schedpriv;
+static PRIntn pt_schedpriv = 0;
extern PRLock *_pr_sleeplock;
-struct _PT_Bookeeping pt_book = {0};
+static struct _PT_Bookeeping
+{
+ PRLock *ml; /* a lock to protect ourselves */
+ PRCondVar *cv; /* used to signal global things */
+ PRInt32 system, user; /* a count of the two different types */
+ PRUintn this_many; /* number of threads allowed for exit */
+ pthread_key_t key; /* private private data key */
+ pthread_key_t highwater; /* ordinal value of next key to be allocated */
+ PRThread *first, *last; /* list of threads we know about */
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ PRInt32 minPrio, maxPrio; /* range of scheduling priorities */
+#endif
+} pt_book = {0};
+static void _pt_thread_death(void *arg);
static void init_pthread_gc_support(void);
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
static PRIntn pt_PriorityMap(PRThreadPriority pri)
{
return pt_book.minPrio +
pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST;
}
+#endif
/*
** Initialize a stack for a native pthread thread
@@ -156,23 +172,73 @@ static void *_pt_root(void *arg)
}
PR_Unlock(pt_book.ml);
- /* last chance to delete this puppy if the thread is detached */
- if (detached)
+ /*
+ * Here we set the pthread's backpointer to the PRThread to NULL.
+ * Otherwise the desctructor would get called eagerly as the thread
+ * returns to the pthread runtime. The joining thread would them be
+ * the proud possessor of a dangling reference. However, this is the
+ * last chance to delete the object if the thread is detached, so
+ * just let the destuctor do the work.
+ */
+ if (PR_FALSE == detached)
{
- if (NULL != thred->io_cv)
- PR_DestroyCondVar(thred->io_cv);
- PR_DELETE(thred->stack);
-#if defined(DEBUG)
- memset(thred, 0xaf, sizeof(PRThread));
-#endif
- PR_DELETE(thred);
+ rv = pthread_setspecific(pt_book.key, NULL);
+ PR_ASSERT(0 == rv);
}
- rv = pthread_setspecific(pt_book.key, NULL);
- PR_ASSERT(0 == rv);
return NULL;
} /* _pt_root */
+static PRThread* pt_AttachThread(void)
+{
+ PRThread *thred = NULL;
+ void *privateData = NULL;
+
+ /*
+ * NSPR must have been initialized when PR_AttachThread is called.
+ * We cannot have PR_AttachThread call implicit initialization
+ * because if multiple threads call PR_AttachThread simultaneously,
+ * NSPR may be initialized more than once.
+ * We can't call PR_SetError() either.
+ */
+ if (!_pr_initialized) return NULL;
+
+ /*
+ * If the thread is already known, it will have a non-NULL value
+ * in its private data. If that's the case, simply suppress the
+ * attach and note an error.
+ */
+ PTHREAD_GETSPECIFIC(pt_book.key, privateData);
+ if (NULL != privateData)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+ thred = PR_NEWZAP(PRThread);
+ if (NULL == thred) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ int rv;
+
+ thred->priority = PR_PRIORITY_NORMAL;
+ thred->id = pthread_self();
+ rv = pthread_setspecific(pt_book.key, thred);
+ PR_ASSERT(0 == rv);
+
+ thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN;
+ PR_Lock(pt_book.ml);
+
+ /* then put it into the list */
+ thred->prev = pt_book.last;
+ pt_book.last->next = thred;
+ thred->next = NULL;
+ pt_book.last = thred;
+ PR_Unlock(pt_book.ml);
+
+ }
+ return thred; /* may be NULL */
+} /* pt_AttachThread */
+
static PRThread* _PR_CreateThread(
PRThreadType type, void (*start)(void *arg),
void *arg, PRThreadPriority priority, PRThreadScope scope,
@@ -194,11 +260,11 @@ static PRThread* _PR_CreateThread(
if (EPERM != pt_schedpriv)
{
-#if !defined(_PR_DCETHREADS) && !defined(FREEBSD) && !defined(NETBSD)
+#if !defined(_PR_DCETHREADS) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
struct sched_param schedule;
#endif
-#if !defined(FREEBSD) && !defined(NETBSD)
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
rv = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
PR_ASSERT(0 == rv);
#endif
@@ -208,7 +274,7 @@ static PRThread* _PR_CreateThread(
#if defined(_PR_DCETHREADS)
rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority));
PR_ASSERT(0 == rv);
-#elif !defined(FREEBSD) && !defined(NETBSD)
+#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
rv = pthread_attr_getschedparam(&tattr, &schedule);
PR_ASSERT(0 == rv);
schedule.sched_priority = pt_PriorityMap(priority);
@@ -228,21 +294,8 @@ static PRThread* _PR_CreateThread(
PR_ASSERT(0 == rv);
#endif /* !defined(_PR_DCETHREADS) */
- /*
- * HPUX only supports PTHREAD_SCOPE_SYSTEM.
- * IRIX only supports PTHREAD_SCOPE_PROCESS.
- * OSF1 only supports PTHREAD_SCOPE_PROCESS.
- * AIX only supports PTHREAD_SCOPE_SYSTEM.
- */
-#if defined(SOLARIS)
- rv = pthread_attr_setscope(&tattr,
- ((PR_GLOBAL_THREAD == scope) ?
- PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS));
- PR_ASSERT(0 == rv);
-#endif
-
#if defined(IRIX)
- if ((16 * 1024) > stackSize) stackSize = (16 * 1024); /* IRIX minimum */
+ if ((32 * 1024) > stackSize) stackSize = (32 * 1024); /* IRIX minimum */
else
#endif
if (0 == stackSize) stackSize = (64 * 1024); /* default == 64K */
@@ -255,7 +308,12 @@ static PRThread* _PR_CreateThread(
#endif
thred = PR_NEWZAP(PRThread);
- if (thred != NULL)
+ if (NULL == thred)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, errno);
+ goto done;
+ }
+ else
{
pthread_t id;
@@ -273,7 +331,9 @@ static PRThread* _PR_CreateThread(
thred->stack = PR_NEWZAP(PRThreadStack);
if (thred->stack == NULL) {
- PR_DELETE(thred); /* all that work ... poof! */
+ PRIntn oserr = errno;
+ PR_Free(thred); /* all that work ... poof! */
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, oserr);
thred = NULL; /* and for what? */
goto done;
}
@@ -281,24 +341,45 @@ static PRThread* _PR_CreateThread(
thred->stack->thr = thred;
#ifdef PT_NO_SIGTIMEDWAIT
- pthread_mutex_init(&thred->suspendResumeMutex,NULL);
- pthread_cond_init(&thred->suspendResumeCV,NULL);
+ pthread_mutex_init(&thred->suspendResumeMutex,NULL);
+ pthread_cond_init(&thred->suspendResumeCV,NULL);
#endif
- /* make the thread counted to the rest of the runtime */
- PR_Lock(pt_book.ml);
- if (thred->state & PT_THREAD_SYSTEM)
- pt_book.system += 1;
- else pt_book.user += 1;
- PR_Unlock(pt_book.ml);
+ /* make the thread counted to the rest of the runtime */
+ PR_Lock(pt_book.ml);
+ if (PR_SYSTEM_THREAD == type)
+ pt_book.system += 1;
+ else pt_book.user += 1;
+ PR_Unlock(pt_book.ml);
/*
* We pass a pointer to a local copy (instead of thred->id)
* to pthread_create() because who knows what wacky things
* pthread_create() may be doing to its argument.
*/
- if (PTHREAD_CREATE(&id, tattr, _pt_root, thred) != 0)
+ rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
+
+#if !defined(_PR_DCETHREADS)
+ if (EPERM == rv)
+ {
+ /* Remember that we don't have thread scheduling privilege. */
+ pt_schedpriv = EPERM;
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("_PR_CreateThread: no thread scheduling privilege"));
+ /* Try creating the thread again without setting priority. */
+ rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
+ PR_ASSERT(0 == rv);
+ rv = PTHREAD_CREATE(&id, tattr, _pt_root, thred);
+ }
+#endif
+
+ if (0 != rv)
{
+#if defined(_PR_DCETHREADS)
+ PRIntn oserr = errno;
+#else
+ PRIntn oserr = rv;
+#endif
PR_Lock(pt_book.ml);
if (thred->state & PT_THREAD_SYSTEM)
pt_book.system -= 1;
@@ -306,8 +387,9 @@ static PRThread* _PR_CreateThread(
PR_NotifyAllCondVar(pt_book.cv);
PR_Unlock(pt_book.ml);
- PR_DELETE(thred->stack);
- PR_DELETE(thred); /* all that work ... poof! */
+ PR_Free(thred->stack);
+ PR_Free(thred); /* all that work ... poof! */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, oserr);
thred = NULL; /* and for what? */
goto done;
}
@@ -370,61 +452,10 @@ PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env)
PR_IMPLEMENT(PRThread*) PR_AttachThread(
PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
{
- PRThread *thred = NULL;
- void *privateData = NULL;
-
- /*
- * NSPR must have been initialized when PR_AttachThread is called.
- * We cannot have PR_AttachThread call implicit initialization
- * because if multiple threads call PR_AttachThread simultaneously,
- * NSPR may be initialized more than once.
- */
- if (!_pr_initialized) {
- /* Since NSPR is not initialized, we cannot call PR_SetError. */
- return NULL;
- }
-
- PTHREAD_GETSPECIFIC(pt_book.key, privateData);
- if (NULL != privateData)
- {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return NULL;
- }
- thred = PR_NEWZAP(PRThread);
- if (NULL == thred) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- else
- {
- int rv;
-
- if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)priority)
- priority = PR_PRIORITY_FIRST;
- else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)priority)
- priority = PR_PRIORITY_LAST;
-
- thred->priority = priority;
- thred->id = pthread_self();
- rv = pthread_setspecific(pt_book.key, thred);
- PR_ASSERT(0 == rv);
-
- PR_Lock(pt_book.ml);
- if (PR_SYSTEM_THREAD == type)
- {
- pt_book.system += 1;
- thred->state |= PT_THREAD_SYSTEM;
- }
- else pt_book.user += 1;
-
- /* then put it into the list */
- thred->prev = pt_book.last;
- pt_book.last->next = thred;
- thred->next = NULL;
- pt_book.last = thred;
- PR_Unlock(pt_book.ml);
-
- }
- return thred; /* may be NULL */
+ return PR_GetCurrentThread();
} /* PR_AttachThread */
+
PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
{
int rv = -1;
@@ -432,7 +463,8 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
PR_ASSERT(thred != NULL);
if ((0xafafafaf == thred->state)
- || (PT_THREAD_DETACHED & thred->state))
+ || (PT_THREAD_DETACHED == (PT_THREAD_DETACHED & thred->state))
+ || (PT_THREAD_FOREIGN == (PT_THREAD_FOREIGN & thred->state)))
{
/*
* This might be a bad address, but if it isn't, the state should
@@ -440,65 +472,44 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
* deleted. However, the client that called join on a detached
* thread deserves all the rath I can muster....
*/
- PR_SetError(PR_ILLEGAL_ACCESS_ERROR, 0);
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
PR_LogPrint(
"PR_JoinThread: 0x%X not joinable | already smashed\n", thred);
- PR_ASSERT((0xafafafaf == thred->state)
- || (PT_THREAD_DETACHED & thred->state));
+ PR_ASSERT(!"Illegal thread join attempt");
}
else
{
pthread_t id = thred->id;
rv = pthread_join(id, &result);
PR_ASSERT(rv == 0 && result == NULL);
- if (0 != rv)
- PR_SetError(PR_UNKNOWN_ERROR, errno);
- if (NULL != thred->io_cv)
- PR_DestroyCondVar(thred->io_cv);
- PR_DELETE(thred->stack);
-#if defined(DEBUG)
- memset(thred, 0xaf, sizeof(PRThread));
-#endif
- PR_DELETE(thred);
+ if (0 == rv)
+ {
+ _pt_thread_death(thred);
+ }
+ else
+ {
+ PRErrorCode prerror;
+ switch (rv)
+ {
+ case EINVAL: /* not a joinable thread */
+ case ESRCH: /* no thread with given ID */
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EDEADLK: /* a thread joining with itself */
+ prerror = PR_DEADLOCK_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, rv);
+ }
}
return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
} /* PR_JoinThread */
-PR_IMPLEMENT(void) PR_DetachThread()
-{
- void *tmp;
- PTHREAD_GETSPECIFIC(pt_book.key, tmp);
- PR_ASSERT(NULL != tmp);
-
- if (NULL != tmp)
- {
- int rv;
- PRThread *thred = (PRThread*)tmp;
-
- PR_Lock(pt_book.ml);
- if (thred->state & PT_THREAD_SYSTEM)
- pt_book.system -= 1;
- else if (--pt_book.user == pt_book.this_many)
- PR_NotifyAllCondVar(pt_book.cv);
- thred->prev->next = thred->next;
- if (NULL == thred->next)
- pt_book.last = thred->prev;
- else
- thred->next->prev = thred->prev;
- PR_Unlock(pt_book.ml);
-
- if (NULL != thred->io_cv)
- PR_DestroyCondVar(thred->io_cv);
- rv = pthread_setspecific(pt_book.key, NULL);
- PR_ASSERT(0 == rv);
- PR_DELETE(thred->stack);
-#if defined(DEBUG)
- memset(thred, 0xaf, sizeof(PRThread));
-#endif
- PR_DELETE(thred);
- }
-} /* PR_DetachThread */
+PR_IMPLEMENT(void) PR_DetachThread() { } /* PR_DetachThread */
PR_IMPLEMENT(PRThread*) PR_GetCurrentThread()
{
@@ -507,14 +518,14 @@ PR_IMPLEMENT(PRThread*) PR_GetCurrentThread()
if (!_pr_initialized) _PR_ImplicitInitialization();
PTHREAD_GETSPECIFIC(pt_book.key, thred);
+ if (NULL == thred) thred = pt_AttachThread();
PR_ASSERT(NULL != thred);
return (PRThread*)thred;
} /* PR_GetCurrentThread */
PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred)
{
- return (thred->state & PT_THREAD_GLOBAL) ?
- PR_GLOBAL_THREAD : PR_LOCAL_THREAD;
+ return PR_GLOBAL_THREAD;
} /* PR_GetThreadScope() */
PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred)
@@ -550,7 +561,7 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri
rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));
/* pthread_setprio returns the old priority */
PR_ASSERT(-1 != rv);
-#elif !defined(FREEBSD) && !defined(NETBSD)
+#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
if (EPERM != pt_schedpriv)
{
int policy;
@@ -560,13 +571,20 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri
PR_ASSERT(0 == rv);
schedule.sched_priority = pt_PriorityMap(newPri);
rv = pthread_setschedparam(thred->id, policy, &schedule);
- PR_ASSERT(0 == rv);
+ PR_ASSERT(0 == rv || EPERM == rv);
+ if (EPERM == rv)
+ {
+ pt_schedpriv = EPERM;
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_SetThreadPriority: no thread scheduling privilege"));
+ }
}
#endif
thred->priority = newPri;
} /* PR_SetThreadPriority */
+#if 0
PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
PRUintn *newIndex, PRThreadPrivateDTOR destructor)
{
@@ -611,6 +629,7 @@ PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index)
PTHREAD_GETSPECIFIC((pthread_key_t)index, result);
return result;
} /* PR_GetThreadPrivate */
+#endif
PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred)
{
@@ -675,27 +694,54 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks)
}
else
{
- PRCondVar *cv = PR_NewCondVar(_pr_sleeplock);
+ PRCondVar *cv;
+ PRIntervalTime timein;
+
+ timein = PR_IntervalNow();
+ cv = PR_NewCondVar(_pr_sleeplock);
PR_ASSERT(cv != NULL);
PR_Lock(_pr_sleeplock);
- rv = PR_WaitCondVar(cv, ticks);
+ do
+ {
+ PRIntervalTime now = PR_IntervalNow();
+ PRIntervalTime delta = now - timein;
+ if (delta > ticks) break;
+ rv = PR_WaitCondVar(cv, ticks - delta);
+ } while (PR_SUCCESS == rv);
PR_Unlock(_pr_sleeplock);
PR_DestroyCondVar(cv);
}
return rv;
} /* PR_Sleep */
+static void _pt_thread_death(void *arg)
+{
+ PRThread *thred = (PRThread*)arg;
+ _PR_DestroyThreadPrivate(thred);
+ if (NULL != thred->errorString)
+ PR_Free(thred->errorString);
+ if (NULL != thred->io_cv)
+ PR_DestroyCondVar(thred->io_cv);
+ PR_Free(thred->stack);
+#if defined(DEBUG)
+ memset(thred, 0xaf, sizeof(PRThread));
+#endif /* defined(DEBUG) */
+ PR_Free(thred);
+} /* _pt_thread_death */
+
void _PR_InitThreads(
PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
{
int rv;
PRThread *thred;
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
/*
** These might be function evaluations
*/
pt_book.minPrio = PT_PRIO_MIN;
pt_book.maxPrio = PT_PRIO_MAX;
+#endif
PR_ASSERT(NULL == pt_book.ml);
pt_book.ml = PR_NewLock();
@@ -709,7 +755,7 @@ void _PR_InitThreads(
thred->priority = priority;
thred->id = pthread_self();
- thred->state |= (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);
+ thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);
if (PR_SYSTEM_THREAD == type)
{
thred->state |= PT_THREAD_SYSTEM;
@@ -737,13 +783,17 @@ void _PR_InitThreads(
* threads delete the objects in Join.
*
* NB: The destructor logic seems to have a bug so it isn't used.
+ * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998.
+ * More info - the problem is that pthreads calls the destructor
+ * eagerly as the thread returns from its root, rather than lazily
+ * after the thread is joined. Therefore, threads that are joining
+ * and holding PRThread references are actually holding pointers to
+ * nothing.
*/
- rv = PTHREAD_KEY_CREATE(&pt_book.key, NULL);
+ rv = PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);
PR_ASSERT(0 == rv);
rv = pthread_setspecific(pt_book.key, thred);
- PR_ASSERT(0 == rv);
-
- pt_schedpriv = PT_PRIVCHECK();
+ PR_ASSERT(0 == rv);
PR_SetThreadPriority(thred, priority);
/*
@@ -751,7 +801,7 @@ void _PR_InitThreads(
* conflict with the use of these two signals in our GC support.
* So we don't know how to support GC on Linux pthreads.
*/
-#if !defined(LINUX) && !defined(FREEBSD) && !defined(NETBSD)
+#if !defined(LINUX) && !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD)
init_pthread_gc_support();
#endif
@@ -769,6 +819,10 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
PR_Unlock(pt_book.ml);
+ _PR_LogCleanup();
+ /* Close all the fd's before calling _PR_CleanupFdCache */
+ _PR_CleanupFdCache();
+
/*
* I am not sure if it's safe to delete the cv and lock here,
* since there may still be "system" threads around. If this
@@ -780,8 +834,7 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_DestroyCondVar(pt_book.cv); pt_book.cv = NULL;
PR_DestroyLock(pt_book.ml); pt_book.ml = NULL;
}
- PR_DELETE(me->stack);
- PR_DELETE(me);
+ _pt_thread_death(me);
return PR_SUCCESS;
}
return PR_FAILURE;
@@ -792,6 +845,15 @@ PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
_exit(status);
}
+PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
+{
+#if defined(_PR_DCETHREADS)
+ return (PRUint32)&thred->id; /* this is really a sham! */
+#else
+ return (PRUint32)thred->id; /* and I don't know what they will do with it */
+#endif
+}
+
/*
* $$$
* The following two thread-to-processor affinity functions are not
@@ -1036,7 +1098,7 @@ static void suspend_signal_handler(PRIntn sig)
pthread_cond_signal(&me->suspendResumeCV);
while (me->suspend & PT_THREAD_SUSPENDED)
{
-#if !defined(FREEBSD) && !defined(NETBSD) /*XXX*/
+#if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) /*XXX*/
PRIntn rv;
sigwait(&sigwait_set, &rv);
#endif
diff --git a/pr/src/threads/Makefile b/pr/src/threads/Makefile
index 91ad0aaa..755d9928 100644
--- a/pr/src/threads/Makefile
+++ b/pr/src/threads/Makefile
@@ -35,10 +35,12 @@ endif
endif
ifdef USE_PTHREADS
-CSRCS = prcmon.c \
+CSRCS = \
+ prcmon.c \
+ prtpd.c \
$(NULL)
else
-CSRCS = \
+CSRCS = \
prcmon.c \
prdump.c \
prmon.c \
diff --git a/pr/src/threads/combined/prucpu.c b/pr/src/threads/combined/prucpu.c
index 99ad4d83..e50e9702 100644
--- a/pr/src/threads/combined/prucpu.c
+++ b/pr/src/threads/combined/prucpu.c
@@ -145,6 +145,8 @@ static _PRCPU *_PR_CreateCPU(PRThread *thread, PRBool needQueue)
PR_DELETE(cpu);
return NULL;
}
+ cpu->idle_thread->cpu = cpu;
+
cpu->idle_thread->no_sched = 0;
cpu->thread = thread;
@@ -206,7 +208,7 @@ static void PR_CALLBACK _PR_CPU_Idle(void *_cpu)
cpu->idle_thread = me;
if (_MD_LAST_THREAD())
_MD_LAST_THREAD()->no_sched = 0;
- if (!_PR_IS_NATIVE_THREAD(me)) _PR_SET_INTSOFF(0);
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_MD_SET_INTSOFF(0);
while(1) {
PRInt32 is;
PRIntervalTime timeout;
diff --git a/pr/src/threads/combined/prucv.c b/pr/src/threads/combined/prucv.c
index bf2bd551..41eb62f2 100644
--- a/pr/src/threads/combined/prucv.c
+++ b/pr/src/threads/combined/prucv.c
@@ -157,7 +157,7 @@ void _PR_NotifyLockedThread (PRThread *thread)
PRStatus _PR_WaitCondVar(
PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
{
- intn is;
+ PRIntn is;
PRStatus rv = PR_SUCCESS;
PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
@@ -336,7 +336,6 @@ void _PR_ClockInterrupt(void)
if (elapsed < thread->sleep) {
thread->sleep -= elapsed;
_PR_SLEEPQMAX(thread->cpu) -= elapsed;
- PR_ASSERT((PRInt32)(thread->sleep) >= 0);
_PR_SLEEPQ_UNLOCK(cpu);
break;
}
diff --git a/pr/src/threads/combined/prustack.c b/pr/src/threads/combined/prustack.c
index 09690806..4e0053f6 100644
--- a/pr/src/threads/combined/prustack.c
+++ b/pr/src/threads/combined/prustack.c
@@ -77,7 +77,7 @@ PRThreadStack *_PR_NewStack(PRUint32 stackSize)
_PR_MD_CLEAR_STACK(ts);
_pr_numFreeStacks--;
- PR_DestroySegment(ts->seg);
+ _PR_DestroySegment(ts->seg);
PR_DELETE(ts);
}
@@ -125,7 +125,7 @@ PRThreadStack *_PR_NewStack(PRUint32 stackSize)
** up).
*/
ts->allocSize = stackSize + 2*REDZONE;
- ts->seg = PR_NewSegment(ts->allocSize, 0);
+ ts->seg = _PR_NewSegment(ts->allocSize, 0);
if (!ts->seg) {
PR_DELETE(ts);
return NULL;
@@ -133,7 +133,7 @@ PRThreadStack *_PR_NewStack(PRUint32 stackSize)
}
done:
- ts->allocBase = ts->seg->vaddr;
+ ts->allocBase = (char*)ts->seg->vaddr;
ts->flags = _PR_STACK_MAPPED;
ts->stackSize = stackSize;
diff --git a/pr/src/threads/combined/pruthr.c b/pr/src/threads/combined/pruthr.c
index 2a3c38d6..bcc2e650 100644
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -22,22 +22,22 @@
/* _pr_activeLock protects the following global variables */
PRLock *_pr_activeLock;
-PRUintn _pr_primordialExitCount; /* In PR_Cleanup(), the primordial thread
- * waits until all other user (non-system)
- * threads have terminated before it exits.
- * So whenever we decrement _pr_userActive,
- * it is compared with
- * _pr_primordialExitCount.
- * If the primordial thread is a system
- * thread, then _pr_primordialExitCount
- * is 0. If the primordial thread is
- * itself a user thread, then
- * _pr_primordialThread is 1.
- */
+PRInt32 _pr_primordialExitCount; /* In PR_Cleanup(), the primordial thread
+ * waits until all other user (non-system)
+ * threads have terminated before it exits.
+ * So whenever we decrement _pr_userActive,
+ * it is compared with
+ * _pr_primordialExitCount.
+ * If the primordial thread is a system
+ * thread, then _pr_primordialExitCount
+ * is 0. If the primordial thread is
+ * itself a user thread, then
+ * _pr_primordialThread is 1.
+ */
PRCondVar *_pr_primordialExitCVar; /* When _pr_userActive is decremented to
- * _pr_primordialExitCount, this condition
- * variable is notified.
- */
+ * _pr_primordialExitCount, this condition
+ * variable is notified.
+ */
PRLock *_pr_deadQLock;
PRUint32 _pr_numNativeDead;
@@ -80,13 +80,13 @@ void _PR_InitThreads(PRThreadType type, PRThreadPriority priority,
stack = PR_NEWZAP(PRThreadStack);
#ifdef HAVE_STACK_GROWING_UP
stack->stackTop = (char*) ((((long)&type) >> _pr_pageShift)
- << _pr_pageShift);
+ << _pr_pageShift);
#else
#if defined(SOLARIS) || defined (UNIXWARE) && defined (USR_SVR4_THREADS)
stack->stackTop = (char*) &thread;
#else
stack->stackTop = (char*) ((((long)&type + _pr_pageSize - 1)
- >> _pr_pageShift) << _pr_pageShift);
+ >> _pr_pageShift) << _pr_pageShift);
#endif
#endif
#else
@@ -105,13 +105,13 @@ void _PR_InitThreads(PRThreadType type, PRThreadPriority priority,
if (type == PR_SYSTEM_THREAD) {
thread->flags = _PR_SYSTEM;
_pr_systemActive++;
- _pr_primordialExitCount = 0;
+ _pr_primordialExitCount = 0;
} else {
_pr_userActive++;
- _pr_primordialExitCount = 1;
+ _pr_primordialExitCount = 1;
}
- thread->no_sched = 1;
- _pr_primordialExitCVar = PR_NewCondVar(_pr_activeLock);
+ thread->no_sched = 1;
+ _pr_primordialExitCVar = PR_NewCondVar(_pr_activeLock);
}
if (!thread) PR_Abort();
@@ -126,18 +126,18 @@ void _PR_InitThreads(PRThreadType type, PRThreadPriority priority,
* _PR_MD_INIT_THREAD()
*/
if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
- /*
- * XXX do what?
- */
- }
+ /*
+ * XXX do what?
+ */
+ }
if (_PR_IS_NATIVE_THREAD(thread)) {
- PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
- _pr_global_threads++;
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
+ _pr_global_threads++;
} else {
- PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
- _pr_local_threads++;
- }
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
+ _pr_local_threads++;
+ }
_pr_recycleThreads = 0;
_pr_deadQLock = PR_NewLock();
@@ -159,13 +159,13 @@ static void _PR_InitializeNativeStack(PRThreadStack *ts)
** Setup stackTop and stackBottom values.
*/
#ifdef HAVE_STACK_GROWING_UP
- ts->allocBase = (char*) ((((long)&ts) >> _pr_pageShift)
- << _pr_pageShift);
+ ts->allocBase = (char*) ((((long)&ts) >> _pr_pageShift)
+ << _pr_pageShift);
ts->stackBottom = ts->allocBase + ts->stackSize;
ts->stackTop = ts->allocBase;
#else
- ts->allocBase = (char*) ((((long)&ts + _pr_pageSize - 1)
- >> _pr_pageShift) << _pr_pageShift);
+ ts->allocBase = (char*) ((((long)&ts + _pr_pageSize - 1)
+ >> _pr_pageShift) << _pr_pageShift);
ts->stackTop = ts->allocBase;
ts->stackBottom = ts->allocBase - ts->stackSize;
#endif
@@ -180,7 +180,7 @@ void _PR_NotifyJoinWaiters(PRThread *thread)
** Notify on our "termination" condition variable so that joining
** thread will know about our termination. Switch our context and
** come back later on to continue the cleanup.
- */
+ */
PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
if (thread->term != NULL) {
PR_Lock(_pr_terminationCVLock);
@@ -195,7 +195,7 @@ void _PR_NotifyJoinWaiters(PRThread *thread)
PR_NotifyCondVar(thread->term);
PR_Unlock(_pr_terminationCVLock);
_PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);
- PR_ASSERT(thread->state != _PR_JOIN_WAIT);
+ PR_ASSERT(thread->state != _PR_JOIN_WAIT);
}
}
@@ -235,19 +235,19 @@ static void _PR_InitializeRecycledThread(PRThread *thread)
PRStatus _PR_RecycleThread(PRThread *thread)
{
if ( _PR_IS_NATIVE_THREAD(thread) &&
- _PR_NUM_DEADNATIVE < _pr_recycleThreads) {
+ _PR_NUM_DEADNATIVE < _pr_recycleThreads) {
_PR_DEADQ_LOCK;
PR_APPEND_LINK(&thread->links, &_PR_DEADNATIVEQ);
_PR_INC_DEADNATIVE;
_PR_DEADQ_UNLOCK;
- return (PR_SUCCESS);
+ return (PR_SUCCESS);
} else if ( !_PR_IS_NATIVE_THREAD(thread) &&
- _PR_NUM_DEADUSER < _pr_recycleThreads) {
+ _PR_NUM_DEADUSER < _pr_recycleThreads) {
_PR_DEADQ_LOCK;
PR_APPEND_LINK(&thread->links, &_PR_DEADUSERQ);
_PR_INC_DEADUSER;
_PR_DEADQ_UNLOCK;
- return (PR_SUCCESS);
+ return (PR_SUCCESS);
}
return (PR_FAILURE);
}
@@ -283,7 +283,7 @@ _PR_DecrActiveThreadCount(PRThread *thread)
** Detach thread structure
*/
static void
-_PR_DetachThread(PRThread *thread)
+_PR_DestroyThread(PRThread *thread)
{
_MD_FREE_LOCK(&thread->threadLock);
PR_DELETE(thread);
@@ -293,40 +293,40 @@ void
_PR_NativeDestroyThread(PRThread *thread)
{
if(thread->term) {
- PR_DestroyCondVar(thread->term);
+ PR_DestroyCondVar(thread->term);
thread->term = 0;
}
PR_DELETE(thread->stack);
- _PR_DetachThread(thread);
+ _PR_DestroyThread(thread);
}
void
_PR_UserDestroyThread(PRThread *thread)
{
if(thread->term) {
- PR_DestroyCondVar(thread->term);
- thread->term = 0;
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ if (NULL != thread->privateData)
+ {
+ PR_ASSERT(0 != thread->tpdLength);
+ PR_DELETE(thread->privateData);
+ thread->privateData = NULL;
+ thread->tpdLength = 0;
}
- if (NULL != thread->privateData)
- {
- PR_ASSERT(0 != thread->tpdLength);
- PR_DELETE(thread->privateData);
- thread->privateData = NULL;
- thread->tpdLength = 0;
- }
_MD_FREE_LOCK(&thread->threadLock);
if (thread->threadAllocatedOnStack == 1) {
- _PR_MD_CLEAN_THREAD(thread);
- /*
- * Because the no_sched field is set, this thread/stack will
- * will not be re-used until the flag is cleared by the thread
- * we will context switch to.
- */
- _PR_FreeStack(thread->stack);
+ _PR_MD_CLEAN_THREAD(thread);
+ /*
+ * Because the no_sched field is set, this thread/stack will
+ * will not be re-used until the flag is cleared by the thread
+ * we will context switch to.
+ */
+ _PR_FreeStack(thread->stack);
} else {
#ifdef WINNT
- _PR_MD_CLEAN_THREAD(thread);
+ _PR_MD_CLEAN_THREAD(thread);
#else
/*
* This assertion does not apply to NT. On NT, every fiber,
@@ -347,38 +347,38 @@ _PR_UserDestroyThread(PRThread *thread)
*/
void _PR_NativeRunThread(void *arg)
{
- PRThread *thread = (PRThread *)arg;
+ PRThread *thread = (PRThread *)arg;
_PR_MD_SET_CURRENT_THREAD(thread);
_PR_MD_SET_CURRENT_CPU(NULL);
- /* Set up the thread stack information */
- _PR_InitializeNativeStack(thread->stack);
+ /* Set up the thread stack information */
+ _PR_InitializeNativeStack(thread->stack);
- /* Set up the thread md information */
- if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
- /*
- * thread failed to initialize itself, possibly due to
- * failure to allocate per-thread resources
- */
- return;
- }
+ /* Set up the thread md information */
+ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
+ /*
+ * thread failed to initialize itself, possibly due to
+ * failure to allocate per-thread resources
+ */
+ return;
+ }
while(1) {
thread->state = _PR_RUNNING;
- if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_SET_INTSOFF(0);
+ if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0);
- /*
- * Add to list of active threads
- */
- PR_Lock(_pr_activeLock);
- PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
- _pr_global_threads++;
- PR_Unlock(_pr_activeLock);
+ /*
+ * Add to list of active threads
+ */
+ PR_Lock(_pr_activeLock);
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
+ _pr_global_threads++;
+ PR_Unlock(_pr_activeLock);
- (*thread->startFunc)(thread->arg);
+ (*thread->startFunc)(thread->arg);
/*
* The following two assertions are meant for NT asynch io.
@@ -397,15 +397,15 @@ void _PR_NativeRunThread(void *arg)
*/
PR_ASSERT(thread->io_suspended == PR_FALSE);
- /*
- * remove thread from list of active threads
- */
+ /*
+ * remove thread from list of active threads
+ */
PR_Lock(_pr_activeLock);
PR_REMOVE_LINK(&thread->active);
- _pr_global_threads--;
+ _pr_global_threads--;
PR_Unlock(_pr_activeLock);
- PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));
/* All done, time to go away */
_PR_CleanupThread(thread);
@@ -417,21 +417,21 @@ void _PR_NativeRunThread(void *arg)
thread->state = _PR_DEAD_STATE;
if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
- PR_FAILURE)) {
- /*
- * thread not recycled
- * platform-specific thread exit processing
- * - for stuff like releasing native-thread resources, etc.
- */
- _PR_MD_EXIT_THREAD(thread);
- /*
- * Free memory allocated for the thread
- */
- _PR_NativeDestroyThread(thread);
- /*
- * thread gone, cannot de-reference thread now
- */
- return;
+ PR_FAILURE)) {
+ /*
+ * thread not recycled
+ * platform-specific thread exit processing
+ * - for stuff like releasing native-thread resources, etc.
+ */
+ _PR_MD_EXIT_THREAD(thread);
+ /*
+ * Free memory allocated for the thread
+ */
+ _PR_NativeDestroyThread(thread);
+ /*
+ * thread gone, cannot de-reference thread now
+ */
+ return;
}
/* Now wait for someone to activate us again... */
@@ -445,7 +445,7 @@ static void _PR_UserRunThread(void)
PRIntn is;
if (_MD_LAST_THREAD())
- _MD_LAST_THREAD()->no_sched = 0;
+ _MD_LAST_THREAD()->no_sched = 0;
#ifdef HAVE_CUSTOM_USER_THREADS
if (thread->stack == NULL) {
@@ -456,17 +456,17 @@ static void _PR_UserRunThread(void)
while(1) {
/* Run thread main */
- if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_SET_INTSOFF(0);
-
- /*
- * Add to list of active threads
- */
- if (!(thread->flags & _PR_IDLE_THREAD)) {
- PR_Lock(_pr_activeLock);
- PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
- _pr_local_threads++;
- PR_Unlock(_pr_activeLock);
- }
+ if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0);
+
+ /*
+ * Add to list of active threads
+ */
+ if (!(thread->flags & _PR_IDLE_THREAD)) {
+ PR_Lock(_pr_activeLock);
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
+ _pr_local_threads++;
+ PR_Unlock(_pr_activeLock);
+ }
(*thread->startFunc)(thread->arg);
@@ -488,33 +488,33 @@ static void _PR_UserRunThread(void)
PR_ASSERT(thread->io_suspended == PR_FALSE);
PR_Lock(_pr_activeLock);
- /*
- * remove thread from list of active threads
- */
- if (!(thread->flags & _PR_IDLE_THREAD)) {
- PR_REMOVE_LINK(&thread->active);
- _pr_local_threads--;
- }
- PR_Unlock(_pr_activeLock);
+ /*
+ * remove thread from list of active threads
+ */
+ if (!(thread->flags & _PR_IDLE_THREAD)) {
+ PR_REMOVE_LINK(&thread->active);
+ _pr_local_threads--;
+ }
+ PR_Unlock(_pr_activeLock);
PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));
/* All done, time to go away */
_PR_CleanupThread(thread);
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
_PR_NotifyJoinWaiters(thread);
- _PR_DecrActiveThreadCount(thread);
+ _PR_DecrActiveThreadCount(thread);
thread->state = _PR_DEAD_STATE;
if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
- PR_FAILURE)) {
+ PR_FAILURE)) {
/*
** Destroy the thread resources
*/
- _PR_UserDestroyThread(thread);
+ _PR_UserDestroyThread(thread);
}
/*
@@ -542,55 +542,53 @@ void _PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri)
}
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
_PR_THREAD_LOCK(thread);
if (newPri != thread->priority) {
- PRUintn oldPri;
- _PRCPU *cpu = thread->cpu;
+ _PRCPU *cpu = thread->cpu;
- oldPri = thread->priority;
- switch (thread->state) {
- case _PR_RUNNING:
- /* Change my priority */
+ switch (thread->state) {
+ case _PR_RUNNING:
+ /* Change my priority */
_PR_RUNQ_LOCK(cpu);
- thread->priority = newPri;
- if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) {
- if (!_PR_IS_NATIVE_THREAD(me))
+ thread->priority = newPri;
+ if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) {
+ if (!_PR_IS_NATIVE_THREAD(me))
_PR_SET_RESCHED_FLAG();
- }
+ }
_PR_RUNQ_UNLOCK(cpu);
- break;
+ break;
- case _PR_RUNNABLE:
+ case _PR_RUNNABLE:
- _PR_RUNQ_LOCK(cpu);
+ _PR_RUNQ_LOCK(cpu);
/* Move to different runQ */
_PR_DEL_RUNQ(thread);
thread->priority = newPri;
PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
_PR_ADD_RUNQ(thread, cpu, newPri);
- _PR_RUNQ_UNLOCK(cpu);
+ _PR_RUNQ_UNLOCK(cpu);
if (newPri > me->priority) {
- if (!_PR_IS_NATIVE_THREAD(me))
- _PR_SET_RESCHED_FLAG();
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_SET_RESCHED_FLAG();
}
- break;
+ break;
- case _PR_LOCK_WAIT:
- case _PR_COND_WAIT:
- case _PR_IO_WAIT:
- case _PR_SUSPENDED:
+ case _PR_LOCK_WAIT:
+ case _PR_COND_WAIT:
+ case _PR_IO_WAIT:
+ case _PR_SUSPENDED:
- thread->priority = newPri;
- break;
- }
+ thread->priority = newPri;
+ break;
+ }
}
_PR_THREAD_UNLOCK(thread);
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSON(is);
+ _PR_INTSON(is);
}
/*
@@ -605,7 +603,7 @@ static void _PR_Suspend(PRThread *thread)
PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread) || (!thread->cpu));
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
_PR_THREAD_LOCK(thread);
switch (thread->state) {
case _PR_RUNNABLE:
@@ -617,21 +615,21 @@ static void _PR_Suspend(PRThread *thread)
_PR_MISCQ_LOCK(thread->cpu);
_PR_ADD_SUSPENDQ(thread, thread->cpu);
_PR_MISCQ_UNLOCK(thread->cpu);
- } else {
- /*
- * Only LOCAL threads are suspended by _PR_Suspend
- */
- PR_ASSERT(0);
- }
+ } else {
+ /*
+ * Only LOCAL threads are suspended by _PR_Suspend
+ */
+ PR_ASSERT(0);
+ }
thread->state = _PR_SUSPENDED;
break;
case _PR_RUNNING:
- /*
- * The thread being suspended should be a LOCAL thread with
- * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
- */
- PR_ASSERT(0);
+ /*
+ * The thread being suspended should be a LOCAL thread with
+ * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
+ */
+ PR_ASSERT(0);
break;
case _PR_LOCK_WAIT:
@@ -639,7 +637,7 @@ static void _PR_Suspend(PRThread *thread)
case _PR_COND_WAIT:
if (_PR_IS_NATIVE_THREAD(thread)) {
_PR_MD_SUSPEND_THREAD(thread);
- }
+ }
thread->flags |= _PR_SUSPENDING;
break;
@@ -676,12 +674,12 @@ static void _PR_Resume(PRThread *thread)
_PR_RUNQ_UNLOCK(thread->cpu);
if (pri > _PR_MD_CURRENT_THREAD()->priority) {
- if (!_PR_IS_NATIVE_THREAD(me))
- _PR_SET_RESCHED_FLAG();
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_SET_RESCHED_FLAG();
}
- } else {
- PR_ASSERT(0);
- }
+ } else {
+ PR_ASSERT(0);
+ }
break;
case _PR_IO_WAIT:
@@ -692,7 +690,7 @@ static void _PR_Resume(PRThread *thread)
case _PR_LOCK_WAIT:
{
- PRLock *wLock = thread->wait.lock;
+ PRLock *wLock = thread->wait.lock;
thread->flags &= ~_PR_SUSPENDING;
@@ -704,25 +702,25 @@ static void _PR_Resume(PRThread *thread)
break;
}
case _PR_RUNNABLE:
- break;
+ break;
case _PR_RUNNING:
- /*
- * The thread being suspended should be a LOCAL thread with
- * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
- */
- PR_ASSERT(0);
- break;
+ /*
+ * The thread being suspended should be a LOCAL thread with
+ * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
+ */
+ PR_ASSERT(0);
+ break;
default:
- /*
- * thread should have been in one of the above-listed blocked states
- * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE)
- */
+ /*
+ * thread should have been in one of the above-listed blocked states
+ * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE)
+ */
PR_Abort();
}
_PR_THREAD_UNLOCK(thread);
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSON(is);
+ _PR_INTSON(is);
}
@@ -747,7 +745,7 @@ static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
}
thread = NULL;
for (pri = priMax; pri >= priMin ; pri-- ) {
- if (r & (1 << pri)) {
+ if (r & (1 << pri)) {
for (qp = _PR_RUNQ(cpu)[pri].next;
qp != &_PR_RUNQ(cpu)[pri];
qp = qp->next) {
@@ -756,30 +754,40 @@ static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
* skip non-schedulable threads
*/
PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
- if (thread->no_sched){
+ if (thread->no_sched) {
thread = NULL;
- /*
- * Need to wakeup cpus to avoid missing a
- * runnable thread
- * Waking up all CPU's need happen only once.
- */
+ /*
+ * Need to wakeup cpus to avoid missing a
+ * runnable thread
+ * Waking up all CPU's need happen only once.
+ */
- *wakeup_cpus = PR_TRUE;
+ *wakeup_cpus = PR_TRUE;
+ continue;
+ } else if (thread->flags & _PR_BOUND_THREAD) {
+ /*
+ * Thread bound to cpu 0
+ */
+
+ thread = NULL;
+#ifdef IRIX
+ _PR_MD_WAKEUP_PRIMORDIAL_CPU();
+#endif
continue;
} else if (thread->io_pending == PR_TRUE) {
- /*
- * A thread that is blocked for I/O needs to run
- * on the same cpu on which it was blocked. This is because
- * the cpu's ioq is accessed without lock protection and scheduling
- * the thread on a different cpu would preclude this optimization.
- */
+ /*
+ * A thread that is blocked for I/O needs to run
+ * on the same cpu on which it was blocked. This is because
+ * the cpu's ioq is accessed without lock protection and scheduling
+ * the thread on a different cpu would preclude this optimization.
+ */
thread = NULL;
- continue;
+ continue;
} else {
/* Pull thread off of its run queue */
_PR_DEL_RUNQ(thread);
_PR_RUNQ_UNLOCK(cpu);
- return(thread);
+ return(thread);
}
}
}
@@ -802,7 +810,7 @@ static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
void _PR_Schedule(void)
{
PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
- _PRCPU *cpu = me->cpu;
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
PRIntn pri;
PRUint32 r;
PRCList *qp;
@@ -824,22 +832,22 @@ void _PR_Schedule(void)
_PR_RUNQ_LOCK(cpu);
/*
* if we are in SuspendAll mode, can schedule only the thread
- * that called PR_SuspendAll
+ * that called PR_SuspendAll
*
* The thread may be ready to run now, after completing an I/O
* operation, for example
*/
if ((thread = suspendAllThread) != 0) {
- if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) {
+ if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) {
/* Pull thread off of its run queue */
_PR_DEL_RUNQ(thread);
_PR_RUNQ_UNLOCK(cpu);
goto found_thread;
- } else {
+ } else {
thread = NULL;
_PR_RUNQ_UNLOCK(cpu);
goto idle_thread;
- }
+ }
}
r = _PR_RUNQREADYMASK(cpu);
if (r==0) {
@@ -852,7 +860,7 @@ void _PR_Schedule(void)
}
thread = NULL;
for (pri = priMax; pri >= priMin ; pri-- ) {
- if (r & (1 << pri)) {
+ if (r & (1 << pri)) {
for (qp = _PR_RUNQ(cpu)[pri].next;
qp != &_PR_RUNQ(cpu)[pri];
qp = qp->next) {
@@ -880,25 +888,25 @@ void _PR_Schedule(void)
#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
- wakeup_cpus = PR_FALSE;
+ wakeup_cpus = PR_FALSE;
_PR_CPU_LIST_LOCK();
for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
- if (cpu != _PR_CPU_PTR(qp)) {
- if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))
- != NULL) {
- thread->cpu = cpu;
- _PR_CPU_LIST_UNLOCK();
- if (wakeup_cpus == PR_TRUE)
- _PR_MD_WAKEUP_CPUS();
- goto found_thread;
- }
- }
+ if (cpu != _PR_CPU_PTR(qp)) {
+ if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))
+ != NULL) {
+ thread->cpu = cpu;
+ _PR_CPU_LIST_UNLOCK();
+ if (wakeup_cpus == PR_TRUE)
+ _PR_MD_WAKEUP_CPUS();
+ goto found_thread;
+ }
+ }
}
_PR_CPU_LIST_UNLOCK();
- if (wakeup_cpus == PR_TRUE)
- _PR_MD_WAKEUP_CPUS();
+ if (wakeup_cpus == PR_TRUE)
+ _PR_MD_WAKEUP_CPUS();
-#endif /* _PR_LOCAL_THREADS_ONLY */
+#endif /* _PR_LOCAL_THREADS_ONLY */
idle_thread:
/*
@@ -909,11 +917,11 @@ idle_thread:
found_thread:
PR_ASSERT((me == thread) || ((thread->state == _PR_RUNNABLE) &&
- (!(thread->no_sched))));
+ (!(thread->no_sched))));
/* Resume the thread */
PR_LOG(_pr_sched_lm, PR_LOG_MAX,
- ("switching to %d[%p]", thread->id, thread));
+ ("switching to %d[%p]", thread->id, thread));
PR_ASSERT(thread->state != _PR_RUNNING);
thread->state = _PR_RUNNING;
@@ -921,6 +929,7 @@ found_thread:
* resource, and by the time we got here another real native thread had
* already given us the resource and put us back on the runqueue
*/
+ PR_ASSERT(thread->cpu == _PR_MD_CURRENT_CPU());
if (thread != me)
_PR_MD_RESTORE_CONTEXT(thread);
#if 0
@@ -962,9 +971,9 @@ _PR_AttachThread(PRThreadType type, PRThreadPriority priority,
thread->state = _PR_RUNNING;
PR_INIT_CLIST(&thread->lockList);
if (_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
- PR_DELETE(thread);
- return 0;
- }
+ PR_DELETE(thread);
+ return 0;
+ }
return thread;
}
@@ -975,12 +984,12 @@ _PR_AttachThread(PRThreadType type, PRThreadPriority priority,
PR_IMPLEMENT(PRThread*)
_PR_NativeCreateThread(PRThreadType type,
- void (*start)(void *arg),
- void *arg,
- PRThreadPriority priority,
- PRThreadScope scope,
- PRThreadState state,
- PRUint32 stackSize,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize,
PRUint32 flags)
{
#if defined(XP_MAC)
@@ -993,7 +1002,7 @@ _PR_NativeCreateThread(PRThreadType type,
if (thread) {
PR_Lock(_pr_activeLock);
- thread->flags = (flags | _PR_GLOBAL_SCOPE);
+ thread->flags = (flags | _PR_GLOBAL_SCOPE);
thread->id = ++_pr_utid;
if (type == PR_SYSTEM_THREAD) {
thread->flags |= _PR_SYSTEM;
@@ -1019,28 +1028,28 @@ _PR_NativeCreateThread(PRThreadType type,
*/
if (state == PR_JOINABLE_THREAD) {
thread->term = PR_NewCondVar(_pr_terminationCVLock);
- if (thread->term == NULL) {
- PR_DELETE(thread->stack);
- goto done;
- }
+ if (thread->term == NULL) {
+ PR_DELETE(thread->stack);
+ goto done;
+ }
}
- thread->state = _PR_RUNNING;
+ thread->state = _PR_RUNNING;
if (_PR_MD_CREATE_THREAD(thread, _PR_NativeRunThread, priority,
scope,state,stackSize) == PR_SUCCESS) {
return thread;
}
if (thread->term) {
PR_DestroyCondVar(thread->term);
- thread->term = NULL;
- }
- PR_DELETE(thread->stack);
+ thread->term = NULL;
+ }
+ PR_DELETE(thread->stack);
}
done:
if (thread) {
- _PR_DecrActiveThreadCount(thread);
- _PR_DetachThread(thread);
+ _PR_DecrActiveThreadCount(thread);
+ _PR_DestroyThread(thread);
}
return NULL;
}
@@ -1048,12 +1057,12 @@ done:
/************************************************************************/
PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
- void (*start)(void *arg),
- void *arg,
- PRThreadPriority priority,
- PRThreadScope scope,
- PRThreadState state,
- PRUint32 stackSize,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize,
PRUint32 flags)
{
PRThread *me;
@@ -1065,35 +1074,35 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
PRIntn useRecycled = 0;
PRBool status;
- /*
- First, pin down the priority. Not all compilers catch passing out of
- range enum here. If we let bad values thru, priority queues won't work.
- */
+ /*
+ First, pin down the priority. Not all compilers catch passing out of
+ range enum here. If we let bad values thru, priority queues won't work.
+ */
if (priority > PR_PRIORITY_LAST) {
priority = PR_PRIORITY_LAST;
} else if (priority < PR_PRIORITY_FIRST) {
priority = PR_PRIORITY_FIRST;
}
-
+
if (!_pr_initialized) _PR_ImplicitInitialization();
if (! (flags & _PR_IDLE_THREAD))
- me = _PR_MD_CURRENT_THREAD();
+ me = _PR_MD_CURRENT_THREAD();
-#if defined(_PR_GLOBAL_THREADS_ONLY)
+#if defined(_PR_GLOBAL_THREADS_ONLY)
scope = PR_GLOBAL_THREAD;
#endif
native = ((scope == PR_GLOBAL_THREAD) && _PR_IS_NATIVE_THREAD_SUPPORTED());
- _PR_ADJUST_STACKSIZE(stackSize);
+ _PR_ADJUST_STACKSIZE(stackSize);
if (native) {
- /*
- * clear the IDLE_THREAD flag which applies to LOCAL
- * threads only
- */
- flags &= ~_PR_IDLE_THREAD;
+ /*
+ * clear the IDLE_THREAD flag which applies to LOCAL
+ * threads only
+ */
+ flags &= ~_PR_IDLE_THREAD;
flags |= _PR_GLOBAL_SCOPE;
if (_PR_NUM_DEADNATIVE > 0) {
_PR_DEADQ_LOCK;
@@ -1109,33 +1118,31 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
_PR_InitializeRecycledThread(thread);
thread->startFunc = start;
thread->arg = arg;
- PR_Lock(_pr_activeLock);
- thread->flags = (flags | _PR_GLOBAL_SCOPE);
- if (type == PR_SYSTEM_THREAD) {
- thread->flags |= _PR_SYSTEM;
- _pr_systemActive++;
- } else {
- _pr_userActive++;
- }
- PR_Unlock(_pr_activeLock);
-
- if (state == PR_JOINABLE_THREAD) {
- if (!thread->term)
- thread->term = PR_NewCondVar(_pr_terminationCVLock);
- }
- else {
- if(thread->term) {
- PR_DestroyCondVar(thread->term);
- thread->term = 0;
- }
- }
+ thread->flags = (flags | _PR_GLOBAL_SCOPE);
+ if (type == PR_SYSTEM_THREAD)
+ {
+ thread->flags |= _PR_SYSTEM;
+ PR_AtomicIncrement(&_pr_systemActive);
+ }
+ else PR_AtomicIncrement(&_pr_userActive);
+
+ if (state == PR_JOINABLE_THREAD) {
+ if (!thread->term)
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ }
+ else {
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ }
thread->priority = priority;
- _PR_MD_SET_PRIORITY(&(thread->md), priority);
- /* XXX what about stackSize? */
- thread->state = _PR_RUNNING;
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ /* XXX what about stackSize? */
+ thread->state = _PR_RUNNING;
_PR_MD_WAKEUP_WAITER(thread);
- return thread;
+ return thread;
}
}
thread = _PR_NativeCreateThread(type, start, arg, priority,
@@ -1156,7 +1163,7 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
while( ptr != &_PR_DEADUSERQ ) {
thread = _PR_THREAD_PTR(ptr);
if ((thread->stack->stackSize >= stackSize) &&
- (!thread->no_sched)) {
+ (!thread->no_sched)) {
PR_REMOVE_LINK(&thread->links);
_PR_DEC_DEADUSER;
break;
@@ -1173,15 +1180,15 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
thread->startFunc = start;
thread->arg = arg;
thread->priority = priority;
- if (state == PR_JOINABLE_THREAD) {
- if (!thread->term)
- thread->term = PR_NewCondVar(_pr_terminationCVLock);
- } else {
- if(thread->term) {
- PR_DestroyCondVar(thread->term);
- thread->term = 0;
- }
- }
+ if (state == PR_JOINABLE_THREAD) {
+ if (!thread->term)
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ } else {
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ }
useRecycled++;
}
}
@@ -1191,31 +1198,31 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
stack = _PR_NewStack(stackSize);
if (!stack) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return 0;
+ return 0;
}
- stack->thr = thread;
/* Allocate thread object and per-thread data off the top of the stack*/
top = stack->stackTop;
#ifdef HAVE_STACK_GROWING_UP
thread = (PRThread*) top;
top = top + sizeof(PRThread);
- /*
- * Make stack 64-byte aligned
- */
+ /*
+ * Make stack 64-byte aligned
+ */
if ((PRUptrdiff)top & 0x3f) {
top = (char*)(((PRUptrdiff)top + 0x40) & ~0x3f);
}
#else
top = top - sizeof(PRThread);
thread = (PRThread*) top;
- /*
- * Make stack 64-byte aligned
- */
+ /*
+ * Make stack 64-byte aligned
+ */
if ((PRUptrdiff)top & 0x3f) {
top = (char*)((PRUptrdiff)top & ~0x3f);
}
#endif
+ stack->thr = thread;
memset(thread, 0, sizeof(PRThread));
thread->threadAllocatedOnStack = 1;
#else
@@ -1229,8 +1236,6 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
#endif
/* Initialize thread */
- if (stack)
- stack->thr = thread;
thread->tpdLength = 0;
thread->privateData = NULL;
thread->stack = stack;
@@ -1240,36 +1245,36 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
PR_INIT_CLIST(&thread->lockList);
if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
- if (thread->threadAllocatedOnStack == 1)
- _PR_FreeStack(thread->stack);
- else {
- PR_DELETE(thread);
- }
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
- return NULL;
- }
-
- if (_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
- if (thread->threadAllocatedOnStack == 1)
- _PR_FreeStack(thread->stack);
- else {
- PR_DELETE(thread->privateData);
- PR_DELETE(thread);
- }
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
- return NULL;
- }
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread);
+ }
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
+
+ if (_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
+ PR_DELETE(thread);
+ }
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
_PR_MD_INIT_CONTEXT(thread, top, _PR_UserRunThread, &status);
if (status == PR_FALSE) {
- _MD_FREE_LOCK(&thread->threadLock);
- if (thread->threadAllocatedOnStack == 1)
- _PR_FreeStack(thread->stack);
- else {
- PR_DELETE(thread->privateData);
+ _MD_FREE_LOCK(&thread->threadLock);
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
PR_DELETE(thread);
- }
+ }
return NULL;
}
@@ -1279,16 +1284,16 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
*/
if (state == PR_JOINABLE_THREAD) {
thread->term = PR_NewCondVar(_pr_terminationCVLock);
- if (thread->term == NULL) {
- _MD_FREE_LOCK(&thread->threadLock);
- if (thread->threadAllocatedOnStack == 1)
- _PR_FreeStack(thread->stack);
- else {
- PR_DELETE(thread->privateData);
- PR_DELETE(thread);
- }
- return NULL;
- }
+ if (thread->term == NULL) {
+ _MD_FREE_LOCK(&thread->threadLock);
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
+ PR_DELETE(thread);
+ }
+ return NULL;
+ }
}
}
@@ -1306,9 +1311,9 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
/* Make thread runnable */
thread->state = _PR_RUNNABLE;
- /*
- * Add to list of active threads
- */
+ /*
+ * Add to list of active threads
+ */
PR_Unlock(_pr_activeLock);
if ( (thread->flags & _PR_IDLE_THREAD) || _PR_IS_NATIVE_THREAD(me) )
@@ -1317,7 +1322,7 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
thread->cpu = _PR_MD_CURRENT_CPU();
if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me))
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(thread)) {
_PR_RUNQ_LOCK(thread->cpu);
_PR_ADD_RUNQ(thread, thread->cpu, priority);
@@ -1334,19 +1339,19 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
_PR_MD_WAKEUP_WAITER(NULL);
}
if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me) )
- _PR_INTSON(is);
+ _PR_INTSON(is);
}
return thread;
}
PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type,
- void (*start)(void *arg),
- void *arg,
- PRThreadPriority priority,
- PRThreadScope scope,
- PRThreadState state,
- PRUint32 stackSize)
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
{
return _PR_CreateThread(type, start, arg, priority, scope, state,
stackSize, 0);
@@ -1354,9 +1359,9 @@ PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type,
/*
** Associate a thread object with an existing native thread.
-** "type" is the type of thread object to attach
-** "priority" is the priority to assign to the thread
-** "stack" defines the shape of the threads stack
+** "type" is the type of thread object to attach
+** "priority" is the priority to assign to the thread
+** "stack" defines the shape of the threads stack
**
** This can return NULL if some kind of error occurs, or if memory is
** tight.
@@ -1364,7 +1369,7 @@ PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type,
** This call is not normally needed unless you create your own native
** thread. PR_Init does this automatically for the primordial thread.
*/
-PR_IMPLEMENT(PRThread*) _PRI_AttachThread(PRThreadType type,
+PRThread* _PRI_AttachThread(PRThreadType type,
PRThreadPriority priority, PRThreadStack *stack, PRUint32 flags)
{
PRThread *thread;
@@ -1372,6 +1377,7 @@ PR_IMPLEMENT(PRThread*) _PRI_AttachThread(PRThreadType type,
if ((thread = _PR_MD_GET_ATTACHED_THREAD()) != NULL) {
return thread;
}
+ _PR_MD_SET_CURRENT_THREAD(NULL);
/* Clear out any state if this thread was attached before */
_PR_MD_SET_CURRENT_CPU(NULL);
@@ -1387,7 +1393,7 @@ PR_IMPLEMENT(PRThread*) _PRI_AttachThread(PRThreadType type,
if (!stack) {
thread->stack = PR_NEWZAP(PRThreadStack);
if (!thread->stack) {
- _PR_DetachThread(thread);
+ _PR_DestroyThread(thread);
return NULL;
}
thread->stack->stackSize = _MD_DEFAULT_STACK_SIZE;
@@ -1396,9 +1402,9 @@ PR_IMPLEMENT(PRThread*) _PRI_AttachThread(PRThreadType type,
if (_PR_MD_INIT_ATTACHED_THREAD(thread) == PR_FAILURE) {
PR_DELETE(thread->stack);
- _PR_DetachThread(thread);
+ _PR_DestroyThread(thread);
return NULL;
- }
+ }
_PR_MD_SET_CURRENT_CPU(NULL);
@@ -1423,34 +1429,31 @@ PR_IMPLEMENT(PRThread*) _PRI_AttachThread(PRThreadType type,
PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type,
PRThreadPriority priority, PRThreadStack *stack)
{
- return _PRI_AttachThread(type, priority, stack, 0);
+ return PR_GetCurrentThread();
}
-/*
-** Detach the nspr thread from the currently executing native thread.
-** The thread object will be destroyed and all related data attached
-** to it. The exit procs will be invoked.
-**
-** This call is not normally needed unless you create your own native
-** thread. PR_Exit will automatially detach the nspr thread object
-** created by PR_Init for the primordial thread.
-**
-** This call returns after the nspr thread object is destroyed.
-*/
PR_IMPLEMENT(void) PR_DetachThread(void)
{
- PRIntn is;
+}
+
+void _PRI_DetachThread(void)
+{
PRThread *me = _PR_MD_CURRENT_THREAD();
+ if (me->flags & _PR_PRIMORDIAL) {
+ /*
+ * ignore, if primordial thread
+ */
+ return;
+ }
PR_ASSERT(me->flags & _PR_ATTACHED);
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me));
_PR_CleanupThread(me);
- PR_DELETE(me->privateData);
- _PR_MD_CLEAN_THREAD(me);
+ PR_DELETE(me->privateData);
- /*XXX we need DetachCPU */
- if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
_PR_DecrActiveThreadCount(me);
- if ( !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is);
+
+ _PR_MD_CLEAN_THREAD(me);
_PR_MD_SET_CURRENT_THREAD(NULL);
if (!me->threadAllocatedOnStack)
PR_DELETE(me->stack);
@@ -1460,7 +1463,7 @@ PR_IMPLEMENT(void) PR_DetachThread(void)
/*
** Wait for thread termination:
-** "thread" is the target thread
+** "thread" is the target thread
**
** This can return PR_FAILURE if no joinable thread could be found
** corresponding to the specified target thread.
@@ -1478,10 +1481,11 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
PRThread *me = _PR_MD_CURRENT_THREAD();
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
term = thread->term;
/* can't join a non-joinable thread */
if (term == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto ErrorExit;
}
@@ -1490,7 +1494,7 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
goto ErrorExit;
}
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSON(is);
+ _PR_INTSON(is);
/* wait for the target thread's termination cv invariant */
PR_Lock (_pr_terminationCVLock);
@@ -1498,14 +1502,14 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
(void) PR_WaitCondVar(term, PR_INTERVAL_NO_TIMEOUT);
}
(void) PR_Unlock (_pr_terminationCVLock);
-
+
/*
Remove target thread from global waiting to join Q; make it runnable
again and put it back on its run Q. When it gets scheduled later in
_PR_RunThread code, it will clean up its stack.
- */
+ */
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSOFF(is);
+ _PR_INTSOFF(is);
thread->state = _PR_RUNNABLE;
if ( !_PR_IS_NATIVE_THREAD(thread) ) {
_PR_THREAD_LOCK(thread);
@@ -1518,7 +1522,7 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
_PR_THREAD_UNLOCK(thread);
}
if (!_PR_IS_NATIVE_THREAD(me))
- _PR_INTSON(is);
+ _PR_INTSON(is);
_PR_MD_WAKEUP_WAITER(thread);
@@ -1533,16 +1537,16 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thread,
PRThreadPriority newPri)
{
- /*
- First, pin down the priority. Not all compilers catch passing out of
- range enum here. If we let bad values thru, priority queues won't work.
- */
+ /*
+ First, pin down the priority. Not all compilers catch passing out of
+ range enum here. If we let bad values thru, priority queues won't work.
+ */
if (newPri > PR_PRIORITY_LAST) {
newPri = PR_PRIORITY_LAST;
} else if (newPri < PR_PRIORITY_FIRST) {
newPri = PR_PRIORITY_FIRST;
}
-
+
if ( _PR_IS_NATIVE_THREAD(thread) ) {
thread->priority = newPri;
_PR_MD_SET_PRIORITY(&(thread->md), newPri);
@@ -1567,18 +1571,18 @@ PR_IMPLEMENT(void) PR_SuspendAll(void)
suspendAllThread = _PR_MD_CURRENT_THREAD();
_PR_MD_BEGIN_SUSPEND_ALL();
for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
- qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
- if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
- (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD)) {
- _PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp));
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD)) {
+ _PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp));
PR_ASSERT((_PR_ACTIVE_THREAD_PTR(qp))->state != _PR_RUNNING);
}
}
for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
- qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
- if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
- (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
- /* PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); */
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
+ /* PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); */
_PR_MD_SUSPEND_THREAD(_PR_ACTIVE_THREAD_PTR(qp));
}
_PR_MD_END_SUSPEND_ALL();
@@ -1598,15 +1602,15 @@ PR_IMPLEMENT(void) PR_ResumeAll(void)
*/
_PR_MD_BEGIN_RESUME_ALL();
for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
- qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
- if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
- (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
- _PR_Resume(_PR_ACTIVE_THREAD_PTR(qp));
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
+ _PR_Resume(_PR_ACTIVE_THREAD_PTR(qp));
}
for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
- qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
- if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
- (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ (_PR_ACTIVE_THREAD_PTR(qp)->flags & _PR_GCABLE_THREAD))
_PR_MD_RESUME_THREAD(_PR_ACTIVE_THREAD_PTR(qp));
}
_PR_MD_END_RESUME_ALL();
diff --git a/pr/src/threads/prcthr.c b/pr/src/threads/prcthr.c
index 6b3c80c7..1d9fd809 100644
--- a/pr/src/threads/prcthr.c
+++ b/pr/src/threads/prcthr.c
@@ -86,7 +86,10 @@ PR_IMPLEMENT(PRStatus) PR_Yield()
*/
PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
{
- PRStatus rv = PR_SUCCESS;
+ PRStatus rv = PR_SUCCESS;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
if (PR_INTERVAL_NO_WAIT == timeout)
{
/*
@@ -129,16 +132,19 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
** but the lock and cvar used are local to the implementation
** and not visible to the caller, therefore not notifiable.
*/
- PRIntervalTime timein = PR_IntervalNow();
- PRCondVar *cv = PR_NewCondVar(_pr_sleeplock);
+ PRCondVar *cv;
+ PRIntervalTime timein;
+ timein = PR_IntervalNow();
+ cv = PR_NewCondVar(_pr_sleeplock);
+ PR_ASSERT(cv != NULL);
PR_Lock(_pr_sleeplock);
- while (rv == PR_SUCCESS)
+ do
{
PRIntervalTime delta = PR_IntervalNow() - timein;
if (delta > timeout) break;
rv = PR_WaitCondVar(cv, timeout - delta);
- }
+ } while (rv == PR_SUCCESS);
PR_Unlock(_pr_sleeplock);
PR_DestroyCondVar(cv);
}
@@ -366,8 +372,9 @@ PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type,
PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble(
PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
{
- if (!_pr_initialized) _PR_ImplicitInitialization();
- return _PRI_AttachThread(type, priority, stack, _PR_GCABLE_THREAD);
+ /* $$$$ not sure how to finese this one */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
}
PR_IMPLEMENT(void) PR_SetThreadGCAble()
diff --git a/pr/src/threads/prtpd.c b/pr/src/threads/prtpd.c
index b92ebbbb..54ce8027 100644
--- a/pr/src/threads/prtpd.c
+++ b/pr/src/threads/prtpd.c
@@ -44,40 +44,24 @@
#define _PR_TPD_MODULO 8 /* vectors are extended by this much */
#define _PR_TPD_LIMIT 128 /* arbitary limit on the TPD slots */
-static PRUintn _pr_tpd_highwater = 0; /* next TPD key to be assigned */
-static PRUintn _pr_tpd_length = 0; /* current length of destructor vector */
+static PRInt32 _pr_tpd_length = 0; /* current length of destructor vector */
+static PRInt32 _pr_tpd_highwater = 0; /* next TPD key to be assigned */
PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
/* the destructors are associated with
the keys, therefore asserting that
the TPD key depicts the data's 'type' */
/* Lock protecting the index assignment of per-thread-private data table */
-#ifdef _PR_NO_PREEMPT
-#define _PR_NEW_LOCK_TPINDEX()
-#define _PR_FREE_LOCK_TPINDEX()
-#define _PR_LOCK_TPINDEX()
-#define _PR_UNLOCK_TPINDEX()
-#else
-#ifdef _PR_LOCAL_THREADS_ONLY
-#define _PR_NEW_LOCK_TPINDEX()
-#define _PR_FREE_LOCK_TPINDEX()
-#define _PR_LOCK_TPINDEX() _PR_INTSOFF(_is)
-#define _PR_UNLOCK_TPINDEX() _PR_INTSON(_is)
-#else
-static PRLock *_pr_threadPrivateIndexLock;
-#define _PR_NEW_LOCK_TPINDEX() (_pr_threadPrivateIndexLock = PR_NewLock())
-#define _PR_FREE_LOCK_TPINDEX() (PR_DestroyLock(_pr_threadPrivateIndexLock))
-#define _PR_LOCK_TPINDEX() PR_Lock(_pr_threadPrivateIndexLock)
-#define _PR_UNLOCK_TPINDEX() PR_Unlock(_pr_threadPrivateIndexLock)
-#endif
-#endif
/*
** Initialize the thread private data manipulation
*/
void _PR_InitTPD()
{
- _PR_NEW_LOCK_TPINDEX();
+ _pr_tpd_destructors = (PRThreadPrivateDTOR*)
+ PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));
+ PR_ASSERT(NULL != _pr_tpd_destructors);
+ _pr_tpd_length = _PR_TPD_LIMIT;
}
/*
@@ -85,8 +69,7 @@ void _PR_InitTPD()
*/
void _PR_CleanupTPD(void)
{
- _PR_FREE_LOCK_TPINDEX();
-}
+} /* _PR_CleanupTPD */
/*
** This routine returns a new index for per-thread-private data table.
@@ -101,8 +84,8 @@ void _PR_CleanupTPD(void)
** is NULL, and upon thread creation the value associated with all indices for
** that thread is NULL.
**
-** "dtor" is the destructor function to invoke when the private
-** data is destroyed
+** "dtor" is the destructor function to invoke when the private
+** data is destroyed
**
** Returns PR_FAILURE if the total number of indices will exceed the maximun
** allowed.
@@ -112,49 +95,24 @@ PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
PRUintn *newIndex, PRThreadPrivateDTOR dtor)
{
PRStatus rv;
+ PRInt32 index;
if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_ASSERT(NULL != newIndex);
+ PR_ASSERT(NULL != _pr_tpd_destructors);
- if (_pr_tpd_highwater >= _PR_TPD_LIMIT)
+ index = PR_AtomicIncrement(&_pr_tpd_highwater); /* allocate index */
+ if (_PR_TPD_LIMIT < index)
{
PR_SetError(PR_TPD_RANGE_ERROR, 0);
- rv = PR_FAILURE; /* that's just wrong */
+ rv = PR_FAILURE; /* that's just wrong */
}
else
{
- PRThreadPrivateDTOR *old = NULL;
- PRIntn _is;
-
- _PR_LOCK_TPINDEX();
- if (_pr_tpd_highwater >= _pr_tpd_length)
- {
- old = _pr_tpd_destructors;
- _pr_tpd_destructors = PR_CALLOC(
- (_pr_tpd_length + _PR_TPD_MODULO) * sizeof(PRThreadPrivateDTOR*));
- if (NULL == _pr_tpd_destructors)
- {
- _pr_tpd_destructors = old; old = NULL;
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- rv = PR_FAILURE; /* that's just wrong */
- goto failed; /* then extract one's self */
- }
- else
- {
- memcpy(
- _pr_tpd_destructors, old,
- _pr_tpd_length * sizeof(PRThreadPrivateDTOR*));
- _pr_tpd_length += _PR_TPD_MODULO;
- }
- }
-
- *newIndex = _pr_tpd_highwater++; /* this is really all we wanted */
- _pr_tpd_destructors[*newIndex] = dtor; /* record destructor @index */
-
-failed:
- _PR_UNLOCK_TPINDEX();
- if (NULL != old) PR_DELETE(old);
- rv = PR_SUCCESS;
+ _pr_tpd_destructors[index] = dtor; /* record destructor @index */
+ *newIndex = (PRIntn)index; /* copy into client's location */
+ rv = PR_SUCCESS; /* that's okay */
}
return rv;
@@ -162,8 +120,8 @@ failed:
/*
** Define some per-thread-private data.
-** "index" is an index into the per-thread private data table
-** "priv" is the per-thread-private data
+** "index" is an index into the per-thread private data table
+** "priv" is the per-thread-private data
**
** If the per-thread private data table has a previously registered
** destructor function and a non-NULL per-thread-private data value,
@@ -173,9 +131,10 @@ failed:
** high water mark) or memory is insufficient to allocate an exanded vector.
*/
-PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
+PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn his, void *priv)
{
PRStatus rv = PR_SUCCESS;
+ PRInt32 index = (PRInt32)his;
PRThread *self = PR_GetCurrentThread();
/*
@@ -183,17 +142,13 @@ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
** thread. But if the index has been allocated, it's okay to go
** ahead and extend this one now.
*/
- if (index >= _pr_tpd_highwater)
+ if (index > _pr_tpd_highwater)
{
- PR_ASSERT(index < _pr_tpd_highwater);
PR_SetError(PR_TPD_RANGE_ERROR, 0);
- rv = PR_FAILURE;
+ rv = PR_FAILURE;
}
else
{
- PRIntn _is;
-
- _PR_LOCK_TPINDEX();
if ((NULL == self->privateData) || (self->tpdLength <= index))
{
void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*));
@@ -206,7 +161,7 @@ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
extension, self->privateData,
self->tpdLength * sizeof(void*));
self->tpdLength = _pr_tpd_length;
- self->privateData = extension;
+ self->privateData = (void**)extension;
}
}
/*
@@ -217,9 +172,7 @@ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
{
void *data = self->privateData[index];
self->privateData[index] = NULL;
- _PR_UNLOCK_TPINDEX();
- (*_pr_tpd_destructors[index])(data);
- _PR_LOCK_TPINDEX();
+ (*_pr_tpd_destructors[index])(data);
}
/*
@@ -232,10 +185,9 @@ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
rv = PR_FAILURE;
}
else self->privateData[index] = priv;
- _PR_UNLOCK_TPINDEX();
- }
+ }
- return rv;
+ return rv;
}
/*
@@ -247,8 +199,9 @@ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
**
*/
-PR_IMPLEMENT(void*) PR_GetThreadPrivate(uintn index)
+PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn his)
{
+ PRInt32 index = (PRInt32)his;
PRThread *self = PR_GetCurrentThread();
void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ?
NULL : self->privateData[index];
@@ -256,24 +209,57 @@ PR_IMPLEMENT(void*) PR_GetThreadPrivate(uintn index)
return tpd;
}
+/*
+** Destroy the thread's private data, if any exists. This is called at
+** thread termination time only. There should be no threading issues
+** since this is being called by the thread itself.
+*/
+void _PR_DestroyThreadPrivate(PRThread* self)
+{
+ if (NULL != self->privateData) /* we have some */
+ {
+ PRBool clean = PR_TRUE;
+ PRInt32 index, passes = 4;
+ PR_ASSERT(0 != self->tpdLength);
+ do
+ {
+ for (index = 0; index < self->tpdLength; ++index)
+ {
+ void *priv = self->privateData[index]; /* extract */
+ if (NULL != priv) /* we have data at this index */
+ {
+ if (NULL != _pr_tpd_destructors[index])
+ {
+ self->privateData[index] = NULL; /* precondition */
+ (*_pr_tpd_destructors[index])(priv); /* destroy */
+ clean = PR_FALSE; /* unknown side effects */
+ }
+ }
+ }
+ } while ((passes-- > 0) && !clean); /* limit # of passes */
+ PR_DELETE(self->privateData); /* that's just this thread's vector */
+ }
+} /* _PR_DestroyThreadPrivate */
+
+#if 0
PR_IMPLEMENT(PRStatus) PR_SetThreadExit(PRUintn index, PRThreadExit func, void *arg)
{
_PRPerThreadExit *pte;
PRThread *thread = _PR_MD_CURRENT_THREAD();
if (index >= thread->numExits) {
- if (thread->ptes) {
- thread->ptes = (_PRPerThreadExit*)
- PR_REALLOC(thread->ptes, (index+1) * sizeof(_PRPerThreadExit));
- } else {
- thread->ptes = (_PRPerThreadExit*)
- PR_CALLOC(index+1 * sizeof(_PRPerThreadExit));
- }
- if (!thread->ptes) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return PR_FAILURE;
- }
- thread->numExits = index + 1;
+ if (thread->ptes) {
+ thread->ptes = (_PRPerThreadExit*)
+ PR_REALLOC(thread->ptes, (index+1) * sizeof(_PRPerThreadExit));
+ } else {
+ thread->ptes = (_PRPerThreadExit*)
+ PR_CALLOC(index+1 * sizeof(_PRPerThreadExit));
+ }
+ if (!thread->ptes) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_FAILURE;
+ }
+ thread->numExits = index + 1;
}
pte = &thread->ptes[index];
pte->func = func;
@@ -287,10 +273,12 @@ PR_IMPLEMENT(PRThreadExit) PR_GetThreadExit(PRUintn index, void **argp)
PRThread *thread = _PR_MD_CURRENT_THREAD();
if (index >= thread->numExits) {
- if (argp) *argp = 0;
- return 0;
+ if (argp) *argp = 0;
+ return 0;
}
pte = &thread->ptes[index];
if (argp) *argp = pte->arg;
return pte->func;
}
+
+#endif
diff --git a/pr/tests/Makefile b/pr/tests/Makefile
index 9db675f9..d1fc8afd 100644
--- a/pr/tests/Makefile
+++ b/pr/tests/Makefile
@@ -37,6 +37,7 @@ OS_CFLAGS = $(OS_EXE_CFLAGS)
endif
CSRCS = \
+ acceptread.c \
accept.c \
alarm.c \
atomic.c \
@@ -52,11 +53,14 @@ CSRCS = \
dtoa.c \
exit.c \
fileio.c \
+ foreign.c \
forktest.c \
fsync.c \
getproto.c \
i2l.c \
+ initclk.c \
inrval.c \
+ instrumt.c \
intrupt.c \
io_timeout.c \
ipv6.c \
@@ -86,9 +90,11 @@ CSRCS = \
poll_er.c \
poll_nm.c \
poll_to.c \
+ pollable.c \
prftest1.c \
prftest2.c \
priotest.c \
+ provider.c \
ranfile.c \
sel_spd.c \
selct_er.c \
@@ -106,6 +112,7 @@ CSRCS = \
sprintf.c \
sproc_ch.c \
sproc_p.c \
+ stack.c \
stdio.c \
strod.c \
suspend.c \
@@ -120,6 +127,7 @@ CSRCS = \
tmoacc.c \
tmocon.c \
tpd.c \
+ version.c \
udpsrv.c \
writev.c \
xnotify.c \
@@ -133,7 +141,7 @@ endif
PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
-TARGETS = $(PROGS) $(OBJS)
+TARGETS = $(PROGS)
INCLUDES = -I$(DIST)/include/obsolete -I$(DIST)/include/private -I$(DIST)/include
@@ -165,96 +173,112 @@ PWD = $(shell pwd)
endif
ifeq ($(OS_ARCH), IRIX)
-LDOPTS += -rpath $(PWD)/$(DIST)/lib -rdata_shared
-
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -rpath $(PWD)/$(DIST)/lib -rdata_shared
# For 6.x machines, include this flag
-ifeq ($(basename $(OS_RELEASE)),6)
-ifeq ($(USE_N32),1)
-LDOPTS += -n32
-else
-LDOPTS += -32
-endif
-endif
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifeq ($(USE_N32),1)
+ LDOPTS += -n32
+ else
+ LDOPTS += -32
+ endif
+ ifeq ($(USE_PTHREADS), 1)
+ ifeq ($(OS_RELEASE), 6.2)
+ LDOPTS += -Wl,-woff,85
+ endif
+ endif
+ endif
endif
ifeq ($(OS_ARCH), OSF1)
+ ifeq ($(USE_CPLUS), 1)
+ CC = cxx
+ endif
# I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so
# we do static linking.
-ifeq ($(OS_RELEASE), V3.2)
- LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
- LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
- EXTRA_LIBS = -lc_r
-else
- LDOPTS += -rpath $(PWD)/$(DIST)/lib
-endif
+ ifeq ($(OS_RELEASE), V3.2)
+ LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
+ LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
+ EXTRA_LIBS = -lc_r
+ else
+ LDOPTS += -rpath $(PWD)/$(DIST)/lib
+ endif
endif
ifeq ($(OS_ARCH), HP-UX)
-LDOPTS += -Wl,+s,+b,$(PWD)/$(DIST)/lib
+ LDOPTS += -z -Wl,+s,+b,$(PWD)/$(DIST)/lib
+ ifeq ($(USE_64),1)
+ LDOPTS += -L/usr/lib/pa20_64 -lpthread +DD64
+ endif
endif
# AIX
ifeq ($(OS_ARCH),AIX)
-ifeq ($(CLASSIC_NSPR),1)
-LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lpp/xlC/lib:/usr/lib:/lib
-else
-LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib
-endif
-ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
-LIBPR = -lnspr$(MOD_VERSION)_shr
-LIBPLC = -lplc$(MOD_VERSION)_shr
-else
-LDOPTS += -brtl
-EXTRA_LIBS = -ldl
-endif
+ ifeq ($(CLASSIC_NSPR),1)
+ LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lpp/xlC/lib:/usr/lib:/lib
+ else
+ LDOPTS += -blibpath:.:$(PWD)/$(DIST)/lib:/usr/lib/threads:/usr/lpp/xlC/lib:/usr/lib:/lib
+ endif
+ ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+ LIBPR = -lnspr$(MOD_VERSION)_shr
+ LIBPLC = -lplc$(MOD_VERSION)_shr
+ else
+ LDOPTS += -brtl
+ EXTRA_LIBS = -ldl
+ endif
endif
# Solaris
ifeq ($(OS_ARCH), SunOS)
-ifneq ($(OS_RELEASE), 4.1.3_U1)
-ifdef NS_USE_GCC
-LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(DIST)/lib
-else
-LDOPTS += -R $(PWD)/$(DIST)/lib
-endif
-endif
-
-ifneq ($(LOCAL_THREADS_ONLY),1)
+ ifneq ($(OS_RELEASE), 4.1.3_U1)
+ ifdef NS_USE_GCC
+ LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(DIST)/lib
+ else
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -R $(PWD)/$(DIST)/lib
+ endif
+ endif
+
+ ifneq ($(LOCAL_THREADS_ONLY),1)
# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
# even though we already linked with these system libraries
# when we built libnspr.so.
-ifeq ($(OS_RELEASE), 5.4)
-EXTRA_LIBS = -lthread
-endif
-
-ifeq ($(OS_RELEASE), 5.5)
-ifdef USE_PTHREADS
-EXTRA_LIBS = -lpthread
-else
-EXTRA_LIBS = -lthread
-endif
-endif
-endif # LOCAL_THREADS_ONLY
+ ifeq ($(OS_RELEASE), 5.4)
+ EXTRA_LIBS = -lthread
+ endif
+
+ ifeq ($(OS_RELEASE), 5.5)
+ ifdef USE_PTHREADS
+ EXTRA_LIBS = -lpthread
+ else
+ EXTRA_LIBS = -lthread
+ endif
+ endif
+ endif # LOCAL_THREADS_ONLY
endif # SunOS
ifeq ($(OS_ARCH), NEC)
-EXTRA_LIBS = $(OS_LIBS)
+ EXTRA_LIBS = $(OS_LIBS)
# This hardcodes in the executable programs the directory to find
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
-export LD_RUN_PATH = $(PWD)/$(DIST)/lib
+ export LD_RUN_PATH = $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH), NCR)
# NCR needs to link against -lsocket -lnsl -ldl (and -lc, which is
# linked implicitly by $(CC)). Note that we did not link with these
# system libraries when we built libnspr.so.
-EXTRA_LIBS = -lsocket -lnsl -ldl
+ EXTRA_LIBS = -lsocket -lnsl -ldl
# This hardcodes in the executable programs the directory to find
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
-export LD_RUN_PATH = $(PWD)/$(DIST)/lib
+ export LD_RUN_PATH = $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH), NEWS-OS)
@@ -262,20 +286,20 @@ ifeq ($(OS_ARCH), NEWS-OS)
# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
# option for ld on other platforms.
#export LD_RUN_PATH = $(PWD)/$(DIST)/lib
- LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
- LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
- EXTRA_LIBS = -lsocket -lnsl -lgen -lresolv
+ LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).a
+ LIBPLC = $(DIST)/lib/libplc$(MOD_VERSION).a
+ EXTRA_LIBS = -lsocket -lnsl -lgen -lresolv
endif
ifeq ($(OS_ARCH), Linux)
-ifeq ($(OS_RELEASE), 1.2)
-EXTRA_LIBS = -ldl
-else
-LDOPTS += -Xlinker -rpath $(PWD)/$(DIST)/lib
-ifeq ($(USE_PTHREADS),1)
-EXTRA_LIBS = -lpthread
-endif
-endif
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(PWD)/$(DIST)/lib
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
endif
ifeq ($(OS_ARCH), SCOOS)
@@ -304,12 +328,29 @@ ifeq ($(OS_ARCH),FreeBSD)
ifeq ($(USE_PTHREADS),1)
EXTRA_LIBS = -lc_r
endif
+LDOPTS += -Xlinker -R $(PWD)/$(DIST)/lib
endif
ifeq ($(OS_ARCH),BSD_OS)
EXTRA_LIBS = -ldl
endif
+ifeq ($(USE_PTHREADS),1)
+ifeq ($(OS_ARCH),AIX)
+LIBPTHREAD = -lpthreads
+else
+ ifeq ($(OS_ARCH),FreeBSD)
+ LIBPTHREAD = -lc_r
+ else
+ ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10)
+ LIBPTHREAD = -ldce
+ else
+ LIBPTHREAD = -lpthread
+ endif
+ endif
+endif
+endif
+
#####################################################
#
# The rules
@@ -352,15 +393,7 @@ else
ifeq ($(USE_PTHREADS), 1)
$(OBJDIR)/attach: $(OBJDIR)/attach.$(OBJ_SUFFIX)
@$(MAKE_OBJDIR)
-ifeq ($(OS_ARCH), AIX)
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lpthreads -o $@
-else
-ifeq ($(OS_ARCH),FreeBSD)
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lc_r -o $@
-else
- $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) -lpthread -o $@
-endif
-endif
+ $(CC) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) -o $@
endif
@@ -400,6 +433,13 @@ install:: export
clean::
rm -f $(TARGETS)
+ifeq ($(USE_PTHREADS), 1)
+$(OBJDIR)/foreign: $(OBJDIR)/foreign.o
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) $(LIBPTHREAD) -o $@
+$(OBJDIR)/provider: $(OBJDIR)/provider.o
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) $(LIBPTHREAD) -o $@
+endif
+
#
# Run the test programs with no arguments
#
diff --git a/pr/tests/accept.c b/pr/tests/accept.c
index 79ab811f..5318de74 100644
--- a/pr/tests/accept.c
+++ b/pr/tests/accept.c
@@ -48,12 +48,6 @@
#include "plgetopt.h"
#include "plerror.h"
-#ifdef XP_MAC
-#include "prlog.h"
-#define printf PR_LogPrint
-extern void SetupMacPrintfLog(char *logFile);
-#endif
-
#define BASE_PORT 8001
#define CLIENT_DATA 128
@@ -76,6 +70,7 @@ extern void SetupMacPrintfLog(char *logFile);
PRIntervalTime timeoutTime;
static PRInt32 count = 1;
+static PRFileDesc *output;
static PRNetAddr serverAddr;
static PRThreadScope thread_scope = PR_LOCAL_THREAD;
@@ -86,13 +81,8 @@ void Test_Assert(const char *msg, const char *file, PRIntn line)
{
failed_already=1;
if (debug_mode) {
-#if defined(WIN16)
- printf( "@%s:%d ", file, line);
- printf(msg);
-#else
- PR_fprintf(PR_STDERR, "@%s:%d ", file, line);
- PL_FPrintError(PR_STDERR, msg);
-#endif
+ PR_fprintf(output, "@%s:%d ", file, line);
+ PR_fprintf(output, msg);
}
} /* Test_Assert */
@@ -106,7 +96,7 @@ void timeout_callback(void *magic)
{
TEST_ASSERT(magic == (void *)CALLBACK_MAGIC);
if (debug_mode)
- printf("timeout callback called okay\n");
+ PR_fprintf(output, "timeout callback called okay\n");
}
#endif
@@ -131,7 +121,7 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf("client: unable to create socket\n");
+ PR_fprintf(output, "client: unable to create socket\n");
return;
}
@@ -142,10 +132,9 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf(
+ PR_fprintf(output,
"client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
- iterations, rv, PR_GetError(),
- PR_GetOSError());
+ iterations, rv, PR_GetError(), PR_GetOSError());
goto ErrorExit;
}
@@ -155,25 +144,24 @@ ClientThread(void *_action)
if (!debug_mode)
failed_already=1;
else
- printf("client: unable to send to server (%d, %ld, %ld)\n",
- CLIENT_DATA, rv,
- PR_GetError());
+ PR_fprintf(output,
+ "client: unable to send to server (%d, %ld, %ld)\n",
+ CLIENT_DATA, rv, PR_GetError());
goto ErrorExit;
}
} else {
- PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
- 1));
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
}
} else {
- PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS+
- 1));
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
}
if (debug_mode)
- printf(".");
+ PR_fprintf(output, ".");
PR_Close(sock);
+ sock = NULL;
}
if (debug_mode)
- printf("\n");
+ PR_fprintf(output, "\n");
ErrorExit:
if (sock != NULL)
@@ -203,7 +191,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (!listenSock) {
failed_already=1;
if (debug_mode)
- printf("unable to create listen socket\n");
+ PR_fprintf(output, "unable to create listen socket\n");
return;
}
listenAddr.inet.family = PR_AF_INET;
@@ -213,7 +201,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (rv == PR_FAILURE) {
failed_already=1;
if (debug_mode)
- printf("unable to bind\n");
+ PR_fprintf(output, "unable to bind\n");
return;
}
@@ -221,7 +209,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (rv == PR_FAILURE) {
failed_already=1;
if (debug_mode)
- printf("unable to listen\n");
+ PR_fprintf(output, "unable to listen\n");
return;
}
@@ -232,7 +220,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
if (!clientThread) {
failed_already=1;
if (debug_mode)
- printf("error creating client thread\n");
+ PR_fprintf(output, "error creating client thread\n");
return;
}
@@ -288,8 +276,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
case CLIENT_TIMEOUT_ACCEPT:
TEST_ASSERT(clientSock == 0);
if (debug_mode)
- printf("PR_GetError is %ld\n",
- PR_GetError());
+ PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError());
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
break;
case CLIENT_NORMAL:
@@ -342,8 +329,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
break;
case CLIENT_TIMEOUT_SEND:
if (debug_mode)
- printf("clientSock = 0x%8.8lx\n",
- clientSock);
+ PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
TEST_ASSERT(clientSock);
TEST_ASSERT(status == -1);
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
@@ -431,7 +417,7 @@ static void Measure(void (*func)(void), const char *msg)
d = (double)PR_IntervalToMicroseconds(stop - start);
if (debug_mode)
- printf("%40s: %6.2f usec\n", msg, d / count);
+ PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count);
}
@@ -467,6 +453,7 @@ int main(int argc, char **argv)
PL_DestroyOptState(opt);
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ output = PR_STDERR;
PR_STDIO_INIT();
#ifdef XP_MAC
@@ -476,7 +463,7 @@ int main(int argc, char **argv)
timeoutTime = PR_SecondsToInterval(TIMEOUTSECS);
if (debug_mode)
- printf("\nRun accept() sucessful connection tests\n");
+ PR_fprintf(output, "\nRun accept() sucessful connection tests\n");
Measure(AcceptUpdatedTest, "PR_Accept()");
Measure(AcceptReadTest, "PR_AcceptRead()");
@@ -486,28 +473,19 @@ int main(int argc, char **argv)
Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
if (debug_mode)
- printf("\nRun accept() timeout in the accept tests\n");
+ PR_fprintf(output, "\nRun accept() timeout in the accept tests\n");
#ifdef WINNT
Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
Measure(TimeoutReadUpdatedTest, "PR_Accept()");
if (debug_mode)
- printf("\nRun accept() timeout in the read tests\n");
+ PR_fprintf(output, "\nRun accept() timeout in the read tests\n");
Measure(TimeoutReadReadTest, "PR_AcceptRead()");
#ifdef WINNT
Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
#endif
- if(failed_already)
- {
- printf("FAIL\n");
- return 1;
- }
- else
- {
- printf("PASS\n");
- return 0;
-
- }
+ PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS");
+ return failed_already;
}
diff --git a/pr/tests/atomic.c b/pr/tests/atomic.c
index d5e334d5..a2ba2044 100644
--- a/pr/tests/atomic.c
+++ b/pr/tests/atomic.c
@@ -22,7 +22,7 @@
PRIntn main(PRIntn argc, char **argv)
{
- PRInt32 rv, test, result = 0;
+ PRInt32 rv, oldval, test, result = 0;
PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);
test = -2;
@@ -42,6 +42,25 @@ PRIntn main(PRIntn argc, char **argv)
output, "PR_AtomicIncrement(%d) == %d: %s\n",
test, rv, (rv > 0) ? "PASSED" : "FAILED");
+ oldval = test = -2;
+ rv = PR_AtomicAdd(&test,1);
+ result = result | ((rv == -1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, 4);
+ result = result | ((rv == 3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, -6);
+ result = result | ((rv == -3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED");
+
test = 2;
rv = PR_AtomicDecrement(&test);
result = result | ((rv > 0) ? 0 : 1);
diff --git a/pr/tests/attach.c b/pr/tests/attach.c
index 3fa38d49..79a5d3d8 100644
--- a/pr/tests/attach.c
+++ b/pr/tests/attach.c
@@ -66,7 +66,7 @@
#include <os2.h>
#endif
-#define DEFAULT_COUNT 10000
+#define DEFAULT_COUNT 1000
PRIntn failed_already=0;
PRIntn debug_mode;
@@ -81,21 +81,17 @@ AttachDetach(void)
PRInt32 index;
for (index=0;index<count; index++) {
-
me = PR_AttachThread(PR_USER_THREAD,
PR_PRIORITY_NORMAL,
NULL);
if (!me) {
- fprintf(stderr, "Error attaching thread %d: "
- "nspr20 error code %d, os error code %d\n",
- count, PR_GetError(), PR_GetOSError());
- failed_already = 1;
- return;
+ fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n",
+ count);
+ failed_already = 1;
+ return;
}
-
PR_DetachThread();
-
}
}
@@ -277,7 +273,7 @@ int main(int argc, char **argv)
}
rv = WaitForSingleObject(hThread, INFINITE);
if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
- else if (rv != WAIT_FAILED) {
+ else if (rv == WAIT_FAILED) {
failed_already=1;
goto exit_now;
}
@@ -296,6 +292,7 @@ int main(int argc, char **argv)
else {
if (debug_mode)
printf ("thread creation succeeded \n");
+ sleep(3);
goto exit_now;
}
rv = waitpid(threadID, NULL, 0);
diff --git a/pr/tests/bigfile.c b/pr/tests/bigfile.c
index 9cb4e7fd..399da8cd 100644
--- a/pr/tests/bigfile.c
+++ b/pr/tests/bigfile.c
@@ -35,10 +35,10 @@ static void Verbose(Verbosity, const char*, const char*, PRIntn);
#define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__)
-static PRIntn filesize = 1;
static PRIntn test_result = 2;
static PRFileDesc *output = NULL;
static PRIntn verbose = v_silent;
+static PRIntn filesize = DEFAULT_FILESIZE;
static PRIntn Usage(void)
{
@@ -46,6 +46,7 @@ static PRIntn Usage(void)
PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s <n>] <filename>\n");
PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n");
PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n");
+ PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n");
PR_fprintf(output, "\ts <n>\tFile size in megabytes\t\t(1 megabyte)\n");
PR_fprintf(output, "\t<filename>\tName of test file\t(none)\n");
return 2; /* nothing happened */
@@ -64,6 +65,7 @@ static PRStatus DeleteIfFound(const char *filename)
}
else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError())
VERBOSE(v_shout, "Cannot access big file");
+ else rv = PR_SUCCESS;
return rv;
} /* DeleteIfFound */
@@ -87,20 +89,43 @@ static void Verbose(
PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg);
} /* Verbose */
+static void PrintInfo(PRFileInfo64 *info, const char *filename)
+{
+ PRExplodedTime tm;
+ char ctime[40], mtime[40];
+ static const char *types[] = {"FILE", "DIRECTORY", "OTHER"};
+ PR_fprintf(
+ output, "[%s : %d]: File info for %s\n",
+ __FILE__, __LINE__, filename);
+ PR_fprintf(
+ output, " type: %s, size: %llu bytes,\n",
+ types[info->type - 1], info->size);
+
+ PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm);
+ PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm);
+
+ PR_fprintf(
+ output, " creation: %s,\n modify: %s\n", ctime, mtime);
+} /* PrintInfo */
+
PRIntn main(PRIntn argc, char **argv)
{
PRStatus rv;
char *buffer;
PLOptStatus os;
PRInt32 loop, bytes;
+ PRFileInfo small_info;
+ PRFileInfo64 big_info;
+ PRBool keep = PR_FALSE;
PRFileDesc *file = NULL;
const char *filename = NULL;
PRIntn count = DEFAULT_COUNT;
- PRFileInfo64 *big_info = NULL;
- PRInt64 big_answer, big_size, one_meg, zero_meg, big_fragment;
- PRInt64 filesize64;
+ PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment;
+ PRInt64 sevenFox = LL_INIT(0,0x7fffffff);
- PLOptState *opt = PL_CreateOptState(argc, argv, "dvhs:");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:");
output = PR_GetSpecialFD(PR_StandardError);
PR_STDIO_INIT();
@@ -116,6 +141,9 @@ PRIntn main(PRIntn argc, char **argv)
case 'd': /* debug mode */
verbose = v_shout;
break;
+ case 'k': /* keep file */
+ keep = PR_TRUE;
+ break;
case 'v': /* verbosity */
if (v_shout > verbose) verbose += 1;
break;
@@ -132,9 +160,13 @@ PRIntn main(PRIntn argc, char **argv)
}
PL_DestroyOptState(opt);
- if (NULL == filename) return Usage();
if (0 == count) count = DEFAULT_COUNT;
if (0 == filesize) filesize = DEFAULT_FILESIZE;
+ if (NULL == filename)
+ {
+ if (DEFAULT_FILESIZE != filesize) return Usage();
+ else filename = "/usr/tmp/bigfile.dat";
+ }
if (PR_FAILURE == DeleteIfFound(filename)) return 1;
@@ -145,7 +177,7 @@ PRIntn main(PRIntn argc, char **argv)
LL_I2L(filesize64, filesize);
buffer = (char*)PR_MALLOC(BUFFER_SIZE);
LL_I2L(big_fragment, BUFFER_SIZE);
- LL_MUL(big_size, filesize64, one_meg);
+ LL_MUL(filesize64, filesize64, one_meg);
for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop;
@@ -157,32 +189,45 @@ PRIntn main(PRIntn argc, char **argv)
big_answer = file->methods->available64(file);
if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename);
-#if 0
- VERBOSE(v_whisper, "Filling big file with data");
- while (LL_CMP(big_answer, <, big_size))
- {
- bytes = file->methods->write(file, buffer, BUFFER_SIZE);
- if (bytes != BUFFER_SIZE) return Error("write", filename);
- LL_ADD(big_answer, big_answer, big_fragment);
- }
-#else
- LL_SUB(big_size, big_size, one_meg);
+ LL_SUB(big_size, filesize64, one_meg);
+ VERBOSE(v_whisper, "Creating sparce big file by seeking to end");
big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
+ if (!LL_EQ(big_answer, big_size)) return Error("seek", filename);
+
+ VERBOSE(v_whisper, "Writing block at end of sparce file");
bytes = file->methods->write(file, buffer, BUFFER_SIZE);
if (bytes != BUFFER_SIZE) return Error("write", filename);
-#endif
- VERBOSE(v_whisper, "Testing available space in filled file");
+ VERBOSE(v_whisper, "Testing available space at end of sparce file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, zero_meg)) return Error("eof available64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename);
+
+ VERBOSE(v_whisper, "Getting big info on sparce big file");
+ rv = file->methods->fileInfo64(file, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
+ VERBOSE(v_whisper, "Getting small info on sparce big file");
+ rv = file->methods->fileInfo(file, &small_info);
+ if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv))
+ {
+ VERBOSE(v_whisper, "Should have failed and didn't");
+ return Error("fileInfo()", filename);
+ }
+ else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv))
+ {
+ VERBOSE(v_whisper, "Should have succeeded and didn't");
+ return Error("fileInfo()", filename);
+ }
VERBOSE(v_whisper, "Rewinding big file");
big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
- if (LL_NE(big_answer, zero_meg)) return Error("rewind seek64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename);
VERBOSE(v_whisper, "Establishing available space in rewound file");
- big_size = file->methods->available64(file);
- if (!LL_GE_ZERO(big_size)) return Error("bof available64()", filename);
+ big_answer = file->methods->available64(file);
+ if (LL_NE(filesize64, big_answer))
+ return Error("bof available64()", filename);
VERBOSE(v_whisper, "Closing big file");
rv = file->methods->close(file);
@@ -190,47 +235,59 @@ PRIntn main(PRIntn argc, char **argv)
VERBOSE(v_whisper, "Reopening big file");
file = PR_Open(filename, PR_RDWR, 0666);
- if (NULL == file) return Error("bof seek64()", filename);
+ if (NULL == file) return Error("open failed", filename);
VERBOSE(v_whisper, "Checking available data in reopened file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_size, big_answer)) return Error("reopened available64()", filename);
+ if (LL_NE(filesize64, big_answer))
+ return Error("reopened available64()", filename);
big_answer = zero_meg;
- VERBOSE(v_whisper, "Rewriting big file data");
- while (LL_CMP(big_answer, <, big_size))
+ VERBOSE(v_whisper, "Rewriting every byte of big file data");
+ do
{
bytes = file->methods->write(file, buffer, BUFFER_SIZE);
- if (bytes != BUFFER_SIZE) return Error("write", filename);
+ if (bytes != BUFFER_SIZE)
+ return Error("write", filename);
LL_ADD(big_answer, big_answer, big_fragment);
- }
+ } while (LL_CMP(big_answer, <, filesize64));
+
+ VERBOSE(v_whisper, "Checking position at eof");
+ big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR);
+ if (LL_NE(big_answer, filesize64))
+ return Error("file size error", filename);
VERBOSE(v_whisper, "Testing available space at eof");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, zero_meg)) return Error("eof available64()", filename);
+ if (!LL_IS_ZERO(big_answer))
+ return Error("eof available64()", filename);
- VERBOSE(v_whisper, "Rewinding full file file");
+ VERBOSE(v_whisper, "Rewinding full file");
big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
- if (LL_NE(big_answer, zero_meg)) return Error("bof seek64()", filename);
+ if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename);
VERBOSE(v_whisper, "Testing available space in rewound file");
big_answer = file->methods->available64(file);
- if (LL_NE(big_answer, big_size)) return Error("bof available64()", filename);
+ if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename);
VERBOSE(v_whisper, "Seeking to end of big file");
- big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
- if (LL_NE(big_answer, big_size)) return Error("eof seek64()", filename);
+ big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET);
+ if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename);
- VERBOSE(v_whisper, "Getting info on big file");
- big_info = PR_NEWZAP(PRFileInfo64);
- rv = file->methods->fileInfo64(file, big_info);
+ VERBOSE(v_whisper, "Getting info on big file while it's open");
+ rv = file->methods->fileInfo64(file, &big_info);
if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
- PR_DELETE(big_info);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
VERBOSE(v_whisper, "Closing big file");
rv = file->methods->close(file);
if (PR_FAILURE == rv) return Error("close()", filename);
+ VERBOSE(v_whisper, "Getting info on big file after it's closed");
+ rv = PR_GetFileInfo64(filename, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
VERBOSE(v_whisper, "Deleting big file");
rv = PR_Delete(filename);
if (PR_FAILURE == rv) return Error("PR_Delete()", filename);
diff --git a/pr/tests/cltsrv.c b/pr/tests/cltsrv.c
index 346ff2f9..f3333be4 100644
--- a/pr/tests/cltsrv.c
+++ b/pr/tests/cltsrv.c
@@ -79,6 +79,8 @@
#define RECV_FLAGS 0
#define SEND_FLAGS 0
+#define DEFAULT_LOW 0
+#define DEFAULT_HIGH 0
#define BUFFER_SIZE 1024
#define DEFAULT_BACKLOG 5
#define DEFAULT_PORT 12848
@@ -204,22 +206,6 @@ static PRBool Aborted(PRStatus rv)
PR_TRUE : PR_FALSE;
}
-static void Assert(const char *s, const char *file, PRIntn ln)
-{
- PRIntn error = PR_GetError(), syserrno = PR_GetOSError();
- TEST_LOG(
- cltsrv_log_file, TEST_LOG_ALWAYS,
- ("Assertion failed(0x%lx): '%s' in %s[%d]\n",
- PR_CurrentThread(), s, file, ln));
- TEST_LOG(
- cltsrv_log_file, TEST_LOG_ALWAYS,
- ("**Error information: Error = %d, OSError = %d\n",
- error, syserrno));
- PR_LogFlush();
-
- PR_Abort();
-} /* Assert */
-
static void TimeOfDayMessage(const char *msg, PRThread* me)
{
char buffer[100];
@@ -229,7 +215,7 @@ static void TimeOfDayMessage(const char *msg, PRThread* me)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("%s(0x%lx): %s\n", msg, me, buffer));
+ ("%s(0x%p): %s\n", msg, me, buffer));
} /* TimeOfDayMessage */
@@ -264,7 +250,7 @@ static void PR_CALLBACK Client(void *arg)
(void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
- ("\tClient(0x%lx): connecting to server at %s\n", me, buffer));
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
fd = PR_Socket(domain, SOCK_STREAM, protocol);
TEST_ASSERT(NULL != fd);
@@ -273,7 +259,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): conection failed\n", me));
+ ("\tClient(0x%p): conection failed\n", me));
goto aborted;
}
@@ -281,10 +267,10 @@ static void PR_CALLBACK Client(void *arg)
descriptor->size = PR_htonl(descbytes = rand() % clipping);
PR_snprintf(
descriptor->filename, sizeof(descriptor->filename),
- "CS%lx%lx-%lx.dat", client->started, me, client->operations);
+ "CS%p%p-%p.dat", client->started, me, client->operations);
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): sending descriptor for %ld bytes\n", me, descbytes));
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
bytes = PR_Send(
fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
if (sizeof(CSDescriptor_t) != bytes)
@@ -294,7 +280,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): send descriptor timeout\n", me));
+ ("\tClient(0x%p): send descriptor timeout\n", me));
goto retry;
}
}
@@ -308,7 +294,7 @@ static void PR_CALLBACK Client(void *arg)
filebytes = descbytes - netbytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): sending %d bytes\n", me, filebytes));
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
if (filebytes != bytes)
{
@@ -317,7 +303,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): send data timeout\n", me));
+ ("\tClient(0x%p): send data timeout\n", me));
goto retry;
}
}
@@ -332,7 +318,7 @@ static void PR_CALLBACK Client(void *arg)
netbytes = descbytes - filebytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tClient(0x%lx): receiving %d bytes\n", me, netbytes));
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
if (-1 == bytes)
{
@@ -340,17 +326,17 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive data aborted\n", me));
+ ("\tClient(0x%p): receive data aborted\n", me));
goto aborted;
}
else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive data timeout\n", me));
+ ("\tClient(0x%p): receive data timeout\n", me));
else
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tClient(0x%lx): receive error (%ld, %ld)\n",
+ ("\tClient(0x%p): receive error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto retry;
}
@@ -358,7 +344,7 @@ static void PR_CALLBACK Client(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tClient(0x%lx): unexpected end of stream\n",
+ ("\t\tClient(0x%p): unexpected end of stream\n",
PR_CurrentThread()));
break;
}
@@ -372,7 +358,7 @@ retry:
(void)PR_Close(fd); fd = NULL;
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("\tClient(0x%lx): disconnected from server\n", me));
+ ("\tClient(0x%p): disconnected from server\n", me));
PR_Lock(client->ml);
client->operations += 1;
@@ -395,7 +381,7 @@ aborted:
PR_DELETE(descriptor);
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("\tClient(0x%lx): stopped after %lu operations and %lu bytes\n",
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
PR_CurrentThread(), client->operations, client->bytesTransferred));
} /* Client */
@@ -412,7 +398,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): receiving desciptor\n", me));
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
bytes = PR_Recv(
fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
if (-1 == bytes)
@@ -423,7 +409,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): receive timeout\n", me));
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
}
goto exit;
}
@@ -432,7 +418,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
rv = PR_FAILURE;
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): unexpected end of file\n", me));
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
goto exit;
}
descbytes = PR_ntohl(descriptor->size);
@@ -440,7 +426,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): read descriptor {%ld, %s}\n",
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
me, descbytes, descriptor->filename));
file = PR_Open(
@@ -453,7 +439,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\tProcessRequest(0x%lx): open file timeout\n", me));
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
goto aborted;
}
}
@@ -467,7 +453,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
netbytes = descbytes - filebytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): receive %d bytes\n", me, netbytes));
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
if (-1 == bytes)
{
@@ -477,7 +463,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): receive data timeout\n", me));
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
goto aborted;
}
/*
@@ -487,7 +473,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
*/
TEST_LOG(
cltsrv_log_file, TEST_LOG_WARNING,
- ("\t\tProcessRequest(0x%lx): unexpected error (%d, %d)\n",
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -495,7 +481,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_WARNING,
- ("\t\tProcessRequest(0x%lx): unexpected end of stream\n", me));
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
rv = PR_FAILURE;
goto aborted;
}
@@ -505,7 +491,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
MY_ASSERT(netbytes > 0);
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): write %d bytes to file\n", me, netbytes));
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
bytes = PR_Write(file, buffer, netbytes);
if (netbytes != bytes)
{
@@ -515,7 +501,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): write file timeout\n", me));
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
goto aborted;
}
}
@@ -533,7 +519,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): opening %s\n", me, descriptor->filename));
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
file = PR_Open(descriptor->filename, PR_RDONLY, 0);
if (NULL == file)
{
@@ -543,13 +529,13 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): open file timeout\n",
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
PR_CurrentThread()));
goto aborted;
}
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): other file open error (%u, %u)\n",
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -563,7 +549,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
filebytes = descbytes - netbytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tProcessRequest(0x%lx): read %d bytes from file\n", me, filebytes));
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
bytes = PR_Read(file, buffer, filebytes);
if (filebytes != bytes)
{
@@ -572,11 +558,11 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
if (PR_IO_TIMEOUT_ERROR == PR_GetError())
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): read file timeout\n", me));
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
else
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): other file error (%d, %d)\n",
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
me, PR_GetError(), PR_GetOSError()));
goto aborted;
}
@@ -585,7 +571,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
filebytes = bytes;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): sending %d bytes\n", me, filebytes));
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
if (filebytes != bytes)
{
@@ -595,7 +581,7 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tProcessRequest(0x%lx): send data timeout\n", me));
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
goto aborted;
}
break;
@@ -622,7 +608,7 @@ aborted:
exit:
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tProcessRequest(0x%lx): Finished\n", me));
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
PR_DELETE(descriptor);
@@ -648,7 +634,7 @@ static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
}
TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
- ("\tCreateWorker(0x%lx): create new worker (0x%lx)\n",
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
PR_CurrentThread(), worker->thread));
return PR_SUCCESS;
@@ -666,7 +652,7 @@ static void PR_CALLBACK Worker(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\t\tWorker(0x%lx): started [%lu]\n", me, pool->workers + 1));
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
PR_Lock(server->ml);
PR_APPEND_LINK(&worker->element, &server->list);
@@ -678,14 +664,14 @@ static void PR_CALLBACK Worker(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tWorker(0x%lx): waiting for accept slot[%d]\n",
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
me, pool->accepting));
rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
if (Aborted(rv) || (cs_run != server->state))
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\tWorker(0x%lx): has been %s\n",
+ ("\tWorker(0x%p): has been %s\n",
me, (Aborted(rv) ? "interrupted" : "stopped")));
goto exit;
}
@@ -695,7 +681,7 @@ static void PR_CALLBACK Worker(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\t\tWorker(0x%lx): calling accept\n", me));
+ ("\t\tWorker(0x%p): calling accept\n", me));
fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
PR_Lock(server->ml);
@@ -736,7 +722,7 @@ static void PR_CALLBACK Worker(void *arg)
if (PR_SUCCESS != rv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ERROR,
- ("\t\tWorker(0x%lx): server process ended abnormally\n", me));
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
(void)PR_Close(fd); fd = NULL;
PR_Lock(server->ml);
@@ -756,7 +742,7 @@ exit:
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\t\tWorker(0x%lx): exiting [%lu]\n", PR_CurrentThread(), pool->workers));
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
PR_Lock(server->ml);
pool->workers -= 1; /* undefine our existance */
@@ -809,7 +795,7 @@ static void PR_CALLBACK Server(void *arg)
*/
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tServer(0x%lx): waiting for state change\n", me));
+ ("\tServer(0x%p): waiting for state change\n", me));
PR_Lock(server->ml);
while ((cs_run == server->state) && !Aborted(rv))
@@ -821,7 +807,7 @@ static void PR_CALLBACK Server(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("\tServer(0x%lx): shutting down workers\n", me));
+ ("\tServer(0x%p): shutting down workers\n", me));
/*
** Get all the worker threads to exit. They know how to
@@ -838,7 +824,7 @@ static void PR_CALLBACK Server(void *arg)
CSWorker_t *worker = (CSWorker_t*)head;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("\tServer(0x%lx): interrupting worker(0x%lx)\n", me, worker));
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
rv = PR_Interrupt(worker->thread);
TEST_ASSERT(PR_SUCCESS == rv);
PR_REMOVE_AND_INIT_LINK(head);
@@ -848,7 +834,7 @@ static void PR_CALLBACK Server(void *arg)
{
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("\tServer(0x%lx): waiting for %lu workers to exit\n",
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
me, server->pool.workers));
(void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
}
@@ -859,7 +845,7 @@ static void PR_CALLBACK Server(void *arg)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("\tServer(0x%lx): stopped after %lu operations and %lu bytes\n",
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
me, server->operations, server->bytesTransferred));
if (NULL != server->listener) PR_Close(server->listener);
@@ -867,26 +853,15 @@ static void PR_CALLBACK Server(void *arg)
} /* Server */
-#if defined(DEBUG) && defined(_PR_PTHREADS)
-static void PrintPthreadStats(void)
-{
- PT_FPrintStats(debug_out, "\nPThread Statistics\n");
-} /* PrintPthreadStats */
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
-
static void WaitForCompletion(PRIntn execution)
{
-#if defined(DEBUG) && defined(_PR_PTHREADS)
while (execution > 0)
{
PRIntn dally = (execution > 30) ? 30 : execution;
PR_Sleep(PR_SecondsToInterval(dally));
- if (pthread_stats) PrintPthreadStats();
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
execution -= dally;
}
-#else
- PR_Sleep(PR_SecondsToInterval(execution));
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
} /* WaitForCompletion */
static void Help(void)
@@ -895,6 +870,8 @@ static void Help(void)
PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-f <low> low water mark for fd caching (0)\n");
+ PR_fprintf(debug_out, "\t-F <high> high water mark for fd caching (0)\n");
PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
@@ -932,12 +909,15 @@ PRIntn main(PRIntn argc, char** argv)
PRUintn workersMin = DEFAULT_WORKERS_MIN;
PRUintn workersMax = DEFAULT_WORKERS_MAX;
PRIntn execution = DEFAULT_EXECUTION_TIME;
+ PRIntn low = DEFAULT_LOW, high = DEFAULT_HIGH;
/*
* -G use global threads
* -a <n> threads allowed in accept
* -b <n> backlock for listen
* -c <threads> number of clients to create
+ * -f <low> low water mark for caching FDs
+ * -F <high> high water mark for caching FDs
* -w <threads> minimal number of server threads
* -W <threads> maximum number of server threads
* -e <seconds> duration of the test in seconds
@@ -946,7 +926,7 @@ PRIntn main(PRIntn argc, char** argv)
*/
PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:vdhp");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:f:F:w:W:e:s:vdhp");
debug_out = PR_GetSpecialFD(PR_StandardError);
@@ -976,6 +956,12 @@ PRIntn main(PRIntn argc, char** argv)
case 'c': /* number of client threads */
clients = atoi(opt->value);
break;
+ case 'f': /* low water fd cache */
+ low = atoi(opt->value);
+ break;
+ case 'F': /* low water fd cache */
+ high = atoi(opt->value);
+ break;
case 'w': /* minimum server worker threads */
workersMin = atoi(opt->value);
break;
@@ -1026,12 +1012,15 @@ PRIntn main(PRIntn argc, char** argv)
debug_mode = PR_TRUE;
#endif
+ rv = PR_SetFDCacheSize(low, high);
+ PR_ASSERT(PR_SUCCESS == rv);
+
if (serverIsLocal)
{
/* Establish the server */
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("main(0x%lx): starting server\n", PR_CurrentThread()));
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
server = PR_NEWZAP(CSServer_t);
PR_INIT_CLIST(&server->list);
@@ -1048,7 +1037,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): creating server thread\n", PR_CurrentThread()));
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
server->thread = PR_CreateThread(
PR_USER_THREAD, Server, server, PR_PRIORITY_HIGH,
@@ -1057,7 +1046,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): waiting for server init\n", PR_CurrentThread()));
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
PR_Lock(server->ml);
while (server->state == cs_init)
@@ -1066,7 +1055,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): server init complete (port #%d)\n",
+ ("main(0x%p): server init complete (port #%d)\n",
PR_CurrentThread(), server->port));
}
@@ -1079,7 +1068,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): creating %d client threads\n",
+ ("main(0x%p): creating %d client threads\n",
PR_CurrentThread(), clients));
if (!serverIsLocal)
@@ -1110,7 +1099,7 @@ PRIntn main(PRIntn argc, char** argv)
client[index].stateChange = PR_NewCondVar(client[index].ml);
TEST_LOG(
cltsrv_log_file, TEST_LOG_INFO,
- ("main(0x%lx): creating client threads\n", PR_CurrentThread()));
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
client[index].thread = PR_CreateThread(
PR_USER_THREAD, Client, &client[index], PR_PRIORITY_NORMAL,
thread_scope, PR_JOINABLE_THREAD, 0);
@@ -1125,7 +1114,7 @@ PRIntn main(PRIntn argc, char** argv)
/* Then just let them go at it for a bit */
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("main(0x%lx): waiting for execution interval (%d seconds)\n",
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
PR_CurrentThread(), execution));
WaitForCompletion(execution);
@@ -1137,7 +1126,7 @@ PRIntn main(PRIntn argc, char** argv)
for (index = 0; index < clients; ++index)
{
TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
- ("main(0x%lx): notifying client(0x%lx) to stop\n",
+ ("main(0x%p): notifying client(0x%p) to stop\n",
PR_CurrentThread(), client[index].thread));
PR_Lock(client[index].ml);
@@ -1152,7 +1141,7 @@ PRIntn main(PRIntn argc, char** argv)
PR_Unlock(client[index].ml);
TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
- ("main(0x%lx): joining client(0x%lx)\n",
+ ("main(0x%p): joining client(0x%p)\n",
PR_CurrentThread(), client[index].thread));
joinStatus = PR_JoinThread(client[index].thread);
@@ -1168,7 +1157,7 @@ PRIntn main(PRIntn argc, char** argv)
/* All clients joined - retrieve the server */
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): notifying server(0x%lx) to stop\n",
+ ("main(0x%p): notifying server(0x%p) to stop\n",
PR_CurrentThread(), server->thread));
PR_Lock(server->ml);
@@ -1180,7 +1169,7 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_NOTICE,
- ("main(0x%lx): joining server(0x%lx)\n",
+ ("main(0x%p): joining server(0x%p)\n",
PR_CurrentThread(), server->thread));
joinStatus = PR_JoinThread(server->thread);
TEST_ASSERT(PR_SUCCESS == joinStatus);
@@ -1194,13 +1183,12 @@ PRIntn main(PRIntn argc, char** argv)
TEST_LOG(
cltsrv_log_file, TEST_LOG_ALWAYS,
- ("main(0x%lx): test complete\n", PR_CurrentThread()));
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
-#if defined(DEBUG) && defined(_PR_PTHREADS)
- PrintPthreadStats();
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
+ PT_FPrintStats(debug_out, "\nPThread Statistics\n");
TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ PR_Cleanup();
return 0;
} /* main */
diff --git a/pr/tests/concur.c b/pr/tests/concur.c
index 88575dd5..fa2bfa1f 100644
--- a/pr/tests/concur.c
+++ b/pr/tests/concur.c
@@ -26,6 +26,8 @@
#include "prinrval.h"
#include "prlock.h"
#include "prprf.h"
+#include "prmem.h"
+#include "prlog.h"
#include "plgetopt.h"
@@ -37,7 +39,7 @@
#include <stdlib.h>
-#define DEFAULT_RANGE 20
+#define DEFAULT_RANGE 10
#define DEFAULT_LOOPS 100
static PRThreadScope thread_scope = PR_LOCAL_THREAD;
@@ -71,8 +73,11 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
{
PRUintn cpus;
PLOptStatus os;
+ PRThread **threads;
PRBool debug = PR_FALSE;
PRUintn range = DEFAULT_RANGE;
+ PRStatus rc;
+ PRUintn cnt;
PRUintn loops = DEFAULT_LOOPS;
PRIntervalTime hundredMills = PR_MillisecondsToInterval(100);
PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:");
@@ -109,16 +114,17 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
PR_fprintf(
PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops);
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range);
while (--loops > 0)
{
- for (cpus = 1; cpus < range; ++cpus)
+ for (cpus = 1; cpus <= range; ++cpus)
{
PR_SetConcurrency(cpus);
context.want = cpus;
- (void)PR_CreateThread(
+ threads[cpus - 1] = PR_CreateThread(
PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL,
- thread_scope, PR_UNJOINABLE_THREAD, 0);
+ thread_scope, PR_JOINABLE_THREAD, 0);
}
PR_Sleep(hundredMills);
@@ -132,6 +138,10 @@ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
PR_NotifyCondVar(context.cv);
PR_Unlock(context.ml);
}
+ for(cnt = 0; cnt < range; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
}
diff --git a/pr/tests/cvar2.c b/pr/tests/cvar2.c
index f6b34268..f2508a7b 100644
--- a/pr/tests/cvar2.c
+++ b/pr/tests/cvar2.c
@@ -35,6 +35,7 @@
***********************************************************************/
#include "nspr.h"
+#include "plerror.h"
#include "plgetopt.h"
#include <stdio.h>
@@ -167,8 +168,8 @@ CreateTestThread(threadinfo *info,
scope,
PR_JOINABLE_THREAD,
0);
- if (!info->thread)
- printf("error creating thread\n");
+ if (!info->thread)
+ PL_PrintError("error creating thread\n");
}
diff --git a/pr/tests/dceemu.c b/pr/tests/dceemu.c
index 7935eae8..cb04cbd6 100644
--- a/pr/tests/dceemu.c
+++ b/pr/tests/dceemu.c
@@ -36,7 +36,7 @@
***********************************************************************/
-#if defined(XP_UNIX)
+#if defined(_PR_DCETHREADS)
#include "prlog.h"
#include "prinit.h"
@@ -93,12 +93,12 @@ static PRIntn prmain(PRIntn argc, char **argv)
} /* prmain */
-#endif /* #if defined(XP_UNIX) */
+#endif /* #if defined(_PR_DCETHREADS) */
int main(int argc, char **argv)
{
-#if defined(XP_UNIX)
+#if defined(_PR_DCETHREADS)
PR_Initialize(prmain, argc, argv, 0);
if(failed_already)
return 1;
diff --git a/pr/tests/dll/Makefile b/pr/tests/dll/Makefile
index 7afc7300..c2f72d71 100644
--- a/pr/tests/dll/Makefile
+++ b/pr/tests/dll/Makefile
@@ -58,7 +58,9 @@ else
TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
endif
else
+ifdef MKSHLIB
SHARED_LIBRARY = $(OBJDIR)/libmy.$(DLL_SUFFIX)
+endif
TARGETS = $(SHARED_LIBRARY)
endif
@@ -81,6 +83,7 @@ OS_DLL_OPTION = NOCASEEXACT
OS_LIB_FLAGS = -irn
endif
+ifdef SHARED_LIBRARY
export:: $(TARGETS)
$(NSINSTALL) $(TARGETS) ../$(OBJDIR)/dll
@@ -88,3 +91,4 @@ install:: export
clean::
rm -rf $(TARGETS)
+endif
diff --git a/pr/tests/dlltest.c b/pr/tests/dlltest.c
index bd8f7c49..bc817a05 100644
--- a/pr/tests/dlltest.c
+++ b/pr/tests/dlltest.c
@@ -84,15 +84,15 @@ int main(int argc, char** argv)
fprintf(
stderr, "PR_LoadLibrary failed (%d, %d, %s)\n",
PR_GetError(), PR_GetOSError(), text);
- if (!debug_mode) failed_already=1;
+ if (!debug_mode) failed_already=1;
}
getFcn = (GetFcnType) PR_FindSymbol(lib, "My_GetValue");
setFcn = (SetFcnType) PR_FindSymbol(lib, "My_SetValue");
(*setFcn)(888);
value = (*getFcn)();
if (value != 888) {
- fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value);
- if (!debug_mode) failed_already=1;
+ fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
}
if (debug_mode) printf("Test 1 passed\n");
@@ -103,26 +103,24 @@ int main(int argc, char** argv)
*/
getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2);
- if (lib != lib2) {
- fprintf(stderr, "Test 2 failed: handles for the same library are not "
- "equal: handle 1: %p, handle 2: %p\n", lib, lib2);
- if (!debug_mode) failed_already=1;
-
+ if (NULL == getFcn || lib != lib2) {
+ fprintf(stderr, "Test 2 failed: handles for the same library are not "
+ "equal: handle 1: %p, handle 2: %p\n", lib, lib2);
+ if (!debug_mode) failed_already=1;
}
setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
value = (*getFcn)();
if (value != 888) {
- fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n",
- value);
- if (!debug_mode) failed_already=1;
-
+ fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n",
+ value);
+ if (!debug_mode) failed_already=1;
}
(*setFcn)(777);
value = (*getFcn)();
if (value != 777) {
- fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value);
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) printf("Test 2 passed\n");
@@ -133,19 +131,19 @@ int main(int argc, char** argv)
status = PR_UnloadLibrary(lib);
if (PR_FAILURE == status) {
- fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n",
- PR_GetError(), PR_GetOSError());
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
getFcn = (GetFcnType) PR_FindSymbol(lib2, "My_GetValue");
setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
(*setFcn)(666);
value = (*getFcn)();
if (value != 666) {
- fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value);
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) printf("Test 3 passed\n");
@@ -155,21 +153,21 @@ int main(int argc, char** argv)
status = PR_UnloadLibrary(lib2);
if (PR_FAILURE == status) {
- fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n",
- PR_GetError(), PR_GetOSError());
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
- status = PR_UnloadLibrary(lib2);
- if (PR_FAILURE != status || PR_GetError() != PR_INVALID_ARGUMENT_ERROR) {
- fprintf(stderr, "Test 4 failed: how can an already unloaded library "
- "be unloaded again?\n");
- if (!debug_mode) failed_already=1;
- goto exit_now;
+ getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2);
+ if (NULL != getFcn) {
+ fprintf(stderr, "Test 4 failed: how can we find a symbol "
+ "in an already unloaded library?\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
}
if (debug_mode) {
- printf("Test 4 passed\n");
- }
+ printf("Test 4 passed\n");
+ }
/*
** Test 5: LoadStaticLibrary()
@@ -181,21 +179,24 @@ int main(int argc, char** argv)
lib = PR_LoadStaticLibrary( "my.dll", slt );
if ( lib == NULL )
{
- printf("dlltest: Test 5: LoadStatiLibrary() failed\n" );
+ fprintf(stderr, "Test 5: LoadStatiLibrary() failed\n" );
goto exit_now;
}
- printf("Test 5 passed\n");
+ if (debug_mode)
+ {
+ printf("Test 5 passed\n");
+ }
}
- goto exit_now;
+ goto exit_now;
exit_now:
PR_Cleanup();
if (failed_already) {
printf("FAILED\n");
- return 1;
+ return 1;
} else {
printf("PASSED\n");
- return 0;
+ return 0;
}
}
diff --git a/pr/tests/foreign.c b/pr/tests/foreign.c
new file mode 100644
index 00000000..dcf88250
--- /dev/null
+++ b/pr/tests/foreign.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** File: foreign.c
+** Description: Testing various functions w/ foreign threads
+**
+** We create a thread and get it to call exactly one runtime function.
+** The thread is allowed to be created by some other environment that
+** NSPR, but it does not announce itself to the runtime prior to calling
+** in.
+**
+** The goal: try to survive.
+**
+*/
+
+#include "prcvar.h"
+#include "prenv.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prthread.h"
+#include "prtypes.h"
+#include "prprf.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static enum {
+ thread_nspr, thread_pthread, thread_sproc, thread_win32
+} thread_provider;
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+static PRFileDesc *output;
+
+static int _debug_on = 0;
+
+#define DEFAULT_THREAD_COUNT 10
+
+#define DPRINTF(arg) if (_debug_on) PR_fprintf arg
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include "md/_pth.h"
+#include <pthread.h>
+static void *pthread_start(void *arg)
+{
+ StartFn start = ((StartObject*)arg)->start;
+ void *data = ((StartObject*)arg)->arg;
+ PR_Free(arg);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus CreateThread(StartFn start, void *arg)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* CreateThread */
+
+static void PR_CALLBACK lazyEntry(void *arg)
+{
+ PR_ASSERT(NULL == arg);
+} /* lazyEntry */
+
+
+static void OneShot(void *arg)
+{
+ PRUintn pdkey;
+ PRFileDesc *pair[2];
+ PRIntn test = (PRIntn)arg;
+
+ for (test = 0; test < 11; ++test) {
+
+ switch (test)
+ {
+ case 0:
+ (void)PR_NewLock();
+ DPRINTF((output,"Thread[0x%x] called PR_NewLock\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 1:
+ (void)PR_SecondsToInterval(1);
+ DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 2: (void)PR_CreateThread(
+ PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 3:
+ (void)PR_Open("/usr/tmp/", PR_RDONLY, 0);
+ DPRINTF((output,"Thread[0x%x] called PR_Open\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 4:
+ (void)PR_NewUDPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 5:
+ (void)PR_NewTCPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 6:
+ (void)PR_OpenDir("/usr/tmp/");
+ DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 7:
+ (void)PR_NewThreadPrivateIndex(&pdkey, NULL);
+ DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 8:
+ (void)PR_GetEnv("PATH");
+ DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 9:
+ (void)PR_NewTCPSocketPair(pair);
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 10:
+ PR_SetConcurrency(2);
+ DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n",
+ PR_GetCurrentThread()));
+ break;
+
+ default:
+ break;
+ } /* switch() */
+ }
+} /* OneShot */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRIntn test_number;
+ PRInt32 thread_cnt = DEFAULT_THREAD_COUNT;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
+
+#if defined(WIN32)
+ thread_provider = thread_win32;
+#elif defined(_PR_PTHREADS)
+ thread_provider = thread_pthread;
+#elif defined(IRIX)
+ thread_provider = thread_sproc;
+#else
+ thread_provider = thread_nspr;
+#endif
+
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(2);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+
+ while (thread_cnt-- > 0)
+ {
+ rv = CreateThread(OneShot, (void*)thread_cnt);
+ PR_ASSERT(PR_SUCCESS == rv);
+ PR_Sleep(PR_MillisecondsToInterval(5));
+ }
+ PR_Sleep(PR_SecondsToInterval(3));
+ return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1;
+} /* main */
+
+/* foreign.c */
diff --git a/pr/tests/forktest.c b/pr/tests/forktest.c
index b52499d5..ecb09c5b 100644
--- a/pr/tests/forktest.c
+++ b/pr/tests/forktest.c
@@ -40,6 +40,7 @@
#include "plgetopt.h"
#include "nspr.h"
+#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -259,6 +260,7 @@ char *argv[]
)
{
pid_t pid;
+ int rv;
/* main test program */
@@ -275,9 +277,18 @@ char *argv[]
printf("Fork succeeded. Parent process continues.\n");
DoIO();
- if (waitpid(pid, &childStatus, 0) != pid) {
- fprintf(stderr, "waitpid failed: %d\n", errno);
- failed_already = 1;
+ if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ /*
+ * nspr may handle SIGCLD signal
+ */
+ if ((rv < 0) && (errno == ECHILD)) {
+ } else
+#endif
+ {
+ fprintf(stderr, "waitpid failed: %d\n", errno);
+ failed_already = 1;
+ }
} else if (!WIFEXITED(childStatus)
|| WEXITSTATUS(childStatus) != 0) {
failed_already = 1;
@@ -290,6 +301,10 @@ char *argv[]
}
return failed_already;
} else {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ extern void _PR_IRIX_CHILD_PROCESS(void);
+ _PR_IRIX_CHILD_PROCESS();
+#endif
printf("Fork succeeded. Child process continues.\n");
DoIO();
printf("Child process exits.\n");
diff --git a/pr/tests/initclk.c b/pr/tests/initclk.c
new file mode 100644
index 00000000..a815997f
--- /dev/null
+++ b/pr/tests/initclk.c
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * This is a regression test for the bug that the interval timer
+ * is not initialized when _PR_CreateCPU calls PR_IntervalNow.
+ * The bug would make this test program finish prematurely,
+ * when the SHORT_TIMEOUT period expires. The correct behavior
+ * is for the test to finish when the LONG_TIMEOUT period expires.
+ */
+
+#include "prlock.h"
+#include "prcvar.h"
+#include "prthread.h"
+#include "prinrval.h"
+#include "prlog.h"
+#include <stdio.h>
+
+/* The timeouts, in milliseconds */
+#define SHORT_TIMEOUT 1000
+#define LONG_TIMEOUT 3000
+
+PRLock *lock1, *lock2;
+PRCondVar *cv1, *cv2;
+
+void ThreadFunc(void *arg)
+{
+ PR_Lock(lock1);
+ PR_WaitCondVar(cv1, PR_MillisecondsToInterval(SHORT_TIMEOUT));
+ PR_Unlock(lock1);
+}
+
+int main()
+{
+ PRThread *thread;
+ PRIntervalTime start, end;
+ PRUint32 elapsed_ms;
+
+ lock1 = PR_NewLock();
+ PR_ASSERT(NULL != lock1);
+ cv1 = PR_NewCondVar(lock1);
+ PR_ASSERT(NULL != cv1);
+ lock2 = PR_NewLock();
+ PR_ASSERT(NULL != lock2);
+ cv2 = PR_NewCondVar(lock2);
+ PR_ASSERT(NULL != cv2);
+ start = PR_IntervalNow();
+ thread = PR_CreateThread(
+ PR_USER_THREAD,
+ ThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ PR_ASSERT(NULL != thread);
+ PR_Lock(lock2);
+ PR_WaitCondVar(cv2, PR_MillisecondsToInterval(LONG_TIMEOUT));
+ PR_Unlock(lock2);
+ PR_JoinThread(thread);
+ end = PR_IntervalNow();
+ elapsed_ms = PR_IntervalToMilliseconds((PRIntervalTime)(end - start));
+ /* Allow 100ms imprecision */
+ if (elapsed_ms < LONG_TIMEOUT - 100 || elapsed_ms > LONG_TIMEOUT + 100) {
+ printf("Elapsed time should be %u ms but is %u ms\n",
+ LONG_TIMEOUT, elapsed_ms);
+ printf("FAIL\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/pr/tests/inrval.c b/pr/tests/inrval.c
index b963da48..ce1df9cc 100644
--- a/pr/tests/inrval.c
+++ b/pr/tests/inrval.c
@@ -40,6 +40,9 @@
#else
#include "obsolete/pralarm.h"
#endif
+
+#include "prio.h"
+#include "prprf.h"
#include "prlock.h"
#include "prlong.h"
#include "prcvar.h"
@@ -51,14 +54,8 @@
#include <stdio.h>
#include <stdlib.h>
-#ifdef XP_MAC
-#include "prlog.h"
-#define printf PR_LogPrint
-extern void SetupMacPrintfLog(char *logFile);
-#endif
-
-PRIntn failed_already=0;
-PRIntn debug_mode;
+static PRIntn debug_mode;
+static PRFileDesc *output;
static void TestConversions(void)
@@ -66,26 +63,62 @@ static void TestConversions(void)
PRIntervalTime ticks = PR_TicksPerSecond();
if (debug_mode) {
- printf("PR_TicksPerSecond: %ld\n\n", ticks);
- printf("PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1));
- printf("PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000));
- printf("PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000));
+ PR_fprintf(output, "PR_TicksPerSecond: %ld\n\n", ticks);
+ PR_fprintf(output, "PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1));
+ PR_fprintf(output, "PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000));
- printf("PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3));
- printf("PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000));
- printf("PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000));
+ PR_fprintf(output, "PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3));
+ PR_fprintf(output, "PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000));
- printf("PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
- printf("PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
- printf("PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
ticks *= 3;
- printf("PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
- printf("PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
- printf("PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
} /*end debug mode */
} /* TestConversions */
+static void TestIntervalOverhead(void)
+{
+ /* Hopefully the optimizer won't delete this function */
+ PRUint32 elapsed, per_call, loops = 1000000;
+
+ PRIntervalTime timeout, timein = PR_IntervalNow();
+ while (--loops > 0)
+ timeout = PR_IntervalNow();
+
+ elapsed = 1000U * PR_IntervalToMicroseconds(timeout - timein);
+ per_call = elapsed / 1000000U;
+ PR_fprintf(
+ output, "Overhead of 'PR_IntervalNow()' is %u nsecs\n\n", per_call);
+} /* TestIntervalOverhead */
+
+static void TestNowOverhead(void)
+{
+ PRTime timeout, timein;
+ PRInt32 overhead, loops = 1000000;
+ PRInt64 elapsed, per_call, ten23rd, ten26th;
+
+ LL_I2L(ten23rd, 1000);
+ LL_I2L(ten26th, 1000000);
+
+ timein = PR_Now();
+ while (--loops > 0)
+ timeout = PR_Now();
+
+ LL_SUB(elapsed, timeout, timein);
+ LL_MUL(elapsed, elapsed, ten23rd);
+ LL_DIV(per_call, elapsed, ten26th);
+ LL_L2I(overhead, per_call);
+ PR_fprintf(
+ output, "Overhead of 'PR_Now()' is %u nsecs\n\n", overhead);
+} /* TestNowOverhead */
+
static void TestIntervals(void)
{
PRStatus rv;
@@ -107,58 +140,18 @@ static void TestIntervals(void)
LL_I2L(thousand, 1000);
LL_DIV(elapsed, elapsed, thousand);
LL_L2UI(delta, elapsed);
- if (debug_mode) printf(
+ if (debug_mode) PR_fprintf(output,
"TestIntervals: %swaiting %ld seconds took %ld msecs\n",
((rv == PR_SUCCESS) ? "" : "FAILED "), seconds, delta);
}
PR_DestroyCondVar(cv);
PR_DestroyLock(ml);
- if (debug_mode) printf("\n");
+ if (debug_mode) PR_fprintf(output, "\n");
} /* TestIntervals */
-static PRUint32 GetInterval(PRUint32 loops)
-{
- PRIntervalTime interval = 0;
- while (loops-- > 0) interval += PR_IntervalNow();
- return 0;
-} /* GetInterval */
-
-static PRUint32 TimeThis(
- const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops)
-{
- PRUint32 overhead, usecs32;
- PRTime timein, timeout, usecs;
-
- timein = PR_Now();
- overhead = func(loops);
- timeout = PR_Now();
-
- LL_SUB(usecs, timeout, timein);
- LL_L2I(usecs32, usecs);
-
- if(usecs32 < overhead)
- {
- if (debug_mode) {
- printf("%s ran in negative time\n", msg);
- printf(" predicted overhead was %ld usecs\n", overhead);
- printf(" test completed in %ld usecs\n\n", usecs);
- }
- }
- else
- {
- if (debug_mode)
- printf(
- "%s [\n\ttotal: %ld usecs\n\toverhead: %ld usecs\n\tcost: %6.3f usecs]\n\n",
- msg, usecs, overhead,
- ((double)(usecs32 - overhead) / (double)loops));
- }
-
- return overhead;
-} /* TimeThis */
-
static PRIntn PR_CALLBACK RealMain(int argc, char** argv)
{
- PRUint32 cpu, cpus = 2, loops = 1000;
+ PRUint32 vcpu, cpus = 0, loops = 1000;
/* The command line argument: -d is used to determine if the test is being run
in debug mode. The regress tool requires only one line output:PASS or FAIL.
@@ -191,42 +184,28 @@ static PRIntn PR_CALLBACK RealMain(int argc, char** argv)
}
PL_DestroyOptState(opt);
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ PR_fprintf(output, "inrval: Examine stdout to determine results.\n");
- printf("inrval: Examine stdout to determine results.\n");
-
- if (cpus == 0) cpus = 2;
+ if (cpus == 0) cpus = 8;
if (loops == 0) loops = 1000;
- if (debug_mode) printf("Inrval: Using %d loops\n", loops);
-
-
- cpus = (argc < 3) ? 2 : atoi(argv[2]);
- if (cpus == 0) cpus = 2;
- if (debug_mode) printf("Inrval: Using %d cpu(s)\n", cpus);
if (debug_mode > 0)
{
- printf("Inrval: Using %d loops\n", loops);
- printf("Inrval: Using %d cpu(s)\n", cpus);
+ PR_fprintf(output, "Inrval: Using %d loops\n", loops);
+ PR_fprintf(output, "Inrval: Using 1 and %d cpu(s)\n", cpus);
}
-#ifdef XP_MAC
- SetupMacPrintfLog("inrval.log");
- debug_mode = 1;
-#endif
-
- for (cpu = 1; cpu <= cpus; ++cpu)
+ for (vcpu = 1; vcpu <= cpus; vcpu += cpus - 1)
{
+ if (debug_mode)
+ PR_fprintf(output, "\nInrval: Using %d CPU(s)\n\n", vcpu);
+ PR_SetConcurrency(vcpu);
- if (debug_mode) printf("\nInrval: Using %d CPU(s)\n", cpu);
- if (debug_mode > 0)
- printf("\nInrval: Using %d CPU(s)\n", cpu);
-
- PR_SetConcurrency(cpu);
-
+ TestNowOverhead();
+ TestIntervalOverhead();
TestConversions();
TestIntervals();
-
- (void)TimeThis("GetInterval", GetInterval, loops);
}
return 0;
diff --git a/pr/tests/instrumt.c b/pr/tests/instrumt.c
new file mode 100644
index 00000000..5a51a9f3
--- /dev/null
+++ b/pr/tests/instrumt.c
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** File: instrumt.c
+** Description: This test is for the NSPR debug aids defined in
+** prcountr.h, prtrace.h, prolock.h
+**
+** The test case tests the three debug aids in NSPR:
+**
+** Diagnostic messages can be enabled using "instrumt -v 6"
+** This sets the msgLevel to something that PR_LOG() likes.
+** Also define in the environment "NSPR_LOG_MODULES=Test:6"
+**
+** CounterTest() tests the counter facility. This test
+** creates 4 threads. Each thread either increments, decrements,
+** adds to or subtracts from a counter, depending on an argument
+** passed to the thread at thread-create time. Each of these threads
+** does COUNT_LIMIT iterations doing its thing. When all 4 threads
+** are done, the result of the counter is evaluated. If all was atomic,
+** the the value of the counter should be zero.
+**
+** TraceTest():
+** This test mingles with the counter test. Counters trace.
+** A thread to extract trace entries on the fly is started.
+** A thread to dump trace entries to a file is started.
+**
+** OrderedLockTest():
+**
+**
+**
+**
+**
+*/
+
+#include <stdio.h>
+#include <plstr.h>
+#include <prclist.h>
+#include <prmem.h>
+#include <plgetopt.h>
+#include <prlog.h>
+#include <prmon.h>
+#include <pratom.h>
+#include <prtrace.h>
+#include <prcountr.h>
+#include <prolock.h>
+
+#define COUNT_LIMIT (10 * ( 1024))
+
+#define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
+
+typedef enum
+{
+ CountLoop = 1,
+ TraceLoop = 2,
+ TraceFlow = 3
+} TraceTypes;
+
+
+PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
+
+PRBool help = PR_FALSE;
+PRBool failed = PR_FALSE;
+
+
+PRLogModuleInfo *lm;
+PRMonitor *mon;
+PRInt32 activeThreads = 0;
+PR_DEFINE_COUNTER( hCounter );
+PR_DEFINE_TRACE( hTrace );
+
+static void Help(void)
+{
+ printf("Help? ... Ha!\n");
+}
+
+static void ListCounters(void)
+{
+ PR_DEFINE_COUNTER( qh );
+ PR_DEFINE_COUNTER( rh );
+ char *qn, *rn, *dn;
+ char **qname = &qn, **rname = &rn, **desc = &dn;
+ PRUint32 tCtr;
+
+ PR_INIT_COUNTER_HANDLE( qh, NULL );
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_COUNTER_HANDLE( rh, NULL );
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ tCtr = PR_GET_COUNTER(tCtr, rh);
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s Value: %ld\n",
+ qn, rn, dn, tCtr ));
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+static void ListTraces(void)
+{
+ PR_DEFINE_TRACE( qh );
+ PR_DEFINE_TRACE( rh );
+ char *qn, *rn, *dn;
+ char **qname = &qn, **rname = &rn, **desc = &dn;
+
+ PR_INIT_TRACE_HANDLE( qh, NULL );
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_TRACE_HANDLE( rh, NULL );
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s",
+ qn, rn, dn ));
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+
+static PRInt32 one = 1;
+static PRInt32 two = 2;
+static PRInt32 three = 3;
+static PRInt32 four = 4;
+
+/*
+** Thread to iteratively count something.
+*/
+static void PR_CALLBACK CountSomething( void *arg )
+{
+ PRInt32 switchVar = *((PRInt32 *)arg);
+ PRInt32 i;
+
+ PR_LOG( lm, msgLevel,
+ ("CountSomething: begin thread %ld", switchVar ));
+
+ for ( i = 0; i < COUNT_LIMIT ; i++)
+ {
+ switch ( switchVar )
+ {
+ case 1 :
+ PR_INCREMENT_COUNTER( hCounter );
+ break;
+ case 2 :
+ PR_DECREMENT_COUNTER( hCounter );
+ break;
+ case 3 :
+ PR_ADD_TO_COUNTER( hCounter, 1 );
+ break;
+ case 4 :
+ PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
+ break;
+ default :
+ PR_ASSERT( 0 );
+ break;
+ }
+ PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
+ } /* end for() */
+
+ PR_LOG( lm, msgLevel,
+ ("CounterSomething: end thread %ld", switchVar ));
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end CountSomething() */
+
+/*
+** Create the counter threads.
+*/
+static void CounterTest( void )
+{
+ PRThread *t1, *t2, *t3, *t4;
+ PR_DEFINE_COUNTER( tc );
+
+ PR_LOG( lm, msgLevel,
+ ("Begin CounterTest"));
+
+ activeThreads += 4;
+ PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
+
+ PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
+ PR_ASSERT( tc == hCounter );
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &one,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &two,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ t3 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &three,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t3);
+
+ t4 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &four,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t4);
+
+ PR_LOG( lm, msgLevel,
+ ("Counter Threads started"));
+
+ ListCounters();
+ return;
+} /* end CounterTest() */
+
+/*
+** Thread to dump trace buffer to a file.
+*/
+static void PR_CALLBACK RecordTrace(void *arg )
+{
+ PR_RECORD_TRACE_ENTRIES();
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end RecordTrace() */
+
+
+
+#define NUM_TRACE_RECORDS ( 10000 )
+/*
+** Thread to extract and print trace entries from the buffer.
+*/
+static void PR_CALLBACK SampleTrace( void *arg )
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRInt32 found, rc;
+ PRTraceEntry *foundEntries;
+ PRInt32 i;
+
+ foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
+ PR_ASSERT(foundEntries != NULL );
+
+ do
+ {
+ rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
+
+ if ( found != 0)
+ {
+ for ( i = 0 ; i < found; i++ )
+ {
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
+ (foundEntries +i)->thread,
+ (foundEntries +i)->time,
+ (foundEntries +i)->userData[0],
+ (foundEntries +i)->userData[1],
+ (foundEntries +i)->userData[2] ));
+ }
+ }
+ PR_Sleep(PR_MillisecondsToInterval(50));
+ }
+ while( found != 0 && activeThreads >= 1 );
+
+ PR_Free( foundEntries );
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace(): exiting"));
+
+#endif
+ return;
+} /* end RecordTrace() */
+
+/*
+** Basic trace test.
+*/
+static void TraceTest( void )
+{
+ PRInt32 i;
+ PRInt32 size;
+ PR_DEFINE_TRACE( th );
+ PRThread *t1, *t2;
+
+ PR_LOG( lm, msgLevel,
+ ("Begin TraceTest"));
+
+ size = SMALL_TRACE_BUFSIZE;
+ PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
+ PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
+ PR_ASSERT( i == size );
+
+ PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
+
+ PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
+
+
+
+ activeThreads += 2;
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ RecordTrace, NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ SampleTrace, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ ListTraces();
+
+ PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
+ PR_ASSERT( th == hTrace );
+
+ PR_LOG( lm, msgLevel,
+ ("End TraceTest"));
+ return;
+} /* end TraceTest() */
+
+
+/*
+** Ordered lock test.
+*/
+static void OrderedLockTest( void )
+{
+ PR_LOG( lm, msgLevel,
+ ("Begin OrderedLockTest"));
+
+
+} /* end OrderedLockTest() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRUint32 counter;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
+ lm = PR_NewLogModule("Test");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* verbose mode */
+ msgLevel = (PRLogModuleLevel)atol( opt->value);
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
+ mon = PR_NewMonitor();
+ PR_EnterMonitor( mon );
+
+ TraceTest();
+ CounterTest();
+ OrderedLockTest();
+
+ /* Wait for all threads to exit */
+ while ( activeThreads > 0 ) {
+ if ( activeThreads == 1 )
+ PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ PR_GET_COUNTER( counter, hCounter );
+ }
+ PR_ExitMonitor( mon );
+
+ /*
+ ** Evaluate results
+ */
+ PR_GET_COUNTER( counter, hCounter );
+ if ( counter != 0 )
+ {
+ failed = PR_TRUE;
+ PR_LOG( lm, msgLevel,
+ ("Expected counter == 0, found: %ld", counter));
+ printf("FAIL\n");
+ }
+ else
+ {
+ printf("PASS\n");
+ }
+
+ PR_DestroyMonitor( mon );
+
+ PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
+ PR_DESTROY_TRACE( hTrace );
+#else
+ printf("Test not defined\n");
+#endif
+ return 0;
+} /* main() */
+/* end instrumt.c */
+
diff --git a/pr/tests/ipv6.c b/pr/tests/ipv6.c
index 63ddfbf6..15303430 100644
--- a/pr/tests/ipv6.c
+++ b/pr/tests/ipv6.c
@@ -17,10 +17,13 @@
*/
#include "prio.h"
+#include "prenv.h"
#include "prmem.h"
+#include "prlink.h"
#include "prsystem.h"
#include "prnetdb.h"
#include "prprf.h"
+#include "prvrsion.h"
#include "plerror.h"
#include "plgetopt.h"
@@ -37,8 +40,9 @@ static PRFileDesc *err = NULL;
static void Help(void)
{
- PR_fprintf(err, "Usage: [-t s] [-s] [-h]\n");
+ PR_fprintf(err, "Usage: [-V] [-6] [-h]\n");
PR_fprintf(err, "\t<nul> Name of host to lookup (default: self)\n");
+ PR_fprintf(err, "\t-V Display runtime version info (default: FALSE)\n");
PR_fprintf(err, "\t-6 First turn on IPv6 capability (default: FALSE)\n");
PR_fprintf(err, "\t-h This message and nothing else\n");
} /* Help */
@@ -91,8 +95,8 @@ PRIntn main(PRIntn argc, char **argv)
PRProtoEnt proto;
PRBool ipv6 = PR_FALSE;
const char *name = NULL;
- PRBool failed = PR_FALSE;
- PLOptState *opt = PL_CreateOptState(argc, argv, "h6");
+ PRBool failed = PR_FALSE, version = PR_FALSE;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Vh6");
err = PR_GetSpecialFD(PR_StandardError);
@@ -107,6 +111,9 @@ PRIntn main(PRIntn argc, char **argv)
case '6': /* Turn on IPv6 mode */
ipv6 = PR_TRUE;
break;
+ case 'V': /* Do version discovery */
+ version = PR_TRUE;
+ break;
case 'h': /* user wants some guidance */
default:
Help(); /* so give him an earful */
@@ -115,6 +122,58 @@ PRIntn main(PRIntn argc, char **argv)
}
PL_DestroyOptState(opt);
+ if (version)
+ {
+#if defined(XP_UNIX)
+#define NSPR_LIB "nspr21"
+#elif defined(WIN32)
+#define NSPR_LIB "libnspr21"
+#else
+#error "Architecture not supported"
+#endif
+ const PRVersionDescription *version_info;
+ char *nspr_path = PR_GetEnv("LD_LIBRARY_PATH");
+ char *nspr_name = PR_GetLibraryName(nspr_path, NSPR_LIB);
+ PRLibrary *runtime = PR_LoadLibrary(nspr_name);
+ if (NULL == runtime)
+ PL_FPrintError(err, "PR_LoadLibrary");
+ else
+ {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint)
+ PL_FPrintError(err, "PR_FindSymbol");
+ else
+ {
+ char buffer[100];
+ PRExplodedTime exploded;
+ version_info = versionPoint();
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ }
+ }
+ if (NULL != nspr_name) PR_FreeLibraryName(nspr_name);
+ }
+
if (ipv6)
{
rv = PR_SetIPv6Enable(ipv6);
diff --git a/pr/tests/joinkk.c b/pr/tests/joinkk.c
index f3b5396d..5c2e4e9c 100644
--- a/pr/tests/joinkk.c
+++ b/pr/tests/joinkk.c
@@ -154,12 +154,12 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
if(failed_already)
{
printf("FAIL\n");
- return 0;
+ return 1;
}
else
{
printf("PASS\n");
- return 1;
+ return 0;
}
}
diff --git a/pr/tests/layer.c b/pr/tests/layer.c
index e6be944f..0c93e4b6 100644
--- a/pr/tests/layer.c
+++ b/pr/tests/layer.c
@@ -64,6 +64,7 @@ static PRFileDesc *PushLayer(PRFileDesc *stack)
return stack;
} /* PushLayer */
+#if 0
static PRFileDesc *PopLayer(PRFileDesc *stack)
{
PRFileDesc *popped = PR_PopIOLayer(stack, identity);
@@ -73,6 +74,7 @@ static PRFileDesc *PopLayer(PRFileDesc *stack)
return stack;
} /* PopLayer */
+#endif
static void PR_CALLBACK Client(void *arg)
{
@@ -355,8 +357,8 @@ PRIntn main(PRIntn argc, char **argv)
rv = PR_JoinThread(server_thread);
PR_ASSERT(PR_SUCCESS == rv);
- rv = PR_Close(PopLayer(client)); PR_ASSERT(PR_SUCCESS == rv);
- rv = PR_Close(PopLayer(service)); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
if (verbosity > silent)
PR_fprintf(logFile, "Ending layered test\n");
}
diff --git a/pr/tests/lock.c b/pr/tests/lock.c
index e5683171..6f4616dc 100644
--- a/pr/tests/lock.c
+++ b/pr/tests/lock.c
@@ -48,9 +48,11 @@
/* Used to get the command line option */
#include "plgetopt.h"
+#include "prio.h"
#include "prcmon.h"
#include "prinit.h"
#include "prinrval.h"
+#include "prprf.h"
#include "prlock.h"
#include "prlog.h"
#include "prmon.h"
@@ -60,7 +62,6 @@
#include "plstr.h"
-#include <stdio.h>
#include <stdlib.h>
#if defined(XP_UNIX)
@@ -72,21 +73,28 @@
#define printf PR_LogPrint
extern void SetupMacPrintfLog(char *logFile);
#endif
-PRIntn failed_already=0;
-PRIntn debug_mode;
+
+static PRIntn failed_already=0;
+static PRFileDesc *std_err = NULL;
+static PRBool verbosity = PR_FALSE;
+static PRBool debug_mode = PR_FALSE;
const static PRIntervalTime contention_interval = 50;
typedef struct LockContentious_s {
PRLock *ml;
- PRUint32 loops;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
PRIntervalTime overhead;
PRIntervalTime interval;
} LockContentious_t;
typedef struct MonitorContentious_s {
PRMonitor *ml;
- PRUint32 loops;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
PRIntervalTime overhead;
PRIntervalTime interval;
} MonitorContentious_t;
@@ -137,6 +145,7 @@ static void PR_CALLBACK LockContender(void *arg)
while (contention->loops-- > 0)
{
PR_Lock(contention->ml);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_Unlock(contention->ml);
@@ -150,7 +159,7 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
LockContentious_t * contention;
PRIntervalTime rv, overhead, timein = PR_IntervalNow();
- contention = (LockContentious_t *) PR_Calloc( 1, sizeof(LockContentious_t));
+ contention = PR_NEWZAP(LockContentious_t);
contention->loops = loops;
contention->overhead = 0;
contention->ml = PR_NewLock();
@@ -162,9 +171,10 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_Lock(contention->ml);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_Unlock(contention->ml);
@@ -175,6 +185,10 @@ static PRIntervalTime ContentiousLock(PRUint32 loops)
PR_DestroyLock(contention->ml);
overhead += (PR_IntervalNow() - timein);
rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
PR_Free(contention);
return rv;
} /* ContentiousLock */
@@ -210,23 +224,23 @@ static PRIntervalTime NonContentiousMonitor(PRUint32 loops)
static void PR_CALLBACK TryEntry(void *arg)
{
PRMonitor *ml = (PRMonitor*)arg;
- if (debug_mode) printf("Reentrant thread created\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread created\n");
PR_EnterMonitor(ml);
- if (debug_mode) printf("Reentrant thread acquired monitor\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread acquired monitor\n");
PR_ExitMonitor(ml);
- if (debug_mode) printf("Reentrant thread released monitor\n");
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread released monitor\n");
} /* TryEntry */
static PRIntervalTime ReentrantMonitor(PRUint32 loops)
{
- PRStatus status;
+ PRStatus status;
PRThread *thread;
PRMonitor *ml = PR_NewMonitor();
- if (debug_mode) printf("\nMonitor created for reentrant test\n");
+ if (debug_mode) PR_fprintf(std_err, "\nMonitor created for reentrant test\n");
PR_EnterMonitor(ml);
PR_EnterMonitor(ml);
- if (debug_mode) printf("Monitor acquired twice\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor acquired twice\n");
thread = PR_CreateThread(
PR_USER_THREAD, TryEntry, ml,
@@ -235,13 +249,13 @@ static PRIntervalTime ReentrantMonitor(PRUint32 loops)
PR_Sleep(PR_SecondsToInterval(1));
PR_ExitMonitor(ml);
- if (debug_mode) printf("Monitor released first time\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor released first time\n");
PR_ExitMonitor(ml);
- if (debug_mode) printf("Monitor released second time\n");
+ if (debug_mode) PR_fprintf(std_err, "Monitor released second time\n");
status = PR_JoinThread(thread);
- if (debug_mode) printf(
+ if (debug_mode) PR_fprintf(std_err,
"Reentrant thread joined %s\n",
(status == PR_SUCCESS) ? "successfully" : "in error");
@@ -255,6 +269,7 @@ static void PR_CALLBACK MonitorContender(void *arg)
while (contention->loops-- > 0)
{
PR_EnterMonitor(contention->ml);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_ExitMonitor(contention->ml);
@@ -268,7 +283,7 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
MonitorContentious_t * contention;
PRIntervalTime rv, overhead, timein = PR_IntervalNow();
- contention = (MonitorContentious_t *) PR_Calloc(1, sizeof(MonitorContentious_t));
+ contention = PR_NEWZAP(MonitorContentious_t);
contention->loops = loops;
contention->overhead = 0;
contention->ml = PR_NewMonitor();
@@ -280,9 +295,10 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_EnterMonitor(contention->ml);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_ExitMonitor(contention->ml);
@@ -293,6 +309,10 @@ static PRUint32 ContentiousMonitor(PRUint32 loops)
PR_DestroyMonitor(contention->ml);
overhead += (PR_IntervalNow() - timein);
rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
PR_Free(contention);
return rv;
} /* ContentiousMonitor */
@@ -317,6 +337,7 @@ static void PR_CALLBACK Contender(void *arg)
while (contention->loops-- > 0)
{
PR_CEnterMonitor(contention);
+ contention->contender+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_CExitMonitor(contention);
@@ -330,9 +351,8 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
MonitorContentious_t * contention;
PRIntervalTime overhead, timein = PR_IntervalNow();
- contention = (MonitorContentious_t *) PR_Calloc(1, sizeof(MonitorContentious_t));
+ contention = PR_NEWZAP(MonitorContentious_t);
contention->ml = NULL;
- contention->overhead = 0;
contention->loops = loops;
contention->interval = contention_interval;
thread = PR_CreateThread(
@@ -342,9 +362,10 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
overhead = PR_IntervalNow() - timein;
- while (contention->loops > 0)
+ while (contention->loops-- > 0)
{
PR_CEnterMonitor(contention);
+ contention->contentious+= 1;
contention->overhead += contention->interval;
PR_Sleep(contention->interval);
PR_CExitMonitor(contention);
@@ -353,7 +374,13 @@ static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
timein = PR_IntervalNow();
status = PR_JoinThread(thread);
overhead += (PR_IntervalNow() - timein);
- return overhead + contention->overhead;
+ overhead += overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
+ PR_Free(contention);
+ return overhead;
} /* ContentiousCMonitor */
static PRIntervalTime Test(
@@ -381,12 +408,12 @@ static PRIntervalTime Test(
accountable = duration - predicted;
accountable -= overhead;
elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
- printf("%s:", msg);
- while (spaces++ < 50) printf(" ");
+ PR_fprintf(PR_STDOUT, "%s:", msg);
+ while (spaces++ < 50) PR_fprintf(PR_STDOUT, " ");
if ((PRInt32)accountable < 0)
- printf("*****.** usecs/iteration\n");
+ PR_fprintf(PR_STDOUT, "*****.** usecs/iteration\n");
else
- printf("%8.2f usecs/iteration\n", elapsed/loops);
+ PR_fprintf(PR_STDOUT, "%8.2f usecs/iteration\n", elapsed/loops);
}
return duration;
} /* Test */
@@ -410,14 +437,17 @@ int main(int argc, char **argv)
Usage: lock [-d] [-l <num>] [-c <num>]
*/
PLOptStatus os;
- PLOptState *opt = PL_CreateOptState(argc, argv, "dl:c:");
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dvl:c:");
while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
{
if (PL_OPT_BAD == os) continue;
switch (opt->option)
{
case 'd': /* debug mode */
- debug_mode = 1;
+ debug_mode = PR_TRUE;
+ break;
+ case 'v': /* debug mode */
+ verbosity = PR_TRUE;
break;
case 'l': /* number of loops */
loops = atoi(opt->value);
@@ -441,16 +471,20 @@ int main(int argc, char **argv)
#endif
if (loops == 0) loops = 100;
- if (debug_mode) printf("Lock: Using %d loops\n", loops);
+ if (debug_mode)
+ {
+ std_err = PR_STDERR;
+ PR_fprintf(std_err, "Lock: Using %d loops\n", loops);
+ }
if (cpus == 0) cpus = 2;
- if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus);
+ if (debug_mode) PR_fprintf(std_err, "Lock: Using %d cpu(s)\n", cpus);
(void)Sleeper(10); /* try filling in the caches */
for (cpu = 1; cpu <= cpus; ++cpu)
{
- if (debug_mode) printf("\nLock: Using %d CPU(s)\n", cpu);
+ if (debug_mode) PR_fprintf(std_err, "\nLock: Using %d CPU(s)\n", cpu);
PR_SetConcurrency(cpu);
duration = Test("Overhead of PR_Sleep", Sleeper, loops, 0);
@@ -469,7 +503,10 @@ int main(int argc, char **argv)
(void)ReentrantMonitor(loops);
}
- if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((rv) ? "passed" : "failed"));
+ if (debug_mode)
+ PR_fprintf(
+ std_err, "%s: test %s\n", "Lock(mutex) test",
+ ((rv) ? "passed" : "failed"));
else {
if (!rv)
failed_already=1;
@@ -477,12 +514,12 @@ int main(int argc, char **argv)
if(failed_already)
{
- printf("FAIL\n");
+ PR_fprintf(PR_STDOUT, "FAIL\n");
return 1;
}
else
{
- printf("PASS\n");
+ PR_fprintf(PR_STDOUT, "PASS\n");
return 0;
}
diff --git a/pr/tests/many_cv.c b/pr/tests/many_cv.c
index ae973655..1f964458 100644
--- a/pr/tests/many_cv.c
+++ b/pr/tests/many_cv.c
@@ -114,9 +114,7 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
printf("PASS\n");
-#if defined(DEBUG) && defined(_PR_PTHREADS)
PT_FPrintStats(err, "\nPThread Statistics\n");
-#endif /* defined(DEBUG) && defined(_PR_PTHREADS) */
return 0;
}
diff --git a/pr/tests/multiwait.c b/pr/tests/multiwait.c
index be4ed6bb..4358b350 100644
--- a/pr/tests/multiwait.c
+++ b/pr/tests/multiwait.c
@@ -43,7 +43,6 @@ typedef struct Shared
typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
-static PRUint32 identity = 0;
static PRFileDesc *debug = NULL;
static PRInt32 desc_allocated = 0;
static PRUint16 default_port = 12273;
@@ -113,7 +112,7 @@ static PRRecvWait *CreateRecvWait(PRFileDesc *fd, PRIntervalTime timeout)
return desc_out;
} /* CreateRecvWait */
-static void DestroyRecvWait(Shared *shared, PRRecvWait *desc_out)
+static void DestroyRecvWait(PRRecvWait *desc_out)
{
if (verbosity > chatty)
PrintRecvDesc(desc_out, "Destroying");
@@ -134,7 +133,7 @@ static void CancelGroup(Shared *shared)
do
{
desc_out = PR_CancelWaitGroup(shared->group);
- if (NULL != desc_out) DestroyRecvWait(shared, desc_out);
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
} while (NULL != desc_out);
MW_ASSERT(0 == desc_allocated);
@@ -298,7 +297,7 @@ static void PR_CALLBACK SomeOpsThread(void *arg)
if (NULL == desc_out)
{
MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
- if (verbosity > quiet) PrintRecvDesc(desc_out, "Aborted");
+ if (verbosity > quiet) PR_fprintf(debug, "Aborted\n");
break;
}
MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome);
@@ -422,9 +421,6 @@ static void PR_CALLBACK ServiceThread(void *arg)
case PR_MW_SUCCESS:
{
PR_AtomicIncrement(&ops_done);
- if (verbosity > quiet)
- PR_fprintf(
- debug, "%s: Servicing %u\n", shared->title, ops_done);
if (verbosity > chatty)
PrintRecvDesc(desc_out, "Service ready");
rv = ServiceRequest(shared, desc_out);
@@ -445,10 +441,40 @@ static void PR_CALLBACK ServiceThread(void *arg)
}
} while (PR_SUCCESS == rv);
- if (NULL != desc_out) DestroyRecvWait(shared, desc_out);
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
} /* ServiceThread */
+static void PR_CALLBACK EnumerationThread(void *arg)
+{
+ PRStatus rv;
+ PRIntn count;
+ PRRecvWait *desc;
+ Shared *shared = (Shared*)arg;
+ PRIntervalTime five_seconds = PR_SecondsToInterval(5);
+ PRMWaitEnumerator *enumerator = PR_CreateMWaitEnumerator(shared->group);
+ MW_ASSERT(NULL != enumerator);
+
+ while (PR_SUCCESS == PR_Sleep(five_seconds))
+ {
+ count = 0;
+ desc = NULL;
+ while (NULL != (desc = PR_EnumerateWaitGroup(enumerator, desc)))
+ {
+ if (verbosity > chatty) PrintRecvDesc(desc, shared->title);
+ count += 1;
+ }
+ if (verbosity > silent)
+ PR_fprintf(debug,
+ "%s Enumerated %d objects\n", shared->title, count);
+ }
+
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+
+
+ rv = PR_DestroyMWaitEnumerator(enumerator);
+ MW_ASSERT(PR_SUCCESS == rv);
+} /* EnumerationThread */
static void PR_CALLBACK ServerThread(void *arg)
{
@@ -534,7 +560,7 @@ static void RealOneGroupIO(Shared *shared)
*/
PRStatus rv;
PRIntn index;
- PRThread *server_thread, **client_thread;
+ PRThread *server_thread, *enumeration_thread, **client_thread;
if (verbosity > quiet)
PR_fprintf(debug, "%s: creating server_thread\n", shared->title);
@@ -545,6 +571,14 @@ static void RealOneGroupIO(Shared *shared)
PR_JOINABLE_THREAD, 16 * 1024);
if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating enumeration_thread\n", shared->title);
+
+ enumeration_thread = PR_CreateThread(
+ PR_USER_THREAD, EnumerationThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+
+ if (verbosity > quiet)
PR_fprintf(debug, "%s: snoozing before creating clients\n", shared->title);
PR_Sleep(5 * shared->timeout);
@@ -572,6 +606,13 @@ static void RealOneGroupIO(Shared *shared)
}
if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining enumeration_thread\n", shared->title);
+ rv = PR_Interrupt(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > quiet)
PR_fprintf(debug, "%s: interrupting/joining server_thread\n", shared->title);
rv = PR_Interrupt(server_thread);
MW_ASSERT(PR_SUCCESS == rv);
@@ -598,7 +639,7 @@ static void RunThisOne(
static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
{
PRIntn verbage = (PRIntn)verbosity;
- return (Verbosity)(verbage += 1);
+ return (Verbosity)(verbage += delta);
} /* ChangeVerbosity */
PRIntn main(PRIntn argc, char **argv)
diff --git a/pr/tests/nbconn.c b/pr/tests/nbconn.c
index 372a8e78..b206f991 100644
--- a/pr/tests/nbconn.c
+++ b/pr/tests/nbconn.c
@@ -38,6 +38,7 @@
*/
#include "nspr.h"
+#include "plgetopt.h"
#include <stdio.h>
#ifdef XP_MAC
@@ -46,21 +47,61 @@ extern void SetupMacPrintfLog(char *logFile);
static char *hosts[4] = {"cynic", "warp", "gandalf", "neon"};
#endif
+#define SERVER_MAX_BIND_COUNT 100
+#define DATA_BUF_SIZE 256
+#define TCP_SERVER_PORT 10000
+
+typedef struct Server_Param {
+ PRFileDesc *sp_fd; /* server port */
+} Server_Param;
+static void PR_CALLBACK TCP_Server(void *arg);
+
+int _debug_on;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+static PRIntn connection_success_test();
+static PRIntn connection_failure_test();
int main(int argc, char **argv)
{
PRHostEnt he;
char buf[1024];
PRNetAddr addr;
- PRFileDesc *sock;
PRPollDesc pd;
PRStatus rv;
PRSocketOptionData optData;
- PRIntn n;
-
+ const char *hostname;
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRInt32 failed_already = 0;
#ifdef XP_MAC
int index;
PRIntervalTime timeout;
+#endif
+
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* debug mode */
+ hostname = opt->value;
+ break;
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#ifdef XP_MAC
SetupMacPrintfLog("nbconn.log");
for (index=0; index<4; index++) {
argv[1] = hosts[index];
@@ -69,90 +110,473 @@ int main(int argc, char **argv)
timeout = PR_SecondsToInterval(10UL);
#endif
+
PR_STDIO_INIT();
#ifndef XP_MAC
- if (argc != 2) {
- fprintf(stderr, "Usage: nbconn <hostname>\n");
- exit(1);
- }
+ if (hostname)
+ default_case = 0;
+ else
+ default_case = 1;
#endif
- if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
- printf( "Unknown host: %s\n", buf);
- exit(1);
- } else {
- printf( "host: %s\n", buf);
- }
- PR_EnumerateHostEnt(0, &he, 80, &addr);
-
- sock = PR_NewTCPSocket();
- optData.option = PR_SockOpt_Nonblocking;
- optData.value.non_blocking = PR_TRUE;
- PR_SetSocketOption(sock, &optData);
- rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
- if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
- printf( "Connect in progress\n");
- }
+ if (default_case) {
+
+ /*
+ * In the default case the following tests are executed:
+ * 1. successful connection: a server thread accepts a connection
+ * from the main thread
+ * 2. unsuccessful connection: the main thread tries to connect to a
+ * non-existent port and expects to get an error
+ */
+ rv = connection_success_test();
+ if (rv == 0)
+ rv = connection_failure_test();
+ return rv;
+ } else {
+ PRFileDesc *sock;
- pd.fd = sock;
- pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
+ printf( "Unknown host: %s\n", argv[1]);
+ exit(1);
+ } else {
+ printf( "host: %s\n", buf);
+ }
+ PR_EnumerateHostEnt(0, &he, 80, &addr);
+
+ sock = PR_NewTCPSocket();
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(sock, &optData);
+ rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "Connect in progress\n");
+ }
+
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
#ifndef XP_MAC
- n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
#else
- n = PR_Poll(&pd, 1, timeout);
+ n = PR_Poll(&pd, 1, timeout);
#endif
- if (n == -1) {
- printf( "PR_Poll failed\n");
- exit(1);
- }
- printf( "PR_Poll returns %d\n", n);
- if (pd.out_flags & PR_POLL_READ) {
- printf( "PR_POLL_READ\n");
- }
- if (pd.out_flags & PR_POLL_WRITE) {
- printf( "PR_POLL_WRITE\n");
- }
- if (pd.out_flags & PR_POLL_EXCEPT) {
- printf( "PR_POLL_EXCEPT\n");
- }
- if (pd.out_flags & PR_POLL_ERR) {
- printf( "PR_POLL_ERR\n");
- }
- if (pd.out_flags & PR_POLL_NVAL) {
- printf( "PR_POLL_NVAL\n");
- }
+ if (n == -1) {
+ printf( "PR_Poll failed\n");
+ exit(1);
+ }
+ printf( "PR_Poll returns %d\n", n);
+ if (pd.out_flags & PR_POLL_READ) {
+ printf( "PR_POLL_READ\n");
+ }
+ if (pd.out_flags & PR_POLL_WRITE) {
+ printf( "PR_POLL_WRITE\n");
+ }
+ if (pd.out_flags & PR_POLL_EXCEPT) {
+ printf( "PR_POLL_EXCEPT\n");
+ }
+ if (pd.out_flags & PR_POLL_ERR) {
+ printf( "PR_POLL_ERR\n");
+ }
+ if (pd.out_flags & PR_POLL_NVAL) {
+ printf( "PR_POLL_NVAL\n");
+ }
- if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
- printf("PR_GetConnectStatus: connect succeeded\n");
- /* Mac and Win16 have trouble printing to the console. */
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ printf("PR_GetConnectStatus: connect succeeded\n");
+ /* Mac and Win16 have trouble printing to the console. */
#if !defined(XP_MAC) && !defined(WIN16)
- PR_Write(sock, "GET /\r\n\r\n", 9);
- PR_Shutdown(sock, PR_SHUTDOWN_SEND);
- pd.in_flags = PR_POLL_READ;
- while (1) {
- n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
- printf( "poll returns %d\n", n);
- n = PR_Read(sock, buf, sizeof(buf));
- printf( "read returns %d\n", n);
- if (n <= 0) {
- break;
- }
- PR_Write(PR_STDOUT, buf, n);
- }
+ PR_Write(sock, "GET /\r\n\r\n", 9);
+ PR_Shutdown(sock, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ while (1) {
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ printf( "poll returns %d\n", n);
+ n = PR_Read(sock, buf, sizeof(buf));
+ printf( "read returns %d\n", n);
+ if (n <= 0) {
+ break;
+ }
+ PR_Write(PR_STDOUT, buf, n);
+ }
#endif
- } else {
- if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
- printf( "PR_GetConnectStatus: connect still in progress\n");
- exit(1);
- }
- printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
- PR_GetError(), PR_GetOSError());
- }
- PR_Close(sock);
+ } else {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "PR_GetConnectStatus: connect still in progress\n");
+ exit(1);
+ }
+ printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ PR_Close(sock);
#ifdef XP_MAC
- } /* end of for loop */
+ } /* end of for loop */
+#endif
+ printf( "PASS\n");
+ return 0;
+
+ }
+}
+
+
+/*
+ * TCP Server
+ * Server Thread
+ * Accept a connection from the client and write some data
+ */
+static void PR_CALLBACK
+TCP_Server(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRFileDesc *sockfd, *newsockfd;
+ char data_buf[DATA_BUF_SIZE];
+ PRIntn rv, bytes_read;
+
+ sockfd = sp->sp_fd;
+ if ((newsockfd = PR_Accept(sockfd, NULL,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,"ERROR - PR_Accept failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ return;
+ }
+ bytes_read = 0;
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Read(newsockfd, data_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from client - %d\n",bytes_read));
+ rv = PR_Write(newsockfd, data_buf,DATA_BUF_SIZE);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv == DATA_BUF_SIZE);
+ DPRINTF(("Bytes written to client - %d\n",rv));
+ PR_Close(newsockfd);
+}
+
+
+/*
+ * test for successful connection using a non-blocking socket
+ */
+static PRIntn
+connection_success_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRThread *thr = NULL;
+ Server_Param sp;
+ char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRIntn failed_already;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"ERROR - PR_Listen failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ DPRINTF(("Connect in progress\n"));
+ } else {
+ fprintf(stderr,"Error - PR_Connect failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ } else {
+ PR_ASSERT(rv == PR_SUCCESS);
+ fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ /*
+ * Now create a thread to accept a connection
+ */
+ sp.sp_fd = sockfd;
+ thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)&sp,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (thr == NULL) {
+ fprintf(stderr,"Error - PR_CreateThread failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Created TCP_Server thread [0x%x]\n",thr));
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
+#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (pd.out_flags != PR_POLL_WRITE) {
+ fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
+ pd.out_flags);
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+
+ DPRINTF(("Connection successful\n"));
+
+ /*
+ * Write some data, read it back and check data integrity to
+ * make sure the connection is good
+ */
+ pd.in_flags = PR_POLL_WRITE;
+ bytes_sent = 0;
+ memset(send_buf, 'a', DATA_BUF_SIZE);
+ while (bytes_sent != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE));
+ rv = PR_Write(conn_fd, send_buf + bytes_sent,
+ DATA_BUF_SIZE - bytes_sent);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv > 0);
+ bytes_sent += rv;
+ }
+ DPRINTF(("Bytes written to server - %d\n",bytes_sent));
+ PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ bytes_read = 0;
+ memset(recv_buf, 0, DATA_BUF_SIZE);
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ));
+ rv = PR_Read(conn_fd, recv_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from server - %d\n",bytes_read));
+ /*
+ * verify the data read
+ */
+ if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) {
+ fprintf(stderr,"ERROR - data corruption\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Data integrity verified\n"));
+ } else {
+ fprintf(stderr,"PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already = 1;
+ goto def_exit;
+ }
+def_exit:
+ if (thr) {
+ PR_JoinThread(thr);
+ thr = NULL;
+ }
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+
+}
+
+/*
+ * test for connection to a non-existent port using a non-blocking socket
+ */
+static PRIntn
+connection_failure_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRIntn n, failed_already = 0;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError()));
+ } else {
+ PR_ASSERT(rv == PR_SUCCESS);
+ fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (pd.out_flags != PR_POLL_WRITE) {
+ fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
+ pd.out_flags);
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+ fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n");
+ failed_already = 1;
+ goto def_exit;
+ }
+ rv = PR_GetError();
+ DPRINTF(("Connection failed, successfully with PR_Error %d\n",rv));
+def_exit:
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
- printf( "PASS\n");
- return 0;
}
diff --git a/pr/tests/nblayer.c b/pr/tests/nblayer.c
index 2c0ffd67..b14073a1 100644
--- a/pr/tests/nblayer.c
+++ b/pr/tests/nblayer.c
@@ -103,20 +103,24 @@ static void PR_CALLBACK Client(void *arg)
rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError()))
{
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client connect 'in progress'\n");
do
{
- {
- polldesc.fd = stack;
- polldesc.out_flags = 0;
- polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
- ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
- rv = PR_GetConnectStatus(&polldesc);
- if (PR_FAILURE == rv)
- {
- if (PR_IN_PROGRESS_ERROR != PR_GetError()) break;
- }
- }
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ if (verbosity > quiet)
+ PR_fprintf(
+ logFile, "Client connect 'in progress' [0x%x]\n",
+ polldesc.out_flags);
+ rv = PR_GetConnectStatus(&polldesc);
+ if ((PR_FAILURE == rv)
+ && (PR_IN_PROGRESS_ERROR != PR_GetError())) break;
} while (PR_FAILURE == rv);
}
PR_ASSERT(PR_SUCCESS == rv);
@@ -126,24 +130,29 @@ static void PR_CALLBACK Client(void *arg)
for (mits = 0; mits < minor_iterations; ++mits)
{
bytes_sent = 0;
- if (verbosity > chatty)
+ if (verbosity > quiet)
PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer));
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client sending %d bytes\n",
+ sizeof(buffer) - bytes_sent);
ready = PR_Send(
stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_sent += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client send status [%d]\n", ready);
+ if (0 < ready) bytes_sent += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_WRITE;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_sent < sizeof(buffer));
@@ -152,20 +161,26 @@ static void PR_CALLBACK Client(void *arg)
bytes_read = 0;
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receiving %d bytes\n",
+ bytes_sent - bytes_read);
ready = PR_Recv(
stack, buffer + bytes_read, bytes_sent - bytes_read,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_read += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_READ;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_read < bytes_sent);
@@ -200,14 +215,20 @@ static void PR_CALLBACK Server(void *arg)
do
{
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accepting connection\n");
service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accept status [0x%p]\n", service);
if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = stack;
polldesc.out_flags = 0;
- polldesc.in_flags = PR_POLL_READ;
+ polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
} while (NULL == service);
PR_ASSERT(NULL != service);
@@ -220,20 +241,25 @@ static void PR_CALLBACK Server(void *arg)
bytes_read = 0;
do
{
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Server receiving %d bytes\n",
+ sizeof(buffer) - bytes_read);
ready = PR_Recv(
service, buffer + bytes_read, sizeof(buffer) - bytes_read,
empty_flags, PR_INTERVAL_NO_TIMEOUT);
- if (0 < ready)
- {
- bytes_read += ready;
- }
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
{
polldesc.fd = service;
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_READ;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_read < sizeof(buffer));
@@ -260,7 +286,9 @@ static void PR_CALLBACK Server(void *arg)
polldesc.out_flags = 0;
polldesc.in_flags = PR_POLL_WRITE;
ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
- if (1 != ready) break; /* if not 1, then we're dead */
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
}
else break;
} while (bytes_sent < bytes_read);
@@ -331,7 +359,6 @@ static PRInt32 PR_CALLBACK MyRecv(
{
char *b;
PRInt32 rv;
- PRPollDesc polldesc;
PRFileDesc *lo = fd->lower;
PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
diff --git a/pr/tests/op_filok.c b/pr/tests/op_filok.c
index dc17efea..ae540ac7 100644
--- a/pr/tests/op_filok.c
+++ b/pr/tests/op_filok.c
@@ -42,31 +42,42 @@
#else
#endif
-static PRFileDesc *t1;
+/*
+ * The name of a file that is guaranteed to exist
+ * on every machine of a particular OS.
+ */
+#ifdef XP_UNIX
+#define EXISTING_FILENAME "/bin/sh"
+#elif defined(WIN32)
+#define EXISTING_FILENAME "c:/boot.ini"
+#else
+#error "Unknown OS"
+#endif
-PRIntn error_code;
+static PRFileDesc *t1;
int main(int argc, char **argv)
{
-
#ifdef XP_MAC
SetupMacPrintfLog("pr_open_re.log");
#endif
-
-
PR_STDIO_INIT();
- t1 = PR_Open("/usr/tmp/ttools/nspr20/err03.tmp", PR_TRUNCATE | PR_RDWR, 0666);
+ t1 = PR_Open(EXISTING_FILENAME, PR_RDONLY, 0666);
if (t1 == NULL) {
- if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
- printf ("error code is %d \n", PR_GetError());
- printf ("File should be found\n");
+ printf ("error code is %d \n", PR_GetError());
+ printf ("File %s should be found\n",
+ EXISTING_FILENAME);
+ return 1;
+ } else {
+ if (PR_Close(t1) == PR_SUCCESS) {
+ printf ("Test passed \n");
+ return 0;
+ } else {
+ printf ("cannot close file\n");
+ printf ("error code is %d\n", PR_GetError());
return 1;
}
}
- else {
- printf ("Test passed \n");
- return 0;
- }
}
diff --git a/pr/tests/op_noacc.c b/pr/tests/op_noacc.c
index c528dc75..b45fce2e 100644
--- a/pr/tests/op_noacc.c
+++ b/pr/tests/op_noacc.c
@@ -54,6 +54,10 @@ int main(int argc, char **argv)
SetupMacPrintfLog("pr_open_re.log");
#endif
+#ifdef XP_PC
+ printf("op_noacc: Test not valid on MS-Windows.\n\tNo concept of 'mode' on Open() call\n");
+ return(0);
+#endif
PR_STDIO_INIT();
diff --git a/pr/tests/op_nofil.c b/pr/tests/op_nofil.c
index c38063ff..3cb3adef 100644
--- a/pr/tests/op_nofil.c
+++ b/pr/tests/op_nofil.c
@@ -43,31 +43,38 @@
#else
#endif
+/*
+ * A file name that cannot exist
+ */
+#define NO_SUCH_FILE "/no/such/file.tmp"
+
static PRFileDesc *t1;
-PRIntn error_code;
int main(int argc, char **argv)
{
-
#ifdef XP_MAC
SetupMacPrintfLog("pr_open_re.log");
#endif
-
-
PR_STDIO_INIT();
- t1 = PR_Open("/usr/tmp/err02.tmp", PR_RDWR, 0666);
- if (t1 == NULL)
+ t1 = PR_Open(NO_SUCH_FILE, PR_RDONLY, 0666);
+ if (t1 == NULL) {
if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
-
- printf ("error code is %d \n", PR_GetError());
- printf ("PASS\n");
- return 0;
- }
- else {
- printf ("error code is %d \n", PR_GetError());
- printf ("FAIL\n");
- return 1;
+ printf ("error code is PR_FILE_NOT_FOUND_ERROR, as expected\n");
+ printf ("PASS\n");
+ return 0;
+ } else {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("FAIL\n");
+ return 1;
}
+ }
+ printf ("File %s exists on this machine!?\n", NO_SUCH_FILE);
+ if (PR_Close(t1) == PR_FAILURE) {
+ printf ("cannot close file\n");
+ printf ("error code is %d \n", PR_GetError());
+ }
+ printf ("FAIL\n");
+ return 1;
}
diff --git a/pr/tests/parent.c b/pr/tests/parent.c
index 4e82b8b0..d5fef9ec 100644
--- a/pr/tests/parent.c
+++ b/pr/tests/parent.c
@@ -26,6 +26,7 @@
#include "prprf.h"
#include "prinit.h"
#include "prproces.h"
+#include "prinrval.h"
typedef struct Child
{
@@ -44,6 +45,7 @@ PRIntn main (PRIntn argc, char **argv)
{
PRStatus rv;
PRInt32 test_status = 1;
+ PRIntervalTime t_start, t_elapsed;
PRFileDesc *debug = NULL;
Child *child = PR_NEWZAP(Child);
@@ -83,14 +85,22 @@ PRIntn main (PRIntn argc, char **argv)
child->attr, PR_StandardError,
PR_GetSpecialFD(PR_StandardError));
+ t_start = PR_IntervalNow();
child->process = PR_CreateProcess(
child->name, argv, NULL, child->attr);
+ t_elapsed = (PRIntervalTime) (PR_IntervalNow() - t_start);
test_status = (NULL == child->process) ? 1 : 0;
if (NULL != debug)
+ {
PR_fprintf(
debug, "Child was %sforked\n",
(0 == test_status) ? "" : "NOT ");
+ if (0 == test_status)
+ PR_fprintf(
+ debug, "PR_CreateProcess took %lu microseconds\n",
+ PR_IntervalToMicroseconds(t_elapsed));
+ }
if (0 == test_status)
{
diff --git a/pr/tests/perf.c b/pr/tests/perf.c
index 5928052f..b6785d75 100644
--- a/pr/tests/perf.c
+++ b/pr/tests/perf.c
@@ -67,6 +67,26 @@ static void DLLProcedureCall(void)
}
}
+static void Now(void)
+{
+ PRInt32 i;
+ PRTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_Now();
+ }
+}
+
+static void Interval(void)
+{
+ PRInt32 i;
+ PRIntervalTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_IntervalNow();
+ }
+}
+
static void IdleLock(void)
{
PRInt32 i;
@@ -399,6 +419,8 @@ int main(int argc, char **argv)
Measure(LocalProcedureCall, "local procedure call overhead");
Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
Measure(IdleLock, "idle lock lock/unlock pair");
Measure(IdleMonitor, "idle monitor entry/exit pair");
Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
@@ -420,6 +442,8 @@ int main(int argc, char **argv)
Measure(LocalProcedureCall, "local procedure call overhead");
Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
Measure(IdleLock, "idle lock lock/unlock pair");
Measure(IdleMonitor, "idle monitor entry/exit pair");
Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
diff --git a/pr/tests/poll_nm.c b/pr/tests/poll_nm.c
index a8995b3b..ab5c5286 100644
--- a/pr/tests/poll_nm.c
+++ b/pr/tests/poll_nm.c
@@ -89,7 +89,7 @@ clientThreadFunc(void *arg)
addr.inet.port = PR_htons((PRUint16)port);
addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
memset(buf, 0, sizeof(buf));
- PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip);
+ PR_snprintf(buf, sizeof(buf), "%hu", port);
for (i = 0; i < NUM_ITERATIONS; i++) {
sock = PR_NewTCPSocket();
diff --git a/pr/tests/pollable.c b/pr/tests/pollable.c
new file mode 100644
index 00000000..f31d8a93
--- /dev/null
+++ b/pr/tests/pollable.c
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * A test for the pollable events.
+ *
+ * A number of threads are in a ring configuration, each waiting on
+ * a pollable event that is set by its upstream neighbor.
+ */
+
+#include "prinit.h"
+#include "prio.h"
+#include "prthread.h"
+#include "prerror.h"
+#include "prmem.h"
+#include "prlog.h"
+#include "prprf.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+#define DEFAULT_THREADS 10
+#define DEFAULT_LOOPS 100
+
+PRIntn numThreads = DEFAULT_THREADS;
+PRIntn numIterations = DEFAULT_LOOPS;
+PRIntervalTime dally = PR_INTERVAL_NO_WAIT;
+PRFileDesc *debug_out = NULL;
+PRBool debug_mode = PR_FALSE;
+PRBool verbosity = PR_FALSE;
+
+typedef struct ThreadData {
+ PRFileDesc *event;
+ int index;
+ struct ThreadData *next;
+} ThreadData;
+
+void ThreadRoutine(void *arg)
+{
+ ThreadData *data = (ThreadData *) arg;
+ PRIntn i;
+ PRPollDesc pd;
+ PRInt32 rv;
+
+ pd.fd = data->event;
+ pd.in_flags = PR_POLL_READ;
+
+ for (i = 0; i < numIterations; i++) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d awakened\n", data->index);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d posting event\n", data->index);
+ }
+ if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "post event failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void Help(void)
+{
+ debug_out = PR_STDOUT;
+
+ PR_fprintf(
+ debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n");
+ PR_fprintf(
+ debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
+ PR_fprintf(
+ debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
+ PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
+ PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ ThreadData selfData;
+ ThreadData *data;
+ PRThread **thread;
+ void *block;
+ PRIntn i;
+ PRIntervalTime timeStart, timeEnd;
+ PRPollDesc pd;
+ PRInt32 rv;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRBool help = PR_FALSE;
+ PRUintn concurrency = 1;
+ PRUintn average;
+ PLOptStatus os;
+ PLOptState *opt;
+
+ PR_STDIO_INIT();
+
+ opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) {
+ continue;
+ }
+ switch (opt->option) {
+ case 'v': /* verbose mode */
+ verbosity = PR_TRUE;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ numIterations = atoi(opt->value);
+ break;
+ case 't': /* thread limit */
+ numThreads = atoi(opt->value);
+ break;
+ case 'C': /* Concurrency limit */
+ concurrency = atoi(opt->value);
+ break;
+ case 'G': /* global threads only */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'D': /* dally */
+ dally = PR_MillisecondsToInterval(atoi(opt->value));
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (help) {
+ return 1;
+ }
+
+ if (concurrency > 1) {
+ PR_SetConcurrency(concurrency);
+ }
+
+ if (PR_TRUE == debug_mode) {
+ debug_out = PR_STDOUT;
+ PR_fprintf(debug_out, "Test parameters\n");
+ PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads);
+ PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations);
+ PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(debug_out, "\tThread type: %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+ }
+
+ /*
+ * Malloc a block of memory and divide it into data and thread.
+ */
+ block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *)));
+ if (block == NULL) {
+ PR_fprintf(PR_STDERR, "cannot malloc, failed\n");
+ exit(1);
+ }
+ data = (ThreadData *) block;
+ thread = (PRThread **) &data[numThreads];
+
+ /* Pollable event */
+ selfData.event = PR_NewPollableEvent();
+ if (selfData.event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ selfData.next = &data[0];
+ for (i = 0; i < numThreads; i++) {
+ data[i].event = PR_NewPollableEvent();
+ if (data[i].event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ data[i].index = i;
+ if (i != numThreads - 1) {
+ data[i].next = &data[i + 1];
+ } else {
+ data[i].next = &selfData;
+ }
+
+ thread[i] = PR_CreateThread(PR_USER_THREAD,
+ ThreadRoutine, &data[i], PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (thread[i] == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create thread\n");
+ exit(1);
+ }
+ }
+
+ timeStart = PR_IntervalNow();
+ pd.fd = selfData.event;
+ pd.in_flags = PR_POLL_READ;
+ for (i = 0; i < numIterations; i++) {
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread posting event\n");
+ }
+ if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "set event failed\n");
+ exit(1);
+ }
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "wait failed\n");
+ exit(1);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread awakened\n");
+ }
+ if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ }
+ timeEnd = PR_IntervalNow();
+
+ if (debug_mode) {
+ average = PR_IntervalToMicroseconds(timeEnd - timeStart)
+ / (numIterations * numThreads);
+ PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n",
+ average, numThreads);
+ }
+
+ for (i = 0; i < numThreads; i++) {
+ if (PR_JoinThread(thread[i]) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "join thread failed\n");
+ exit(1);
+ }
+ PR_DestroyPollableEvent(data[i].event);
+ }
+ PR_DELETE(block);
+
+ PR_fprintf(PR_STDOUT, "PASSED\n");
+ return 0;
+}
diff --git a/pr/tests/prftest2.c b/pr/tests/prftest2.c
index b5322888..c3239905 100644
--- a/pr/tests/prftest2.c
+++ b/pr/tests/prftest2.c
@@ -105,6 +105,6 @@ int main( int argc, char *argv[])
else
{
printf("PASSED\n");
- return 1;
+ return 0;
}
}
diff --git a/pr/tests/priotest.c b/pr/tests/priotest.c
index cdc76953..f9df1528 100644
--- a/pr/tests/priotest.c
+++ b/pr/tests/priotest.c
@@ -42,7 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
-#define DEFAULT_DURATION 20
+#define DEFAULT_DURATION 5
static PRBool failed = PR_FALSE;
static PRIntervalTime oneSecond;
@@ -131,7 +131,7 @@ static void RudimentaryTests(void)
} /* RudimentataryTests */
-static void CreateThreads(PRInt32 *lowCount, PRInt32 *highCount)
+static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount)
{
(void)PR_CreateThread(
PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW,
diff --git a/pr/tests/provider.c b/pr/tests/provider.c
new file mode 100644
index 00000000..49428b3a
--- /dev/null
+++ b/pr/tests/provider.c
@@ -0,0 +1,1356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ *
+ * Notes:
+ * [1] lth. The call to Sleep() is a hack to get the test case to run
+ * on Windows 95. Without it, the test case fails with an error
+ * WSAECONNRESET following a recv() call. The error is caused by the
+ * server side thread termination without a shutdown() or closesocket()
+ * call. Windows docmunentation suggests that this is predicted
+ * behavior; that other platforms get away with it is ... serindipity.
+ * The test case should shutdown() or closesocket() before
+ * thread termination. I didn't have time to figure out where or how
+ * to do it. The Sleep() call inserts enough delay to allow the
+ * client side to recv() all his data before the server side thread
+ * terminates. Whew! ...
+ *
+ ** Modification History:
+ * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+ * The debug mode will print all of the printfs associated with this test.
+ * The regress mode will be the default mode. Since the regress tool limits
+ * the output to a one line status:PASS or FAIL,all of the printf statements
+ * have been handled with an if (debug_mode) statement.
+ */
+
+#include "prclist.h"
+#include "prcvar.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prtime.h"
+#include "prmem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prthread.h"
+
+#include "pprio.h"
+#include "primpl.h"
+
+#include "plstr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#if defined(XP_UNIX)
+#include <math.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+/*
+** This is the beginning of the test
+*/
+
+#define RECV_FLAGS 0
+#define SEND_FLAGS 0
+#define BUFFER_SIZE 1024
+#define DEFAULT_BACKLOG 5
+#define DEFAULT_PORT 12848
+#define DEFAULT_CLIENTS 1
+#define ALLOWED_IN_ACCEPT 1
+#define DEFAULT_CLIPPING 1000
+#define DEFAULT_WORKERS_MIN 1
+#define DEFAULT_WORKERS_MAX 1
+#define DEFAULT_SERVER "localhost"
+#define DEFAULT_EXECUTION_TIME 10
+#define DEFAULT_CLIENT_TIMEOUT 4000
+#define DEFAULT_SERVER_TIMEOUT 4000
+#define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH
+
+typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t;
+
+static void PR_CALLBACK Worker(void *arg);
+typedef struct CSPool_s CSPool_t;
+typedef struct CSWorker_s CSWorker_t;
+typedef struct CSServer_s CSServer_t;
+typedef enum Verbosity
+{
+ TEST_LOG_ALWAYS,
+ TEST_LOG_ERROR,
+ TEST_LOG_WARNING,
+ TEST_LOG_NOTICE,
+ TEST_LOG_INFO,
+ TEST_LOG_STATUS,
+ TEST_LOG_VERBOSE
+} Verbosity;
+
+static enum {
+ thread_nspr, thread_pthread, thread_sproc, thread_win32
+} thread_provider;
+
+static PRInt32 domain = AF_INET;
+static PRInt32 protocol = 6; /* TCP */
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE;
+static PRBool pthread_stats = PR_FALSE;
+static Verbosity verbosity = TEST_LOG_ALWAYS;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+struct CSWorker_s
+{
+ PRCList element; /* list of the server's workers */
+
+ PRThread *thread; /* this worker objects thread */
+ CSServer_t *server; /* back pointer to server structure */
+};
+
+struct CSPool_s
+{
+ PRCondVar *exiting;
+ PRCondVar *acceptComplete;
+ PRUint32 accepting, active, workers;
+};
+
+struct CSServer_s
+{
+ PRCList list; /* head of worker list */
+
+ PRLock *ml;
+ PRThread *thread; /* the main server thread */
+ PRCondVar *stateChange;
+
+ PRUint16 port; /* port we're listening on */
+ PRUint32 backlog; /* size of our listener backlog */
+ PRFileDesc *listener; /* the fd accepting connections */
+
+ CSPool_t pool; /* statistics on worker threads */
+ CSState_t state; /* the server's state */
+ struct /* controlling worker counts */
+ {
+ PRUint32 minimum, maximum, accepting;
+ } workers;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+};
+
+typedef struct CSDescriptor_s
+{
+ PRInt32 size; /* size of transfer */
+ char filename[60]; /* filename, null padded */
+} CSDescriptor_t;
+
+typedef struct CSClient_s
+{
+ PRLock *ml;
+ PRThread *thread;
+ PRCondVar *stateChange;
+ PRNetAddr serverAddress;
+
+ CSState_t state;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+} CSClient_t;
+
+#define TEST_LOG(l, p, a) \
+ do { \
+ if (debug_mode || (p <= verbosity)) printf a; \
+ } while (0)
+
+PRLogModuleInfo *cltsrv_log_file = NULL;
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+#define TEST_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+static void _MY_Assert(const char *s, const char *file, PRIntn ln)
+{
+ PL_PrintError(NULL);
+#if DEBUG
+ PR_Assert(s, file, ln);
+#endif
+} /* _MW_Assert */
+
+static PRBool Aborted(PRStatus rv)
+{
+ return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ?
+ PR_TRUE : PR_FALSE;
+}
+
+static void TimeOfDayMessage(const char *msg, PRThread* me)
+{
+ char buffer[100];
+ PRExplodedTime tod;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("%s(0x%p): %s\n", msg, me, buffer));
+} /* TimeOfDayMessage */
+
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRIntn index;
+ char buffer[1024];
+ PRFileDesc *fd = NULL;
+ PRUintn clipping = DEFAULT_CLIPPING;
+ CSClient_t *client = (CSClient_t*)arg;
+ PRThread *me = client->thread = PR_CurrentThread();
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT);
+
+
+ for (index = 0; index < sizeof(buffer); ++index)
+ buffer[index] = (char)index;
+
+ client->started = PR_IntervalNow();
+
+ PR_Lock(client->ml);
+ client->state = cs_run;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+
+ TimeOfDayMessage("Client started at", me);
+
+ while (cs_run == client->state)
+ {
+ PRInt32 bytes, descbytes, filebytes, netbytes;
+
+ (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
+ TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
+
+ fd = PR_Socket(domain, SOCK_STREAM, protocol);
+ TEST_ASSERT(NULL != fd);
+ rv = PR_Connect(fd, &client->serverAddress, timeout);
+ if (PR_FAILURE == rv)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): conection failed\n", me));
+ goto aborted;
+ }
+
+ memset(descriptor, 0, sizeof(*descriptor));
+ descriptor->size = PR_htonl(descbytes = rand() % clipping);
+ PR_snprintf(
+ descriptor->filename, sizeof(descriptor->filename),
+ "CS%p%p-%p.dat", client->started, me, client->operations);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
+ bytes = PR_Send(
+ fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
+ if (sizeof(CSDescriptor_t) != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send descriptor timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send data timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(bytes == filebytes);
+ netbytes += bytes;
+ }
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ if (Aborted(PR_FAILURE))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data aborted\n", me));
+ goto aborted;
+ }
+ else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto retry;
+ }
+ if (0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tClient(0x%p): unexpected end of stream\n",
+ PR_CurrentThread()));
+ break;
+ }
+ filebytes += bytes;
+ }
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+retry:
+ (void)PR_Close(fd); fd = NULL;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): disconnected from server\n", me));
+
+ PR_Lock(client->ml);
+ client->operations += 1;
+ client->bytesTransferred += 2 * descbytes;
+ rv = PR_WaitCondVar(client->stateChange, rand() % clipping);
+ PR_Unlock(client->ml);
+ if (Aborted(rv)) break;
+ }
+
+aborted:
+ client->stopped = PR_IntervalNow();
+
+ PR_ClearInterrupt();
+ if (NULL != fd) rv = PR_Close(fd);
+
+ PR_Lock(client->ml);
+ client->state = cs_exit;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+ PR_DELETE(descriptor);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
+ PR_CurrentThread(), client->operations, client->bytesTransferred));
+
+} /* Client */
+
+static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
+{
+ PRStatus drv, rv;
+ char buffer[1024];
+ PRFileDesc *file = NULL;
+ PRThread * me = PR_CurrentThread();
+ PRInt32 bytes, descbytes, netbytes, filebytes = 0;
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
+ bytes = PR_Recv(
+ fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto exit;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
+ }
+ goto exit;
+ }
+ if (0 == bytes)
+ {
+ rv = PR_FAILURE;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
+ goto exit;
+ }
+ descbytes = PR_ntohl(descriptor->size);
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
+ me, descbytes, descriptor->filename));
+
+ file = PR_Open(
+ descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(NULL != file);
+
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
+ goto aborted;
+ }
+ /*
+ * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED)
+ * on NT here. This is equivalent to ECONNRESET on Unix.
+ * -wtc
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ if(0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
+ rv = PR_FAILURE;
+ goto aborted;
+ }
+ filebytes += bytes;
+ netbytes = bytes;
+ /* The byte count for PR_Write should be positive */
+ MY_ASSERT(netbytes > 0);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
+ bytes = PR_Write(file, buffer, netbytes);
+ if (netbytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->operations += 1;
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
+ file = PR_Open(descriptor->filename, PR_RDONLY, 0);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
+ PR_CurrentThread()));
+ goto aborted;
+ }
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(NULL != file);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
+ bytes = PR_Read(file, buffer, filebytes);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(bytes > 0);
+ netbytes += bytes;
+ filebytes = bytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
+ goto aborted;
+ }
+ break;
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+aborted:
+ PR_ClearInterrupt();
+ if (NULL != file) PR_Close(file);
+ drv = PR_Delete(descriptor->filename);
+ TEST_ASSERT(PR_SUCCESS == drv);
+exit:
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
+
+ PR_DELETE(descriptor);
+
+#if defined(WIN95)
+ PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */
+#endif
+ return rv;
+} /* ProcessRequest */
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include "md/_pth.h"
+#include <pthread.h>
+
+static void *pthread_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus JoinThread(PRThread *thread)
+{
+ PRStatus rv;
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ rv = PR_JoinThread(thread);
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ rv = PR_SUCCESS;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ case thread_win32:
+#if defined(WIN32)
+ rv = PR_SUCCESS;
+ break;
+#endif
+ default:
+ rv = PR_FAILURE;
+ break;
+ }
+ return rv;
+} /* JoinThread */
+
+static PRStatus NewThread(
+ StartFn start, void *arg, PRThreadPriority prio, PRThreadState state)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ break;
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* NewThread */
+
+static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
+{
+ PRStatus rv;
+ CSWorker_t *worker = PR_NEWZAP(CSWorker_t);
+ worker->server = server;
+ PR_INIT_CLIST(&worker->element);
+ rv = NewThread(
+ Worker, worker, DEFAULT_SERVER_PRIORITY, PR_UNJOINABLE_THREAD);
+ if (PR_FAILURE == rv) PR_DELETE(worker);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
+ PR_CurrentThread(), worker->thread));
+
+ return rv;
+} /* CreateWorker */
+
+static void PR_CALLBACK Worker(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr from;
+ PRFileDesc *fd = NULL;
+ CSWorker_t *worker = (CSWorker_t*)arg;
+ CSServer_t *server = worker->server;
+ CSPool_t *pool = &server->pool;
+
+ PRThread *me = worker->thread = PR_CurrentThread();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
+
+ PR_Lock(server->ml);
+ PR_APPEND_LINK(&worker->element, &server->list);
+ pool->workers += 1; /* define our existance */
+
+ while (cs_run == server->state)
+ {
+ while (pool->accepting >= server->workers.accepting)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
+ me, pool->accepting));
+ rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
+ if (Aborted(rv) || (cs_run != server->state))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tWorker(0x%p): has been %s\n",
+ me, (Aborted(rv) ? "interrupted" : "stopped")));
+ goto exit;
+ }
+ }
+ pool->accepting += 1; /* how many are really in accept */
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): calling accept\n", me));
+ fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Lock(server->ml);
+ pool->accepting -= 1;
+ PR_NotifyCondVar(pool->acceptComplete);
+
+ if ((NULL == fd) && Aborted(PR_FAILURE))
+ {
+ if (NULL != server->listener)
+ {
+ PR_Close(server->listener);
+ server->listener = NULL;
+ }
+ goto exit;
+ }
+
+ if (NULL != fd)
+ {
+ /*
+ ** Create another worker of the total number of workers is
+ ** less than the minimum specified or we have none left in
+ ** accept() AND we're not over the maximum.
+ ** This sort of presumes that the number allowed in accept
+ ** is at least as many as the minimum. Otherwise we'll keep
+ ** creating new threads and deleting them soon after.
+ */
+ PRBool another =
+ ((pool->workers < server->workers.minimum) ||
+ ((0 == pool->accepting)
+ && (pool->workers < server->workers.maximum))) ?
+ PR_TRUE : PR_FALSE;
+ pool->active += 1;
+ PR_Unlock(server->ml);
+
+ if (another) (void)CreateWorker(server, pool);
+
+ rv = ProcessRequest(fd, server);
+ if (PR_SUCCESS != rv)
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
+ (void)PR_Close(fd); fd = NULL;
+
+ PR_Lock(server->ml);
+ pool->active -= 1;
+ }
+ }
+
+exit:
+ PR_ClearInterrupt();
+ PR_Unlock(server->ml);
+
+ if (NULL != fd)
+ {
+ (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ (void)PR_Close(fd);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
+
+ PR_Lock(server->ml);
+ pool->workers -= 1; /* undefine our existance */
+ PR_REMOVE_AND_INIT_LINK(&worker->element);
+ PR_NotifyCondVar(pool->exiting);
+ PR_Unlock(server->ml);
+
+ PR_DELETE(worker); /* destruction of the "worker" object */
+
+} /* Worker */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr serverAddress;
+ CSServer_t *server = (CSServer_t*)arg;
+ PRThread *me = server->thread = PR_CurrentThread();
+
+ server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
+
+ rv = PR_Bind(server->listener, &serverAddress);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Listen(server->listener, server->backlog);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ server->started = PR_IntervalNow();
+ TimeOfDayMessage("Server started at", me);
+
+ PR_Lock(server->ml);
+ server->state = cs_run;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ /*
+ ** Create the first worker (actually, a thread that accepts
+ ** connections and then processes the work load as needed).
+ ** From this point on, additional worker threads are created
+ ** as they are needed by existing worker threads.
+ */
+ rv = CreateWorker(server, &server->pool);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ /*
+ ** From here on this thread is merely hanging around as the contact
+ ** point for the main test driver. It's just waiting for the driver
+ ** to declare the test complete.
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): waiting for state change\n", me));
+
+ PR_Lock(server->ml);
+ while ((cs_run == server->state) && !Aborted(rv))
+ {
+ rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(server->ml);
+ PR_ClearInterrupt();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tServer(0x%p): shutting down workers\n", me));
+
+ /*
+ ** Get all the worker threads to exit. They know how to
+ ** clean up after themselves, so this is just a matter of
+ ** waiting for clorine in the pool to take effect. During
+ ** this stage we're ignoring interrupts.
+ */
+ server->workers.minimum = server->workers.maximum = 0;
+
+ PR_Lock(server->ml);
+ while (!PR_CLIST_IS_EMPTY(&server->list))
+ {
+ PRCList *head = PR_LIST_HEAD(&server->list);
+ CSWorker_t *worker = (CSWorker_t*)head;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
+ rv = PR_Interrupt(worker->thread);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_REMOVE_AND_INIT_LINK(head);
+ }
+
+ while (server->pool.workers > 0)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
+ me, server->pool.workers));
+ (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ server->state = cs_exit;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
+ me, server->operations, server->bytesTransferred));
+
+ if (NULL != server->listener) PR_Close(server->listener);
+ server->stopped = PR_IntervalNow();
+
+} /* Server */
+
+static void WaitForCompletion(PRIntn execution)
+{
+ while (execution > 0)
+ {
+ PRIntn dally = (execution > 30) ? 30 : execution;
+ PR_Sleep(PR_SecondsToInterval(dally));
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+ execution -= dally;
+ }
+} /* WaitForCompletion */
+
+static void Help(void)
+{
+ PR_fprintf(debug_out, "cltsrv test program usage:\n");
+ PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
+ PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
+ PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
+ PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n");
+ PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n");
+ PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'w')(n)\n");
+ PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n");
+#ifdef _PR_INET6
+ PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n");
+#endif /* _PR_INET6 */
+ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n");
+ PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n");
+ PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n");
+ PR_fprintf(debug_out, "\t-h this message\n");
+} /* Help */
+
+static Verbosity IncrementVerbosity(void)
+{
+ PRIntn verboge = (PRIntn)verbosity + 1;
+ return (Verbosity)verboge;
+} /* IncrementVerbosity */
+
+PRIntn main(PRIntn argc, char** argv)
+{
+ PRUintn index;
+ PRBool boolean;
+ CSClient_t *client;
+ PRStatus rv, joinStatus;
+ CSServer_t *server = NULL;
+
+ PRUintn backlog = DEFAULT_BACKLOG;
+ PRUintn clients = DEFAULT_CLIENTS;
+ const char *serverName = DEFAULT_SERVER;
+ PRBool serverIsLocal = PR_TRUE;
+ PRUintn accepting = ALLOWED_IN_ACCEPT;
+ PRUintn workersMin = DEFAULT_WORKERS_MIN;
+ PRUintn workersMax = DEFAULT_WORKERS_MAX;
+ PRIntn execution = DEFAULT_EXECUTION_TIME;
+
+ /*
+ * -G use global threads
+ * -a <n> threads allowed in accept
+ * -b <n> backlock for listen
+ * -c <threads> number of clients to create
+ * -w <threads> minimal number of server threads
+ * -W <threads> maximum number of server threads
+ * -e <seconds> duration of the test in seconds
+ * -s <string> dsn name of server (implies no server here)
+ * -v verbosity
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:T:vdhp");
+
+ debug_out = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'X': /* use XTP as transport */
+ protocol = 36;
+ break;
+#ifdef _PR_INET6
+ case '6': /* Use IPv6 */
+ domain = AF_INET6;
+ PR_SetIPv6Enable(PR_TRUE);
+ break;
+#endif /* _PR_INET6 */
+ case 'a': /* the value for accepting */
+ accepting = atoi(opt->value);
+ break;
+ case 'b': /* the value for backlock */
+ backlog = atoi(opt->value);
+ break;
+ case 'T': /* the thread provider */
+ if ('n' == *opt->value) thread_provider = thread_nspr;
+ else if ('p' == *opt->value) thread_provider = thread_pthread;
+ else if ('w' == *opt->value) thread_provider = thread_win32;
+ else {Help(); return 2; }
+ break;
+ case 'c': /* number of client threads */
+ clients = atoi(opt->value);
+ break;
+ case 'w': /* minimum server worker threads */
+ workersMin = atoi(opt->value);
+ break;
+ case 'W': /* maximum server worker threads */
+ workersMax = atoi(opt->value);
+ break;
+ case 'e': /* program execution time in seconds */
+ execution = atoi(opt->value);
+ break;
+ case 's': /* server's address */
+ serverName = opt->value;
+ break;
+ case 'v': /* verbosity */
+ verbosity = IncrementVerbosity();
+ break;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'p': /* pthread mode */
+ pthread_stats = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE;
+ if (0 == execution) execution = DEFAULT_EXECUTION_TIME;
+ if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX;
+ if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN;
+ if (0 == accepting) accepting = ALLOWED_IN_ACCEPT;
+ if (0 == backlog) backlog = DEFAULT_BACKLOG;
+
+ if (workersMin > accepting) accepting = workersMin;
+
+ PR_STDIO_INIT();
+ TimeOfDayMessage("Client/Server started at", PR_CurrentThread());
+
+ cltsrv_log_file = PR_NewLogModule("cltsrv_log");
+ MY_ASSERT(NULL != cltsrv_log_file);
+ boolean = PR_SetLogFile("cltsrv.log");
+ MY_ASSERT(boolean);
+
+#ifdef XP_MAC
+ debug_mode = PR_TRUE;
+#endif
+
+ if (serverIsLocal)
+ {
+ /* Establish the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
+
+ server = PR_NEWZAP(CSServer_t);
+ PR_INIT_CLIST(&server->list);
+ server->state = cs_init;
+ server->ml = PR_NewLock();
+ server->backlog = backlog;
+ server->port = DEFAULT_PORT;
+ server->workers.minimum = workersMin;
+ server->workers.maximum = workersMax;
+ server->workers.accepting = accepting;
+ server->stateChange = PR_NewCondVar(server->ml);
+ server->pool.exiting = PR_NewCondVar(server->ml);
+ server->pool.acceptComplete = PR_NewCondVar(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
+
+ rv = NewThread(
+ Server, server, PR_PRIORITY_HIGH, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
+
+ PR_Lock(server->ml);
+ while (server->state == cs_init)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): server init complete (port #%d)\n",
+ PR_CurrentThread(), server->port));
+ }
+
+ if (clients != 0)
+ {
+ /* Create all of the clients */
+ PRHostEnt host;
+ char buffer[BUFFER_SIZE];
+ client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t));
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): creating %d client threads\n",
+ PR_CurrentThread(), clients));
+
+ if (!serverIsLocal)
+ {
+ rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(PR_STDERR, "PR_GetHostByName");
+ return 2;
+ }
+ }
+
+ for (index = 0; index < clients; ++index)
+ {
+ client[index].state = cs_init;
+ client[index].ml = PR_NewLock();
+ if (serverIsLocal)
+ {
+ (void)PR_InitializeNetAddr(
+ PR_IpAddrLoopback, DEFAULT_PORT,
+ &client[index].serverAddress);
+ }
+ else
+ {
+ (void)PR_EnumerateHostEnt(
+ 0, &host, DEFAULT_PORT, &client[index].serverAddress);
+ }
+ client[index].stateChange = PR_NewCondVar(client[index].ml);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
+ rv = NewThread(
+ Client, &client[index], PR_PRIORITY_NORMAL, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_Lock(client[index].ml);
+ while (cs_init == client[index].state)
+ PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(client[index].ml);
+ }
+ }
+
+ /* Then just let them go at it for a bit */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
+ PR_CurrentThread(), execution));
+
+ WaitForCompletion(execution);
+
+ TimeOfDayMessage("Shutting down", PR_CurrentThread());
+
+ if (clients != 0)
+ {
+ for (index = 0; index < clients; ++index)
+ {
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("main(0x%p): notifying client(0x%p) to stop\n",
+ PR_CurrentThread(), client[index].thread));
+
+ PR_Lock(client[index].ml);
+ if (cs_run == client[index].state)
+ {
+ client[index].state = cs_stop;
+ PR_Interrupt(client[index].thread);
+ while (cs_stop == client[index].state)
+ PR_WaitCondVar(
+ client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(client[index].ml);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): joining client(0x%p)\n",
+ PR_CurrentThread(), client[index].thread));
+
+ joinStatus = JoinThread(client[index].thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+ PR_DestroyCondVar(client[index].stateChange);
+ PR_DestroyLock(client[index].ml);
+ }
+ PR_DELETE(client);
+ }
+
+ if (NULL != server)
+ {
+ /* All clients joined - retrieve the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): notifying server(0x%p) to stop\n",
+ PR_CurrentThread(), server->thread));
+
+ PR_Lock(server->ml);
+ server->state = cs_stop;
+ PR_Interrupt(server->thread);
+ while (cs_exit != server->state)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): joining server(0x%p)\n",
+ PR_CurrentThread(), server->thread));
+ joinStatus = JoinThread(server->thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+
+ PR_DestroyCondVar(server->stateChange);
+ PR_DestroyCondVar(server->pool.exiting);
+ PR_DestroyCondVar(server->pool.acceptComplete);
+ PR_DestroyLock(server->ml);
+ PR_DELETE(server);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
+
+ PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+
+ TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ return 0;
+} /* main */
+
+/* cltsrv.c */
diff --git a/pr/tests/sel_spd.c b/pr/tests/sel_spd.c
index f4ce1483..b0033567 100644
--- a/pr/tests/sel_spd.c
+++ b/pr/tests/sel_spd.c
@@ -51,6 +51,9 @@ typedef struct timer_slot_t {
unsigned long requests;
} timer_slot_t;
+static long _iterations = 5;
+static long _client_data = 8192;
+
#if defined(XP_MAC)
/*
* Mac does not scale well specially the requirement for thread stack
@@ -58,22 +61,18 @@ typedef struct timer_slot_t {
* memory and not be able to allocate thread stack or client/server data
* buffer.
*/
+static long _server_data = (8*1024);
static long _threads_max = 10, _threads = 10;
-static long _iterations = 50;
-static long _client_data = 8192;
-static long _server_data = 8192;
#else
-static long _threads_max = 100, _threads = 100;
-static long _iterations = 1000;
-static long _client_data = 8192;
static long _server_data = (128*1024);
+static long _threads_max = 100, _threads = 100;
#endif
-static long _thread_exit_count;
+static int verbose=0;
static PRMonitor *exit_cv;
+static long _thread_exit_count;
static timer_slot_t *timer_data;
static PRThreadScope scope1, scope2;
-static int verbose=0;
void tally_results(int);
diff --git a/pr/tests/socket.c b/pr/tests/socket.c
index 33ce32bb..770d5f71 100644
--- a/pr/tests/socket.c
+++ b/pr/tests/socket.c
@@ -373,7 +373,7 @@ UDP_Server(void *arg)
PRFileDesc *sockfd;
buffer *in_buf;
PRNetAddr netaddr;
- PRInt32 bytes, i, rv;
+ PRInt32 bytes, i, rv = 0;
bytes = sp->datalen;
@@ -1046,7 +1046,6 @@ TransmitFile_Client(void *arg)
fprintf(stderr,
"prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
failed_already=1;
- return;
}
#endif
PR_DELETE(small_buf);
@@ -1518,8 +1517,8 @@ done:
PR_DELETE(buf);
}
#ifdef XP_UNIX
- munmap(small_file_addr, SMALL_FILE_SIZE);
- munmap(large_file_addr, LARGE_FILE_SIZE);
+ munmap((char*)small_file_addr, SMALL_FILE_SIZE);
+ munmap((char*)large_file_addr, LARGE_FILE_SIZE);
#endif
PR_Close(small_file_fd);
PR_Close(large_file_fd);
diff --git a/pr/tests/stack.c b/pr/tests/stack.c
new file mode 100644
index 00000000..d48e3ddb
--- /dev/null
+++ b/pr/tests/stack.c
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+
+/*
+ *
+ * Test atomic stack operations
+ *
+ * Two stacks are created and threads add data items (each containing
+ * one of the first n integers) to the first stack, remove data items
+ * from the first stack and add them to the second stack. The primordial
+ * thread compares the sum of the first n integers to the sum of the
+ * integers in the data items in the second stack. The test succeeds if
+ * they are equal.
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+typedef struct _DataRecord {
+ PRInt32 data;
+ PRStackElem link;
+} DataRecord;
+
+#define RECORD_LINK_PTR(lp) ((DataRecord*) ((char*) (lp) - offsetof(DataRecord,link)))
+
+#define MAX_THREAD_CNT 100
+#define DEFAULT_THREAD_CNT 4
+#define DEFAULT_DATA_CNT 4
+/*
+ * sum of the first n numbers using the formula n*(n+1)/2
+ */
+#define SUM_OF_NUMBERS(n) ((n & 1) ? (((n + 1)/2) * n) : ((n/2) * (n+1)))
+
+typedef struct stack_data {
+ PRStack *list1;
+ PRStack *list2;
+ PRInt32 initial_data_value;
+ PRInt32 data_cnt;
+} stack_data;
+
+static void stackop(void *arg);
+
+static int _debug_on;
+
+PRFileDesc *output;
+PRFileDesc *errhandle;
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRInt32 rv, cnt, sum;
+ DataRecord *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ PRStatus rc;
+
+ PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
+ PRInt32 data_cnt = DEFAULT_DATA_CNT;
+ PRThread **threads;
+ stack_data *thread_args;
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ case 'c': /* data count */
+ data_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(4);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ errhandle = PR_GetSpecialFD(PR_StandardError);
+ list1 = PR_CreateStack("Stack_1");
+ if (list1 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+ list2 = PR_CreateStack("Stack_2");
+ if (list2 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
+ thread_args = (stack_data *) PR_CALLOC(sizeof(stack_data) * thread_cnt);
+
+ if (_debug_on)
+ PR_fprintf(output,"%s: thread_cnt = %d data_cnt = %d\n", argv[0],
+ thread_cnt, data_cnt);
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ PRThreadScope scope;
+
+ thread_args[cnt].list1 = list1;
+ thread_args[cnt].list2 = list2;
+ thread_args[cnt].data_cnt = data_cnt;
+ thread_args[cnt].initial_data_value = 1 + cnt * data_cnt;
+
+ if (cnt & 1)
+ scope = PR_GLOBAL_THREAD;
+ else
+ scope = PR_LOCAL_THREAD;
+
+
+ threads[cnt] = PR_CreateThread(PR_USER_THREAD,
+ stackop, &thread_args[cnt],
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (threads[cnt] == NULL) {
+ PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
+ PR_GetError());
+ PR_ProcessExit(2);
+ }
+ if (_debug_on)
+ PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
+ threads[cnt]);
+ }
+
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
+
+ node = PR_StackPop(list1);
+ /*
+ * list1 should be empty
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 1 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+
+ cnt = data_cnt * thread_cnt;
+ sum = 0;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list2);
+ /*
+ * There should be at least 'cnt' number of records
+ */
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ProcessExit(3);
+ }
+ Item = RECORD_LINK_PTR(node);
+ sum += Item->data;
+ }
+ node = PR_StackPop(list2);
+ /*
+ * there should be exactly 'cnt' number of records
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 2 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+ PR_DELETE(threads);
+ PR_DELETE(thread_args);
+
+ PR_DestroyStack(list1);
+ PR_DestroyStack(list2);
+
+ if (sum == SUM_OF_NUMBERS(data_cnt * thread_cnt)) {
+ PR_fprintf(output, "%s successful\n", argv[0]);
+ PR_fprintf(output, "\t\tsum = 0x%x, expected = 0x%x\n", sum,
+ SUM_OF_NUMBERS(thread_cnt * data_cnt));
+ return 0;
+ } else {
+ PR_fprintf(output, "%s failed: sum = 0x%x, expected = 0x%x\n",
+ argv[0], sum,
+ SUM_OF_NUMBERS(data_cnt * thread_cnt));
+ return 2;
+ }
+}
+
+static void stackop(void *thread_arg)
+{
+ PRInt32 val, cnt, index;
+ DataRecord *Items, *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ stack_data *arg = (stack_data *) thread_arg;
+
+ val = arg->initial_data_value;
+ cnt = arg->data_cnt;
+ list1 = arg->list1;
+ list2 = arg->list2;
+
+ /*
+ * allocate memory for the data records
+ */
+ Items = (DataRecord *) PR_CALLOC(sizeof(DataRecord) * cnt);
+ PR_ASSERT(Items != NULL);
+ index = 0;
+
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d data1 = 0x%x datan = 0x%x\n",
+ PR_GetCurrentThread(), val, cnt, &Items[0], &Items[cnt-1]);
+
+
+ /*
+ * add the data records to list1
+ */
+ while (cnt-- > 0) {
+ Items[index].data = val++;
+ PR_StackPush(list1, &Items[index].link);
+ index++;
+ }
+
+ /*
+ * remove the data records from list1 and add them to list2
+ */
+ cnt = arg->data_cnt;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list1);
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ASSERT(node != NULL);
+ PR_ProcessExit(3);
+ }
+ PR_StackPush(list2, node);
+ }
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d exiting\n",
+ PR_GetCurrentThread(), val, cnt);
+
+}
+
diff --git a/pr/tests/switch.c b/pr/tests/switch.c
index 131260fc..878d7d15 100644
--- a/pr/tests/switch.c
+++ b/pr/tests/switch.c
@@ -63,14 +63,14 @@ static void Help(void)
debug_out = PR_STDOUT;
PR_fprintf(
- debug_out, "Usage: >./switch [-d] [-c n] [-t n] [-T n] [-G]\n");
+ debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
PR_fprintf(
debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
PR_fprintf(
debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
- PR_fprintf(debug_out, "-G n\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
} /* Help */
diff --git a/pr/tests/testfile.c b/pr/tests/testfile.c
index d492a0ff..2f5129d4 100644
--- a/pr/tests/testfile.c
+++ b/pr/tests/testfile.c
@@ -44,7 +44,6 @@ extern void SetupMacPrintfLog(char *logFile);
PRLock *lock;
PRMonitor *mon;
-PRMonitor *mon2;
PRInt32 count;
int thread_count;
@@ -108,11 +107,12 @@ int offset, len;
}
DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf))));
PR_Close(fd_file);
+ PR_DELETE(fp);
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
--thread_count;
- PR_Notify(mon2);
- PR_ExitMonitor(mon2);
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
}
static void PR_CALLBACK File_Read(void *arg)
@@ -143,11 +143,12 @@ int offset, len;
}
DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf))));
PR_Close(fd_file);
+ PR_DELETE(fp);
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
--thread_count;
- PR_Notify(mon2);
- PR_ExitMonitor(mon2);
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
}
@@ -295,6 +296,7 @@ static PRInt32 PR_CALLBACK FileTest(void)
PRDir *fd_dir;
int i, offset, len;
PRThread *t;
+PRThreadScope scope;
File_Rdwr_Param *fparamp;
/*
@@ -334,12 +336,7 @@ File_Rdwr_Param *fparamp;
*/
offset = 0;
len = CHUNK_SIZE;
- mon2 = PR_NewMonitor();
- if (mon2 == NULL) {
- printf("testfile: PR_NewMonitor failed\n");
- return -1;
- }
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
for (i = 0; i < NUM_RDWR_THREADS; i++) {
fparamp = PR_NEW(File_Rdwr_Param);
if (fparamp == NULL) {
@@ -356,27 +353,24 @@ File_Rdwr_Param *fparamp;
* Create LOCAL and GLOBAL Threads, alternately
*/
if (i % 1)
- t = PR_CreateThread(PR_USER_THREAD,
- File_Write, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_GLOBAL_THREAD;
else
- t = PR_CreateThread(PR_USER_THREAD,
- File_Write, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_LOCAL_THREAD;
+
+ t = PR_CreateThread(PR_USER_THREAD,
+ File_Write, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
offset += len;
}
thread_count = i;
/* Wait for writer threads to exit */
while (thread_count) {
- PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
}
- PR_ExitMonitor(mon2);
+ PR_ExitMonitor(mon);
/*
@@ -384,7 +378,7 @@ File_Rdwr_Param *fparamp;
*/
offset = 0;
len = CHUNK_SIZE;
- PR_EnterMonitor(mon2);
+ PR_EnterMonitor(mon);
for (i = 0; i < NUM_RDWR_THREADS; i++) {
fparamp = PR_NEW(File_Rdwr_Param);
if (fparamp == NULL) {
@@ -400,19 +394,16 @@ File_Rdwr_Param *fparamp;
* Create LOCAL and GLOBAL Threads, alternately
*/
if (i % 1)
- t = PR_CreateThread(PR_USER_THREAD,
- File_Read, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_LOCAL_THREAD;
else
- t = PR_CreateThread(PR_USER_THREAD,
- File_Read, (void *)fparamp,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0);
+ scope = PR_GLOBAL_THREAD;
+
+ t = PR_CreateThread(PR_USER_THREAD,
+ File_Read, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
offset += len;
if ((offset + len) > BUF_DATA_SIZE)
break;
@@ -421,9 +412,9 @@ File_Rdwr_Param *fparamp;
/* Wait for reader threads to exit */
while (thread_count) {
- PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
}
- PR_ExitMonitor(mon2);
+ PR_ExitMonitor(mon);
if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
printf("File Test failed: file data corrupted\n");
@@ -759,7 +750,7 @@ HANDLE hfile;
* Test file and directory NSPR APIs
*/
-void main(int argc, char **argv)
+int main(int argc, char **argv)
{
#ifdef XP_UNIX
int opt;
@@ -784,7 +775,11 @@ void main(int argc, char **argv)
SetupMacPrintfLog("testfile.log");
#endif
- mon2 = PR_NewMonitor();
+ mon = PR_NewMonitor();
+ if (mon == NULL) {
+ printf("testfile: PR_NewMonitor failed\n");
+ exit(2);
+ }
if (FileTest() < 0) {
printf("File Test failed\n");
@@ -798,5 +793,7 @@ void main(int argc, char **argv)
}
printf("Dir Test passed\n");
+ PR_DestroyMonitor(mon);
PR_Cleanup();
+ return 0;
}
diff --git a/pr/tests/tpd.c b/pr/tests/tpd.c
index 9afce87c..786948e4 100644
--- a/pr/tests/tpd.c
+++ b/pr/tests/tpd.c
@@ -21,6 +21,7 @@
** Description: Exercising the thread private data bailywick.
*/
+#include "prmem.h"
#include "prinit.h"
#include "prlog.h"
#include "prprf.h"
@@ -42,18 +43,20 @@ static PRBool should = PR_TRUE;
static PRBool did = PR_TRUE;
static PRFileDesc *fout = NULL;
-static void PrintProgress(void)
+static void PrintProgress(PRIntn line)
{
+ failed = failed || (should && !did);
+ failed = failed || (!should && did);
if (debug > 0)
{
#if defined(WIN16)
printf(
- "Destructor should %s have been called and was%s\n",
- ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+ "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
#else
PR_fprintf(
- fout, "Destructor should %s have been called and was%s\n",
- ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+ fout, "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
#endif
}
} /* PrintProgress */
@@ -70,10 +73,15 @@ static void MyAssert(const char *expr, const char *file, PRIntn line)
static void PR_CALLBACK Destructor(void *data)
{
+ MY_ASSERT(NULL != data);
if (should) did = PR_TRUE;
else failed = PR_TRUE;
- MY_ASSERT(NULL != data);
- if (debug > 0) MyAssert((const char*)data, __FILE__, __LINE__);
+ /*
+ * We don't actually free the storage since it's actually allocated
+ * on the stack. Normally, this would not be the case and this is
+ * the opportunity to free whatever.
+ PR_Free(data);
+ */
} /* Destructor */
static void PR_CALLBACK Thread(void *null)
@@ -91,24 +99,24 @@ static void PR_CALLBACK Thread(void *null)
pd = PR_GetThreadPrivate(key[keys]);
MY_ASSERT(NULL == pd);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#if !defined(DEBUG)
did = should = PR_FALSE;
for (keys = 4; keys < 8; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_FAILURE == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#endif
did = PR_FALSE; should = PR_TRUE;
@@ -117,7 +125,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 0; keys < 4; ++keys)
@@ -125,7 +133,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
@@ -133,7 +141,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -141,7 +149,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 8; keys < 127; ++keys)
@@ -149,7 +157,7 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -157,6 +165,17 @@ static void PR_CALLBACK Thread(void *null)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
+
+ /* put in keys and leave them there for thread exit */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+ did = PR_FALSE; should = PR_TRUE;
+
} /* Thread */
static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
@@ -177,7 +196,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 8; ++keys)
@@ -185,24 +204,24 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
pd = PR_GetThreadPrivate(key[keys]);
MY_ASSERT(NULL == pd);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#if !defined(DEBUG)
did = should = PR_FALSE;
for (keys = 4; keys < 8; ++keys)
{
- rv = PR_SetThreadPrivate(keys, key_string[keys]);
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_FAILURE == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
#endif
did = PR_FALSE; should = PR_TRUE;
@@ -211,7 +230,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 0; keys < 4; ++keys)
@@ -219,7 +238,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 0; keys < 4; ++keys)
@@ -227,7 +246,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -237,7 +256,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = PR_FALSE; should = PR_TRUE;
for (keys = 8; keys < 127; ++keys)
@@ -245,7 +264,7 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
rv = PR_SetThreadPrivate(key[keys], NULL);
MY_ASSERT(PR_SUCCESS == rv);
}
- PrintProgress();
+ PrintProgress(__LINE__);
did = should = PR_FALSE;
for (keys = 8; keys < 127; ++keys)
@@ -260,6 +279,8 @@ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
(void)PR_JoinThread(thread);
+ PrintProgress(__LINE__);
+
#if defined(WIN16)
printf(
"%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
diff --git a/pr/tests/udpsrv.c b/pr/tests/udpsrv.c
index 4e9292d1..d45421d4 100644
--- a/pr/tests/udpsrv.c
+++ b/pr/tests/udpsrv.c
@@ -64,13 +64,6 @@
#include <string.h>
#include <errno.h>
-/* --- manifest constants --- */
-#ifdef XP_MAC
-#define fprintf(a,b) printf(b)
-#include "prlog.h"
-#define printf PR_LogPrint
-#endif
-
#ifdef XP_PC
#define mode_t int
#endif
@@ -93,12 +86,13 @@ static PRIntn _debug_on = 0;
static PRBool passed = PR_TRUE;
static PRUint32 cltBytesRead = 0;
static PRUint32 srvBytesRead = 0;
+static PRFileDesc *output = NULL;
/* --- static function declarations --- */
-#define DPRINTF(arg) if (_debug_on) printf(arg)
+#define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
+
-
/*******************************************************************
** ListNetAddr() -- Display the Net Address on stdout
**
@@ -122,7 +116,7 @@ void ListNetAddr( char *msg, PRNetAddr *na )
DPRINTF( mbuf );
#endif
} /* --- end ListNetAddr() --- */
-
+
/********************************************************************
** UDP_Server() -- Test a UDP server application
**
@@ -155,7 +149,9 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( svrSock == NULL )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
return;
}
@@ -174,7 +170,7 @@ static void PR_CALLBACK UDP_Server( void *arg )
{
if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
{
- if (debug_mode) printf("udpsrv: UDP_Server(): \
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
PR_Sleep( PR_MillisecondsToInterval( 2000 ));
continue;
@@ -182,7 +178,7 @@ static void PR_CALLBACK UDP_Server( void *arg )
else
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): \
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
PR_Bind(): failed: %ld with error: %ld\n",
rv, PR_GetError() );
PR_Close( svrSock );
@@ -202,8 +198,10 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
- PR_GetError() );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
+ PR_GetError() );
PR_Close( svrSock );
return;
}
@@ -223,8 +221,10 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
- PR_GetError() );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
+ PR_GetError() );
PR_Close( svrSock );
return;
}
@@ -237,14 +237,16 @@ static void PR_CALLBACK UDP_Server( void *arg )
if ( rv != PR_SUCCESS )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
return;
}
DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
} /* --- end UDP_Server() --- */
-
+
static char cltBuf[UDP_BUF_SIZE];
static char cltBufin[UDP_BUF_SIZE];
/********************************************************************
@@ -284,7 +286,9 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( cltSock == NULL )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
return;
}
@@ -307,14 +311,18 @@ static void PR_CALLBACK UDP_Client( void *arg )
{
if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
{
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
PR_Sleep( PR_MillisecondsToInterval( 2000 ));
continue;
}
else
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
rv, PR_GetError() );
PR_Close( cltSock );
return;
@@ -352,7 +360,7 @@ static void PR_CALLBACK UDP_Client( void *arg )
writeThisMany -= numBytes;
{
char mbuf[256];
- sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %ld, numbytes: %ld\n",
+ sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n",
writeThisMany, numBytes );
DPRINTF( mbuf );
}
@@ -362,7 +370,9 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
PR_GetError() );
PR_Close( cltSock );
return;
@@ -376,7 +386,8 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv == -1 )
{
passed = PR_FALSE;
- if (debug_mode) printf( "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
PR_GetError() );
PR_Close( cltSock );
return;
@@ -393,12 +404,13 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
continue;
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): return data mismatch\n" );
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): return data mismatch\n" );
PR_Close( cltSock );
return;
}
}
- if (debug_mode) printf(".");
+ if (debug_mode) PR_fprintf(output, ".");
}
/* --- Close the socket --- */
@@ -407,12 +419,13 @@ static void PR_CALLBACK UDP_Client( void *arg )
if ( rv != PR_SUCCESS )
{
passed = PR_FALSE;
- if (debug_mode) printf("udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
return;
}
DPRINTF("udpsrv: UDP_Client(): ending\n" );
} /* --- end UDP_Client() --- */
-
+
/********************************************************************
** main() -- udpsrv
**
@@ -461,6 +474,7 @@ int main(int argc, char **argv)
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
PR_STDIO_INIT();
+ output = PR_STDERR;
#ifdef XP_MAC
SetupMacPrintfLog("udpsrv.log");
@@ -481,7 +495,7 @@ int main(int argc, char **argv)
0 );
if ( srv == NULL )
{
- if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
passed = PR_FALSE;
}
@@ -504,7 +518,7 @@ int main(int argc, char **argv)
0 );
if ( clt == NULL )
{
- if (debug_mode) printf( "udpsrv: Cannot create server thread\n" );
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
passed = PR_FALSE;
}
@@ -518,7 +532,7 @@ int main(int argc, char **argv)
/*
** Evaluate test results
*/
- if (debug_mode) printf( "\n\nudpsrv: main(): cltBytesRead(%ld), \
+ if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
srvBytesRead(%ld), expected(%ld)\n",
cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
diff --git a/pr/tests/version.c b/pr/tests/version.c
new file mode 100644
index 00000000..c5c3013d
--- /dev/null
+++ b/pr/tests/version.c
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlink.h"
+#include "prvrsion.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv = 1;
+ PLOptStatus os;
+ PRIntn verbosity = 0;
+ PRLibrary *runtime = NULL;
+ const char *library_name = NULL;
+ const PRVersionDescription *version_info;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* fully qualified library name */
+ library_name = opt->value;
+ break;
+ case 'd': /* verbodity */
+ verbosity += 1;
+ break;
+ default:
+ PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n");
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (NULL == library_name)
+ PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n");
+ else
+ {
+ runtime = PR_LoadLibrary(library_name);
+ if (NULL == runtime) PL_FPrintError(err, "PR_LoadLibrary");
+ else
+ {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint) PL_FPrintError(err, "PR_FindSymbol");
+ else
+ {
+ char buffer[100];
+ PRExplodedTime exploded;
+ version_info = versionPoint();
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ rv = 0;
+ }
+ }
+ }
+ return rv;
+}
+
+/* version.c */