summaryrefslogtreecommitdiff
path: root/pr
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 /pr
parent299a8c91a9d819a6d8e38032447c052271fc41e8 (diff)
downloadnspr-hg-a5cf3a954c0d28455f78eaffcd2067e961972933.tar.gz
NSPR20 v3.0 beta landing from NSPRPUB_RELEASE_3_0_LANDING_BRANCH.
Diffstat (limited to 'pr')
-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
185 files changed, 20071 insertions, 8019 deletions
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 */