diff options
author | cvs2hg <devnull@localhost> | 2004-04-16 22:28:04 +0000 |
---|---|---|
committer | cvs2hg <devnull@localhost> | 2004-04-16 22:28:04 +0000 |
commit | f4c156a0df550fc3ccb6395b97ff98b612723b3b (patch) | |
tree | 513ada980b1cc6324ec31920d6b5da061e049c92 /pr | |
parent | 57c2cc83bfe90fe3b51c3c8ba1e0cd8a7dc9636a (diff) | |
download | nspr-hg-f4c156a0df550fc3ccb6395b97ff98b612723b3b.tar.gz |
fixup commit for branch 'AVIARY_1_0_20040515_BRANCH'THUNDERBIRD_0_6_RELEASETHUNDERBIRD_0_6_BASENETSCAPE_7_2_RELEASEMOZILLA_1_7_RELEASEMOZILLA_1_7_RC3MOZILLA_1_7_RC2MOZILLA_1_7_RC1MOZILLA_1_7_3_RELEASEMOZILLA_1_7_2_RELEASEMOZILLA_1_7_2_BASEMOZILLA_1_7_1_RELEASECAMINO_0_8_RELEASECAMINO_0_8_BETACAMINO_0_8_1_RELEASEAVIARY_20040809_MERGEPOINTAVIARY_1_0_20040515_BASE
Diffstat (limited to 'pr')
172 files changed, 10088 insertions, 3384 deletions
diff --git a/pr/include/md/Makefile.in b/pr/include/md/Makefile.in index 316c4540..5f8f0f71 100644 --- a/pr/include/md/Makefile.in +++ b/pr/include/md/Makefile.in @@ -46,21 +46,22 @@ CONFIGS = $(wildcard $(srcdir)/*.cfg) include $(topsrcdir)/config/rules.mk export:: $(MDCPUCFG_H) - $(INSTALL) -m 444 $(srcdir)/$(MDCPUCFG_H) $(dist_includedir) $(INSTALL) -m 444 $(CONFIGS) $(HEADERS) $(dist_includedir)/md -ifneq ($(OS_ARCH),OpenVMS) - mv -f $(dist_includedir)/$(MDCPUCFG_H) $(dist_includedir)/prcpucfg.h + $(INSTALL) -m 444 $(srcdir)/$(MDCPUCFG_H) $(dist_includedir) +ifeq ($(OS_ARCH),OpenVMS) +# On OpenVMS mv updates the file's modified time, so we create a hard link. + cd $(dist_includedir); \ + if test ! -f prcpucfg.h; then \ + dcl set file /enter=prcpucfg.h $(MDCPUCFG_H); \ + fi else -# mv'ing a link causes the file itself to move, not the link. - rm -f $(dist_includedir)/$(MDCPUCFG_H) - rm -f $(dist_includedir)/prcpucfg.h - ln -fs $(srcdir)/$(MDCPUCFG_H) $(dist_includedir)/prcpucfg.h + mv -f $(dist_includedir)/$(MDCPUCFG_H) $(dist_includedir)/prcpucfg.h endif real_install:: $(NSINSTALL) -D $(DESTDIR)$(includedir)/md cp $(srcdir)/$(MDCPUCFG_H) $(DESTDIR)$(includedir)/prcpucfg.h - $(NSINSTALL) -t -m 644 $(CONFIG) $(HEADERS) $(DESTDIR)$(includedir)/md + $(NSINSTALL) -t -m 644 $(HEADERS) $(DESTDIR)$(includedir)/md release:: export @echo "Copying machine-dependent prcpucfg.h" diff --git a/pr/include/md/_aix.h b/pr/include/md/_aix.h index d8d79eeb..6e89d52d 100644 --- a/pr/include/md/_aix.h +++ b/pr/include/md/_aix.h @@ -57,7 +57,8 @@ #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 -#define _MD_DEFAULT_STACK_SIZE 65536L +#define _MD_DEFAULT_STACK_SIZE (2*65536L) +#define _MD_MINIMUM_STACK_SIZE (2*65536L) #define _MD_MMAP_FLAGS MAP_PRIVATE #define NEED_TIME_R @@ -71,7 +72,9 @@ #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO #endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY @@ -243,4 +246,6 @@ struct _MDCPU { #define _MD_POLL poll #endif +extern void _MD_aix_map_sendfile_error(int err); + #endif /* nspr_aix_defs_h___ */ diff --git a/pr/include/md/_aix32.cfg b/pr/include/md/_aix32.cfg index 8047bb98..0bf01957 100644 --- a/pr/include/md/_aix32.cfg +++ b/pr/include/md/_aix32.cfg @@ -134,6 +134,9 @@ #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 +/* used by protypes.h only */ +#define _PR_AIX_HAVE_BSD_INT_TYPES + #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ diff --git a/pr/include/md/_aix32in6.cfg b/pr/include/md/_aix32in6.cfg deleted file mode 100644 index 0bf01957..00000000 --- a/pr/include/md/_aix32in6.cfg +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape Portable Runtime (NSPR). - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#ifndef nspr_cpucfg___ -#define nspr_cpucfg___ - -#ifndef XP_UNIX -#define XP_UNIX -#endif - -#ifndef AIX -#define AIX -#endif - -#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_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 4 -#define PR_ALIGN_OF_POINTER 4 - -#define HAVE_LONG_LONG -#undef HAVE_ALIGNED_DOUBLES -#undef HAVE_ALIGNED_LONGLONGS - -#define PR_AF_INET6 24 /* same as AF_INET6 */ - -#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 - -/* used by protypes.h only */ -#define _PR_AIX_HAVE_BSD_INT_TYPES - -#endif /* NO_NSPR_10_SUPPORT */ - -#endif /* nspr_cpucfg___ */ diff --git a/pr/include/md/_beos.h b/pr/include/md/_beos.h index 232fea3c..1f69bd66 100644 --- a/pr/include/md/_beos.h +++ b/pr/include/md/_beos.h @@ -51,6 +51,10 @@ * Internal configuration macros */ +#ifdef BONE_VERSION +#define _PR_HAVE_SOCKADDR_LEN +#endif + #define PR_LINKER_ARCH "beos" #define _PR_SI_SYSNAME "BEOS" #ifdef __powerpc__ @@ -87,6 +91,7 @@ #define _PR_HAVE_PEEK_BUFFER #define _PR_PEEK_BUFFER_MAX (16 * 1024) #define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) 1 +#define _PR_CONNECT_DOES_NOT_BIND /* Define threading functions and objects as native BeOS */ struct _MDThread { @@ -141,17 +146,21 @@ struct _MDSegment { ** File- and directory-related definitions */ +#ifndef BONE_VERSION #define BE_SOCK_SHUTDOWN_READ 0x01 #define BE_SOCK_SHUTDOWN_WRITE 0x02 +#endif struct _MDFileDesc { PRInt32 osfd; PRInt32 sock_state; PRBool accepted_socket; PRNetAddr peer_addr; +#ifndef BONE_VERSION PRBool connectValueValid; int connectReturnValue; int connectReturnError; +#endif }; struct _MDDir { @@ -175,14 +184,17 @@ struct _MDFileMap { * Network related definitions. */ +#ifndef BONE_VERSION #define IPPROTO_IP 0 #define AF_UNIX 2 #define TCP_NODELAY SO_NONBLOCK #define SO_LINGER -1 #define SO_ERROR 4 +#endif #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 +#ifndef BONE_VERSION /* these aren't actually used. if they are, we're screwed */ struct protoent { char *p_name; /* official protocol name */ @@ -192,6 +204,7 @@ struct protoent { struct protoent* getprotobyname(const char* name); struct protoent* getprotobynumber(int number); +#endif /* * malloc() related definitions. @@ -304,6 +317,7 @@ struct protoent* getprotobynumber(int number); #define _MD_READ_DIR _MD_read_dir #define _MD_CLOSE_DIR _MD_close_dir #define _MD_MAKE_NONBLOCK _MD_make_nonblock +#define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable #define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable #define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable #define _MD_OPEN _MD_open @@ -509,7 +523,7 @@ NSPR_API(PRInt32) _MD_open(const char *name, PRIntn osflags, PRIntn mode); NSPR_API(PRInt32) _MD_close_file(PRInt32 osfd); NSPR_API(PRInt32) _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount); NSPR_API(PRInt32) _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount); -NSPR_API(PRInt32) _MD_writev(PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); +NSPR_API(PRInt32) _MD_writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_lseek(PRFileDesc *fd, PRInt32 offset, int whence); NSPR_API(PRInt64) _MD_lseek64(PRFileDesc *fd, PRInt64 offset, int whence); NSPR_API(PRInt32) _MD_fsync(PRFileDesc *fd); diff --git a/pr/include/md/_bsdi.h b/pr/include/md/_bsdi.h index c529649f..14eca99e 100644 --- a/pr/include/md/_bsdi.h +++ b/pr/include/md/_bsdi.h @@ -39,6 +39,8 @@ * Internal configuration macros */ +#include <sys/param.h> /* for _BSDI_VERSION */ + #define PR_LINKER_ARCH "bsdi" #define _PR_SI_SYSNAME "BSDI" #if defined(__i386__) @@ -61,6 +63,16 @@ #define USE_SETJMP +/* BSD/OS 4.3 and newer all have IPv6 support */ +#if _BSDI_VERSION >= 200105 +#define _PR_INET6 +#define _PR_HAVE_INET_NTOP +#define _PR_HAVE_GETIPNODEBYNAME +#define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE +#endif + #ifndef _PR_PTHREADS #include <setjmp.h> diff --git a/pr/include/md/_darwin.cfg b/pr/include/md/_darwin.cfg index d06492b8..22fc1083 100644 --- a/pr/include/md/_darwin.cfg +++ b/pr/include/md/_darwin.cfg @@ -39,10 +39,6 @@ #define XP_UNIX #endif -#ifndef DARWIN -#define DARWIN -#endif - #define PR_AF_INET6 30 /* same as AF_INET6 */ #if defined(i386) diff --git a/pr/include/md/_darwin.h b/pr/include/md/_darwin.h index d262849c..38b9ead7 100644 --- a/pr/include/md/_darwin.h +++ b/pr/include/md/_darwin.h @@ -61,6 +61,44 @@ #define _PR_NO_LARGE_FILES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#define _PR_INET6 +/* + * I'd prefer to use getipnodebyname and getipnodebyaddr but the + * getipnodebyname(3) man page on Mac OS X 10.2 says they are not + * thread-safe. AI_V4MAPPED|AI_ADDRCONFIG doesn't work either. + */ +#define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO +/* + * On Mac OS X 10.2, gethostbyaddr fails with h_errno=NO_RECOVERY + * if you pass an IPv4-mapped IPv6 address to it. + */ +#define _PR_GHBA_DISALLOW_V4MAPPED +/* + * socket(AF_INET6) fails with EPROTONOSUPPORT on Mac OS X 10.1. + * IPv6 under OS X 10.2 and below is not complete (see bug 222031). + */ +#if MACOS_DEPLOYMENT_TARGET < 100300 +#define _PR_INET6_PROBE +#endif +/* Mac OS X 10.2 has inet_ntop and inet_pton. */ +#if MACOS_DEPLOYMENT_TARGET >= 100200 +#define _PR_HAVE_INET_NTOP +#endif + +#if defined(__ppc__) +#define _PR_HAVE_ATOMIC_OPS +#define _MD_INIT_ATOMIC() +extern PRInt32 _PR_DarwinPPC_AtomicIncrement(PRInt32 *val); +#define _MD_ATOMIC_INCREMENT(val) _PR_DarwinPPC_AtomicIncrement(val) +extern PRInt32 _PR_DarwinPPC_AtomicDecrement(PRInt32 *val); +#define _MD_ATOMIC_DECREMENT(val) _PR_DarwinPPC_AtomicDecrement(val) +extern PRInt32 _PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval); +#define _MD_ATOMIC_SET(val, newval) _PR_DarwinPPC_AtomicSet(val, newval) +extern PRInt32 _PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val); +#define _MD_ATOMIC_ADD(ptr, val) _PR_DarwinPPC_AtomicAdd(ptr, val) +#endif /* __ppc__ */ + #define USE_SETJMP #if !defined(_PR_PTHREADS) diff --git a/pr/include/md/_freebsd.cfg b/pr/include/md/_freebsd.cfg index ad04ca20..056efcdd 100644 --- a/pr/include/md/_freebsd.cfg +++ b/pr/include/md/_freebsd.cfg @@ -43,16 +43,16 @@ #define FREEBSD #endif +#define PR_AF_INET6 28 /* same as AF_INET6 */ + +#if defined(__i386__) + #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_LONG_LONG #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS -#define PR_AF_INET6 28 /* same as AF_INET6 */ - -#if defined(__i386__) - #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 @@ -98,6 +98,54 @@ #define HAVE_LONG_LONG #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS +#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 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 + +#elif defined(__sparc__) + +#undef IS_LITTLE_ENDIAN +#define IS_BIG_ENDIAN 1 +#define HAVE_LONG_LONG +#define HAVE_ALIGNED_DOUBLES +#define HAVE_ALIGNED_LONGLONGS +#define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 diff --git a/pr/include/md/_freebsd.h b/pr/include/md/_freebsd.h index 0671b60f..7018f6b5 100644 --- a/pr/include/md/_freebsd.h +++ b/pr/include/md/_freebsd.h @@ -37,6 +37,9 @@ #include "prthread.h" +#if __FreeBSD__ >= 2 +#include <osreldate.h> /* for __FreeBSD_version */ +#endif #include <sys/syscall.h> #define PR_LINKER_ARCH "freebsd" @@ -45,6 +48,8 @@ #define _PR_SI_ARCHITECTURE "x86" #elif defined(__alpha) #define _PR_SI_ARCHITECTURE "alpha" +#elif defined(__sparc__) +#define _PR_SI_ARCHITECTURE "sparc" #else #error "Unknown CPU architecture" #endif @@ -65,19 +70,34 @@ #define _PR_HAVE_SOCKADDR_LEN #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_NO_LARGE_FILES -#if ( __FreeBSD__ > 2 ) -#if !defined(_PR_PTHREADS) + +#if defined(_PR_PTHREADS) +#if __FreeBSD_version >= 400008 /* - * libc_r doesn't have poll(). Although libc has poll(), it is not - * thread-safe so we can't use it in the pthreads version. + * libc_r before this version of FreeBSD doesn't have poll(). + * Although libc has poll(), it is not thread-safe so we can't + * use it in the pthreads version. */ #define _PR_POLL_AVAILABLE +#endif +#else +#if __FreeBSD_version >= 300000 +#define _PR_POLL_AVAILABLE #define _PR_USE_POLL #endif #endif + #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#if __FreeBSD_version >= 400014 +#define _PR_INET6 +#define _PR_HAVE_INET_NTOP +#define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE +#endif + #define USE_SETJMP #ifndef _PR_PTHREADS diff --git a/pr/include/md/_hpux.h b/pr/include/md/_hpux.h index c83e7c3c..bf8569b3 100644 --- a/pr/include/md/_hpux.h +++ b/pr/include/md/_hpux.h @@ -46,7 +46,14 @@ #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 -#define _MD_DEFAULT_STACK_SIZE 65536L +/* + * _USE_BIG_FDS increases the size of fd_set from 256 bytes to + * about 7500 bytes. PR_Poll allocates three fd_sets on the + * stack, so it is safer to also increase the default thread + * stack size. + */ +#define _MD_DEFAULT_STACK_SIZE (2*65536L) +#define _MD_MINIMUM_STACK_SIZE (2*65536L) #define _MD_MMAP_FLAGS MAP_PRIVATE #define NEED_TIME_R @@ -55,19 +62,16 @@ #undef HAVE_WEAK_IO_SYMBOLS #undef HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL +#ifdef IS_64 +#define USE_DLFCN +#else #define USE_HPSHL +#endif #ifndef HAVE_STRERROR #define HAVE_STRERROR #endif #define _PR_POLL_AVAILABLE #define _PR_USE_POLL -/* - * OSF1 and HPUX report the POLLHUP event for a socket when the - * shutdown(SHUT_WR) operation is called for the remote end, even though - * the socket is still writeable. Use select(), instead of poll(), to - * workaround this problem. - */ -#define _PR_POLL_WITH_SELECT #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY @@ -75,6 +79,14 @@ #undef _PR_HAVE_ATOMIC_OPS +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#define _PR_HAVE_GETIPNODEBYNAME +#define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE +#endif + #if !defined(_PR_PTHREADS) #include <syscall.h> diff --git a/pr/include/md/_hpux64.cfg b/pr/include/md/_hpux64.cfg index bacd0272..338e3016 100644 --- a/pr/include/md/_hpux64.cfg +++ b/pr/include/md/_hpux64.cfg @@ -82,8 +82,8 @@ #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_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 diff --git a/pr/include/md/_irix.h b/pr/include/md/_irix.h index 09067002..e09b2638 100644 --- a/pr/include/md/_irix.h +++ b/pr/include/md/_irix.h @@ -78,6 +78,13 @@ #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define _PR_ACCEPT_INHERIT_NONBLOCK +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#define _PR_HAVE_GETIPNODEBYNAME +#define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO +#endif + /* Initialization entry points */ NSPR_API(void) _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit diff --git a/pr/include/md/_linux.cfg b/pr/include/md/_linux.cfg index 301f4590..6a25d498 100644 --- a/pr/include/md/_linux.cfg +++ b/pr/include/md/_linux.cfg @@ -182,6 +182,52 @@ #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 +#elif defined(__x86_64__) + +#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_ALIGN_OF_WORD 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + #elif defined(__mc68000__) #undef IS_LITTLE_ENDIAN @@ -414,6 +460,142 @@ #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 +#elif defined(__hppa__) + +#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 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 PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#elif defined(__s390__) + +#define IS_BIG_ENDIAN 1 +#undef IS_LITTLE_ENDIAN + +#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_ALIGN_OF_WORD 4 + +#define PR_BYTES_PER_WORD_LOG2 2 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#elif defined(__s390x__) + +#define IS_BIG_ENDIAN 1 +#undef IS_LITTLE_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_ALIGN_OF_WORD 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + #else #error "Unknown CPU architecture" diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h index 86ea248c..b18e1e6f 100644 --- a/pr/include/md/_linux.h +++ b/pr/include/md/_linux.h @@ -49,6 +49,8 @@ #define _PR_SI_ARCHITECTURE "alpha" #elif defined(__ia64__) #define _PR_SI_ARCHITECTURE "ia64" +#elif defined(__x86_64__) +#define _PR_SI_ARCHITECTURE "x86-64" #elif defined(__mc68000__) #define _PR_SI_ARCHITECTURE "m68k" #elif defined(__sparc__) @@ -59,6 +61,12 @@ #define _PR_SI_ARCHITECTURE "mips" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" +#elif defined(__hppa__) +#define _PR_SI_ARCHITECTURE "hppa" +#elif defined(__s390__) +#define _PR_SI_ARCHITECTURE "s390" +#elif defined(__s390x__) +#define _PR_SI_ARCHITECTURE "s390x" #else #error "Unknown CPU architecture" #endif @@ -103,6 +111,19 @@ extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_ia64_AtomicSet #endif +#if defined(__x86_64__) +#define _PR_HAVE_ATOMIC_OPS +#define _MD_INIT_ATOMIC() +extern PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val); +#define _MD_ATOMIC_INCREMENT _PR_x86_64_AtomicIncrement +extern PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val); +#define _MD_ATOMIC_DECREMENT _PR_x86_64_AtomicDecrement +extern PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val); +#define _MD_ATOMIC_ADD _PR_x86_64_AtomicAdd +extern PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval); +#define _MD_ATOMIC_SET _PR_x86_64_AtomicSet +#endif + #define USE_SETJMP #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _PR_POLL_AVAILABLE @@ -118,7 +139,9 @@ extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval); #endif #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #endif #define _PR_HAVE_SYSV_SEMAPHORES @@ -470,4 +493,6 @@ extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds, /* For writev() */ #include <sys/uio.h> +extern void _MD_linux_map_sendfile_error(int err); + #endif /* nspr_linux_defs_h___ */ diff --git a/pr/include/md/_macos.h b/pr/include/md/_macos.h index f1f0f8aa..90eb07db 100644 --- a/pr/include/md/_macos.h +++ b/pr/include/md/_macos.h @@ -65,6 +65,7 @@ #include <Errors.h> #include <OpenTransport.h> +#include <DriverServices.h> #define _PR_HAVE_PEEK_BUFFER #define _PR_PEEK_BUFFER_MAX (16 * 1024) @@ -105,7 +106,9 @@ struct _MDSegment { }; struct _MDCPU { - PRInt8 notused; + AbsoluteTime lastThreadSwitch; + AbsoluteTime lastWakeUpProcess; + PRBool trackScheduling; }; typedef struct _MDSocketCallerInfo { @@ -114,19 +117,22 @@ typedef struct _MDSocketCallerInfo { } _MDSocketCallerInfo; struct _MDFileDesc { - PRInt32 osfd; - PRBool orderlyDisconnect; - PRBool readReady; - PRBool writeReady; - PRBool exceptReady; - PRLock * miscLock; - - /* Server sockets: listen bit tells the notifier func what to do */ - PRBool doListen; - - _MDSocketCallerInfo misc; - _MDSocketCallerInfo read; - _MDSocketCallerInfo write; + PRInt32 osfd; + PRPackedBool orderlyDisconnect; + PRPackedBool readReady; + PRPackedBool writeReady; + PRPackedBool exceptReady; + PRLock * miscLock; + + /* Server sockets: listen bit tells the notifier func what to do */ + PRBool doListen; + + /* stored error for non-blocking connects, as a Unix-style error code */ + OTReason disconnectError; + + _MDSocketCallerInfo misc; + _MDSocketCallerInfo read; + _MDSocketCallerInfo write; }; /* @@ -172,7 +178,7 @@ extern void _MD_SetIntsOff(PRInt32 ints); #define _MD_CLEANUP_BEFORE_EXIT() #define _MD_EXIT(status) exit(status) #define _MD_INIT_CPUS() -#define _MD_INIT_RUNNING_CPU(cpu) +#define _MD_INIT_RUNNING_CPU(cpu) _MD_InitRunningCPU(cpu) /* ** Process Related definitions @@ -296,16 +302,20 @@ extern PRStatus _MD_InitThread(PRThread *thread); ** context switch because it might have changed. */ /* ResetTimer(); before _PR_Schedule() */ -#define _MD_SWITCH_CONTEXT(_thread) \ - PR_BEGIN_MACRO \ - PR_ASSERT(_thread->no_sched); \ - if (!setjmp(_thread->md.jb)) { \ - _MD_SET_LAST_THREAD(_thread); \ - _PR_Schedule(); \ - } else { \ - PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \ - _MD_LAST_THREAD()->no_sched = 0; \ - } \ + + +#define _MD_SWITCH_CONTEXT(_thread) \ + PR_BEGIN_MACRO \ + PR_ASSERT(_thread->no_sched); \ + if (!setjmp(_thread->md.jb)) { \ + _MD_SET_LAST_THREAD(_thread); \ + if (_PR_MD_CURRENT_CPU()->md.trackScheduling) \ + _PR_MD_CURRENT_CPU()->md.lastThreadSwitch = UpTime(); \ + _PR_Schedule(); \ + } else { \ + PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \ + _MD_LAST_THREAD()->no_sched = 0; \ + } \ PR_END_MACRO /* @@ -473,6 +483,7 @@ extern PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, c */ extern PRStatus _MD_gethostname(char *name, int namelen); #define _MD_GETHOSTNAME _MD_gethostname +#define _PR_GET_HOST_ADDR_AS_NAME /* XXX _MD_WRITEV, _MD_SHUTDOWN & _MD_GETPEERNAME not done yet!!! @@ -514,7 +525,6 @@ extern PRStatus _MD_gethostname(char *name, int namelen); ** Time Related definitions */ -#define kMacTimerInMiliSecs 8L #define _MD_GET_INTERVAL _MD_GetInterval #define _MD_INTERVAL_PER_SEC() PR_MSEC_PER_SEC #define _MD_INTERVAL_INIT() @@ -647,7 +657,7 @@ extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap); #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap extern void SetLogFileTypeCreator(const char *logFile); -extern int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd); +extern int _MD_mac_get_nonblocking_connect_error(PRFileDesc* fd); /* @@ -681,6 +691,18 @@ extern void LeaveCritialRegion(); #endif + +/* + * CPU Idle support + */ + +extern void InitIdleSemaphore(); +extern void TermIdleSemaphore(); + +extern void WaitOnIdleSemaphore(); +extern void SignalIdleSemaphore(); + + /* * Atomic operations */ diff --git a/pr/include/md/_netbsd.h b/pr/include/md/_netbsd.h index 1e70994d..cd829df3 100644 --- a/pr/include/md/_netbsd.h +++ b/pr/include/md/_netbsd.h @@ -80,7 +80,9 @@ #if __NetBSD_Version__ >= 105000000 #define _PR_INET6 +#define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #endif diff --git a/pr/include/md/_nto.h b/pr/include/md/_nto.h index de6b8033..052f2b15 100644 --- a/pr/include/md/_nto.h +++ b/pr/include/md/_nto.h @@ -46,6 +46,7 @@ #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L +#define _MD_MINIMUM_STACK_SIZE 131072L #define _MD_MMAP_FLAGS MAP_PRIVATE #ifndef HAVE_WEAK_IO_SYMBOLS @@ -212,4 +213,6 @@ struct _MDCPU { */ #define _MD_SELECT select +#define SA_RESTART 0 + #endif /* nspr_nto_defs_h___ */ diff --git a/pr/include/md/_openbsd.cfg b/pr/include/md/_openbsd.cfg index 8721a429..2eec1fdc 100644 --- a/pr/include/md/_openbsd.cfg +++ b/pr/include/md/_openbsd.cfg @@ -45,7 +45,7 @@ #define PR_AF_INET6 24 /* same as AF_INET6 */ -#if defined(__i386__) || defined(__arm32__) +#if defined(__i386__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN @@ -91,9 +91,107 @@ #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 +#elif defined(__amd64__) + +#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_ALIGN_OF_WORD 8 + +#define PR_BYTES_PER_WORD_LOG2 3 +#define PR_BYTES_PER_DWORD_LOG2 3 + +#define HAVE_LONG_LONG +#define HAVE_ALIGNED_DOUBLES +#define HAVE_ALIGNED_LONGLONGS + +#elif defined(__sparc_v9__) + +#undef IS_LITTLE_ENDIAN +#define IS_BIG_ENDIAN 1 +#define HAVE_LONG_LONG +#define HAVE_ALIGNED_DOUBLES +#define HAVE_ALIGNED_LONGLONGS +#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(__sparc__) -#undef IS_LITTLE_ENDIAN 1 +#undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_LONG_LONG #define HAVE_ALIGNED_DOUBLES diff --git a/pr/include/md/_openbsd.h b/pr/include/md/_openbsd.h index 20535e55..f254e319 100644 --- a/pr/include/md/_openbsd.h +++ b/pr/include/md/_openbsd.h @@ -43,14 +43,14 @@ #define _PR_SI_ARCHITECTURE "x86" #elif defined(__alpha__) #define _PR_SI_ARCHITECTURE "alpha" +#elif defined(__amd64__) +#define _PR_SI_ARCHITECTURE "amd64" #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" @@ -71,6 +71,12 @@ #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#define _PR_INET6 +#define _PR_HAVE_INET_NTOP +#define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE + #define USE_SETJMP #ifndef _PR_PTHREADS @@ -80,19 +86,14 @@ #define CONTEXT(_th) ((_th)->md.context) -#if defined(__i386__) || defined(__sparc__) || defined(__m68k__) || defined(__powerpc__) +#if defined(__i386__) || defined(__sparc__) || defined(__m68k__) #define JB_SP_INDEX 2 +#elif defined(__powerpc__) +#define JB_SP_INDEX 1 #elif defined(__alpha__) #define JB_SP_INDEX 34 -#elif defined(__arm32__) -/* - * On the arm32, the jmpbuf regs underwent a name change after OpenBSD 1.3. - */ -#ifdef JMPBUF_REG_R13 -#define JB_SP_INDEX JMPBUF_REG_R13 -#else -#define JB_SP_INDEX _JB_REG_R13 -#endif +#elif defined(__amd64__) +#define JB_SP_INDEX 6 #else #error "Need to define SP index in jmp_buf here" #endif diff --git a/pr/include/md/_openvms.h b/pr/include/md/_openvms.h index b0a2af6f..040ff46d 100644 --- a/pr/include/md/_openvms.h +++ b/pr/include/md/_openvms.h @@ -97,6 +97,7 @@ struct ip_mreq { #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_NO_LARGE_FILES +#define _PR_STRICT_ADDR_LEN /* IPv6 support */ #ifdef _SOCKADDR_LEN @@ -104,9 +105,25 @@ struct ip_mreq { #endif #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x00000002 +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif #define AI_V4MAPPED 0x00000010 #define AI_ALL 0x00000008 #define AI_ADDRCONFIG 0x00000020 diff --git a/pr/include/md/_os2.h b/pr/include/md/_os2.h index d98262d1..4f97703a 100644 --- a/pr/include/md/_os2.h +++ b/pr/include/md/_os2.h @@ -47,18 +47,32 @@ #include <errno.h> -#ifdef XP_OS2_EMX -/* - * EMX-specific tweaks: - * o Use stricmp instead of strcmpi. - * o Use errno rather than sock_errno() - * o Use close rather than soclose - * o Ignore sock_init calls. - */ -#define strcmpi stricmp -#define sock_errno() errno -#define soclose close -#define sock_init() +#ifdef XP_OS2_VACPP +/* TODO RAMSEMs need to be written for GCC/EMX */ +#define USE_RAMSEM +#endif + +#ifdef USE_RAMSEM +#pragma pack(4) + +#pragma pack(2) +typedef struct _RAMSEM +{ + ULONG ulTIDPID; + ULONG hevSem; + ULONG cLocks; + USHORT cWaiting; + USHORT cPosts; +} RAMSEM, *PRAMSEM; + +typedef struct _CRITICAL_SECTION +{ + ULONG ulReserved[4]; /* Same size as RAMSEM */ +} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; +#pragma pack(4) + +APIRET _Optlink SemRequest486(PRAMSEM, ULONG); +APIRET _Optlink SemReleasex86(PRAMSEM, ULONG); #endif /* @@ -70,7 +84,9 @@ #define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */ #define HAVE_DLL +#define _PR_GLOBAL_THREADS_ONLY #undef HAVE_THREAD_AFFINITY +#define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #define HANDLE unsigned long @@ -162,7 +178,11 @@ struct _MDNotified { }; struct _MDLock { - HMTX mutex; /* this is recursive on NT */ +#ifdef USE_RAMSEM + CRITICAL_SECTION mutex; /* this is recursive on NT */ +#else + HMTX mutex; /* this is recursive on NT */ +#endif /* * When notifying cvars, there is no point in actually @@ -222,6 +242,9 @@ extern PRInt32 _MD_CloseFile(PRInt32 osfd); /* --- Socket IO stuff --- */ +#define TCPV40HDRS +#define BSD_SELECT + /* The ones that don't map directly may need to be re-visited... */ #ifdef XP_OS2_VACPP #define EPIPE EBADF @@ -258,37 +281,31 @@ extern void _MD_MakeNonblock(PRFileDesc *f); #define _MD_INIT_FD_INHERITABLE (_PR_MD_INIT_FD_INHERITABLE) #define _MD_QUERY_FD_INHERITABLE (_PR_MD_QUERY_FD_INHERITABLE) #define _MD_SHUTDOWN (_PR_MD_SHUTDOWN) -#define _MD_LISTEN(s, backlog) listen(s->secret->md.osfd,backlog) +#define _MD_LISTEN _PR_MD_LISTEN extern PRInt32 _MD_CloseSocket(PRInt32 osfd); #define _MD_CLOSE_SOCKET _MD_CloseSocket #define _MD_SENDTO (_PR_MD_SENDTO) #define _MD_RECVFROM (_PR_MD_RECVFROM) -#define _MD_SOCKETPAIR(s, type, proto, sv) -1 +#define _MD_SOCKETPAIR (_PR_MD_SOCKETPAIR) #define _MD_GETSOCKNAME (_PR_MD_GETSOCKNAME) #define _MD_GETPEERNAME (_PR_MD_GETPEERNAME) #define _MD_GETSOCKOPT (_PR_MD_GETSOCKOPT) #define _MD_SETSOCKOPT (_PR_MD_SETSOCKOPT) -#ifdef XP_OS2_EMX -extern PRInt32 _MD_SELECT(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout); -#else -#define _MD_SELECT select -#endif - #define _MD_FSYNC _PR_MD_FSYNC #define _MD_SET_FD_INHERITABLE (_PR_MD_SET_FD_INHERITABLE) +#ifdef _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT #define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD #define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT #define _MD_ATOMIC_SET _PR_MD_ATOMIC_SET +#endif #define _MD_INIT_IO (_PR_MD_INIT_IO) #define _MD_PR_POLL (_PR_MD_PR_POLL) -/* win95 doesn't have async IO */ #define _MD_SOCKET (_PR_MD_SOCKET) extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd); #define _MD_SOCKETAVAILABLE _MD_SocketAvailable @@ -349,11 +366,33 @@ extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, #define _PR_LOCK _MD_LOCK #define _PR_UNLOCK _MD_UNLOCK +#ifdef USE_RAMSEM +#define _MD_NEW_LOCK (_PR_MD_NEW_LOCK) +#define _MD_FREE_LOCK(lock) (DosCloseEventSem(((PRAMSEM)(&((lock)->mutex)))->hevSem)) +#define _MD_LOCK(lock) (SemRequest486(&((lock)->mutex), -1)) +#define _MD_TEST_AND_LOCK(lock) (SemRequest486(&((lock)->mutex), -1),0) +#define _MD_UNLOCK(lock) \ + PR_BEGIN_MACRO \ + if (0 != (lock)->notified.length) { \ + md_UnlockAndPostNotifies((lock), NULL, NULL); \ + } else { \ + SemReleasex86( &(lock)->mutex, 0 ); \ + } \ + PR_END_MACRO +#else #define _MD_NEW_LOCK (_PR_MD_NEW_LOCK) -#define _MD_FREE_LOCK (_PR_MD_FREE_LOCK) -#define _MD_LOCK (_PR_MD_LOCK) -#define _MD_TEST_AND_LOCK (_PR_MD_TEST_AND_LOCK) -#define _MD_UNLOCK (_PR_MD_UNLOCK) +#define _MD_FREE_LOCK(lock) (DosCloseMutexSem((lock)->mutex)) +#define _MD_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT)) +#define _MD_TEST_AND_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT),0) +#define _MD_UNLOCK(lock) \ + PR_BEGIN_MACRO \ + if (0 != (lock)->notified.length) { \ + md_UnlockAndPostNotifies((lock), NULL, NULL); \ + } else { \ + DosReleaseMutexSem((lock)->mutex); \ + } \ + PR_END_MACRO +#endif /* --- lock and cv waiting --- */ #define _MD_WAIT (_PR_MD_WAIT) @@ -408,7 +447,10 @@ extern PRStatus _PR_KillOS2Process(struct PRProcess *process); #define _MD_CLEANUP_BEFORE_EXIT() #define _MD_EXIT (_PR_MD_EXIT) -#define _MD_INIT_CONTEXT +#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ + PR_BEGIN_MACRO \ + *status = PR_TRUE; \ + PR_END_MACRO #define _MD_SWITCH_CONTEXT #define _MD_RESTORE_CONTEXT @@ -431,7 +473,8 @@ typedef struct __NSPR_TLS extern _NSPR_TLS* pThreadLocalStorage; NSPR_API(void) _PR_MD_ENSURE_TLS(void); -#define _MD_CURRENT_THREAD() pThreadLocalStorage->_pr_currentThread +#define _MD_GET_ATTACHED_THREAD() pThreadLocalStorage->_pr_currentThread +extern struct PRThread * _MD_CURRENT_THREAD(void); #define _MD_SET_CURRENT_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentThread = (_thread) #define _MD_LAST_THREAD() pThreadLocalStorage->_pr_thread_last_run @@ -537,4 +580,6 @@ unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long fla #define FreeLibrary(x) DosFreeModule((HMODULE)x) #define OutputDebugString(x) +extern int _MD_os2_get_nonblocking_connect_error(int osfd); + #endif /* nspr_os2_defs_h___ */ diff --git a/pr/include/md/_os2_errors.h b/pr/include/md/_os2_errors.h index f77e8f6e..b872fac8 100644 --- a/pr/include/md/_os2_errors.h +++ b/pr/include/md/_os2_errors.h @@ -40,14 +40,17 @@ #include <assert.h> #endif +NSPR_API(void) _MD_os2_map_default_error(PRInt32 err); +#define _PR_MD_MAP_DEFAULT_ERROR _MD_os2_map_default_error + NSPR_API(void) _MD_os2_map_opendir_error(PRInt32 err); #define _PR_MD_MAP_OPENDIR_ERROR _MD_os2_map_opendir_error NSPR_API(void) _MD_os2_map_closedir_error(PRInt32 err); #define _PR_MD_MAP_CLOSEDIR_ERROR _MD_os2_map_closedir_error -NSPR_API(void) _MD_unix_readdir_error(PRInt32 err); -#define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error +NSPR_API(void) _MD_os2_readdir_error(PRInt32 err); +#define _PR_MD_MAP_READDIR_ERROR _MD_os2_readdir_error NSPR_API(void) _MD_os2_map_delete_error(PRInt32 err); #define _PR_MD_MAP_DELETE_ERROR _MD_os2_map_delete_error @@ -103,6 +106,9 @@ NSPR_API(void) _MD_os2_map_send_error(PRInt32 err); NSPR_API(void) _MD_os2_map_sendto_error(PRInt32 err); #define _PR_MD_MAP_SENDTO_ERROR _MD_os2_map_sendto_error +NSPR_API(void) _MD_os2_map_writev_error(int err); +#define _PR_MD_MAP_WRITEV_ERROR _MD_os2_map_writev_error + NSPR_API(void) _MD_os2_map_accept_error(PRInt32 err); #define _PR_MD_MAP_ACCEPT_ERROR _MD_os2_map_accept_error @@ -121,6 +127,9 @@ NSPR_API(void) _MD_os2_map_listen_error(PRInt32 err); NSPR_API(void) _MD_os2_map_shutdown_error(PRInt32 err); #define _PR_MD_MAP_SHUTDOWN_ERROR _MD_os2_map_shutdown_error +NSPR_API(void) _MD_os2_map_socketpair_error(int err); +#define _PR_MD_MAP_SOCKETPAIR_ERROR _MD_os2_map_socketpair_error + NSPR_API(void) _MD_os2_map_getsockname_error(PRInt32 err); #define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_os2_map_getsockname_error diff --git a/pr/include/md/_osf1.h b/pr/include/md/_osf1.h index edf2fa3d..1fa43e22 100644 --- a/pr/include/md/_osf1.h +++ b/pr/include/md/_osf1.h @@ -60,20 +60,29 @@ #define _PR_POLL_AVAILABLE #define _PR_USE_POLL -/* - * OSF1 and HPUX report the POLLHUP event for a socket when the - * shutdown(SHUT_WR) operation is called for the remote end, even though - * the socket is still writeable. Use select(), instead of poll(), to - * workaround this problem. - */ -#define _PR_POLL_WITH_SELECT #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_LARGE_OFF_T #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x00000002 +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif #define AI_V4MAPPED 0x00000010 #define AI_ALL 0x00000008 #define AI_ADDRCONFIG 0x00000020 diff --git a/pr/include/md/_pth.h b/pr/include/md/_pth.h index faa50377..1846fbbc 100644 --- a/pr/include/md/_pth.h +++ b/pr/include/md/_pth.h @@ -91,7 +91,11 @@ #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_destroy #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), &(a)) #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m))) +#if defined(DARWIN) +#define _PT_PTHREAD_CONDATTR_INIT(x) 0 +#else #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_init +#endif #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_destroy #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), &(a)) #endif @@ -182,21 +186,20 @@ #endif /* - * These platforms don't have pthread_atfork() + * These platforms don't have sigtimedwait() */ -#if defined(_PR_DCETHREADS) || defined(FREEBSD) \ - || (defined(LINUX) && defined(__alpha)) \ - || defined(NETBSD) || defined(OPENBSD) -#define PT_NO_ATFORK +#if (defined(AIX) && !defined(AIX4_3_PLUS)) || defined(LINUX) \ + || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ + || defined(BSDI) || defined(VMS) || defined(UNIXWARE) \ + || defined(DARWIN) +#define PT_NO_SIGTIMEDWAIT #endif /* - * These platforms don't have sigtimedwait() + * These platforms don't have pthread_kill() */ -#if (defined(AIX) && !defined(AIX4_3)) || defined(LINUX) \ - || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ - || defined(BSDI) || defined(VMS) || defined(UNIXWARE) -#define PT_NO_SIGTIMEDWAIT +#if defined(DARWIN) +#define pthread_kill(thread, sig) ENOSYS #endif #if defined(OSF1) || defined(VMS) @@ -225,7 +228,7 @@ #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER) #endif /* defined(_PR_DCETHREADS) */ -#elif defined(LINUX) +#elif defined(LINUX) || defined(FREEBSD) #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER) #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER) #elif defined(NTO) @@ -245,7 +248,10 @@ */ #define PT_PRIO_MIN 1 #define PT_PRIO_MAX 127 -#elif defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ +#elif defined(OPENBSD) +#define PT_PRIO_MIN 0 +#define PT_PRIO_MAX 31 +#elif defined(NETBSD) \ || defined(BSDI) || defined(DARWIN) || defined(UNIXWARE) /* XXX */ #define PT_PRIO_MIN 0 #define PT_PRIO_MAX 126 diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h index a6412b69..ba4b3216 100644 --- a/pr/include/md/_solaris.h +++ b/pr/include/md/_solaris.h @@ -41,7 +41,13 @@ #define PR_LINKER_ARCH "solaris" #define _PR_SI_SYSNAME "SOLARIS" +#ifdef sparc #define _PR_SI_ARCHITECTURE "sparc" +#elif defined(i386) +#define _PR_SI_ARCHITECTURE "x86" +#else +#error unknown processor +#endif #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 @@ -103,10 +109,24 @@ #endif #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR +#define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #define _PR_ACCEPT_INHERIT_NONBLOCK -#ifndef _PR_INET6 +#ifdef _PR_INET6 +#define _PR_HAVE_INET_NTOP +#else #define AF_INET6 26 +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#define AI_CANONNAME 0x0010 #define AI_V4MAPPED 0x0001 #define AI_ALL 0x0002 #define AI_ADDRCONFIG 0x0004 @@ -213,6 +233,7 @@ extern struct PRLock *_pr_schedLock; #define THREAD_KEY_T thread_key_t +extern struct PRThread *_pr_attached_thread_tls(); extern struct PRThread *_pr_current_thread_tls(); extern struct _PRCPU *_pr_current_cpu_tls(); extern struct PRThread *_pr_last_thread_tls(); @@ -221,6 +242,7 @@ extern THREAD_KEY_T threadid_key; extern THREAD_KEY_T cpuid_key; extern THREAD_KEY_T last_thread_key; +#define _MD_GET_ATTACHED_THREAD() _pr_attached_thread_tls() #define _MD_CURRENT_THREAD() _pr_current_thread_tls() #define _MD_CURRENT_CPU() _pr_current_cpu_tls() #define _MD_LAST_THREAD() _pr_last_thread_tls() @@ -336,7 +358,10 @@ extern PRStatus _MD_WakeupWaiter(struct PRThread *); NSPR_API(void) _MD_InitIO(void); #define _MD_INIT_IO _MD_InitIO -#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) +#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ + PR_BEGIN_MACRO \ + *status = PR_TRUE; \ + PR_END_MACRO #define _MD_SWITCH_CONTEXT(_thread) #define _MD_RESTORE_CONTEXT(_newThread) @@ -784,5 +809,7 @@ PR_END_EXTERN_C #endif /* _PR_GLOBAL_THREADS_ONLY */ +extern void _MD_solaris_map_sendfile_error(int err); + #endif /* nspr_solaris_defs_h___ */ diff --git a/pr/include/md/_solaris32.cfg b/pr/include/md/_solaris32.cfg index 10cb3364..ec19c4d3 100644 --- a/pr/include/md/_solaris32.cfg +++ b/pr/include/md/_solaris32.cfg @@ -43,12 +43,12 @@ #define SOLARIS #endif -#ifdef sparc +#if defined(sparc) || defined(__sparc) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_DOUBLE 8 -#elif defined(i386) +#elif defined(i386) || defined(__i386) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_ALIGN_OF_INT64 4 diff --git a/pr/include/md/_solaris64.cfg b/pr/include/md/_solaris64.cfg index 8318b74b..54331c51 100644 --- a/pr/include/md/_solaris64.cfg +++ b/pr/include/md/_solaris64.cfg @@ -43,12 +43,12 @@ #define SOLARIS #endif -#ifdef sparc +#if defined(sparc) || defined(__sparc) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_DOUBLE 8 -#elif defined(i386) +#elif defined(i386) || defined(__i386) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_ALIGN_OF_INT64 4 diff --git a/pr/include/md/_unixos.h b/pr/include/md/_unixos.h index 345c48d5..25ae239c 100644 --- a/pr/include/md/_unixos.h +++ b/pr/include/md/_unixos.h @@ -145,6 +145,9 @@ extern PRUint32 _pr_md_ioq_timeout; struct _MDFileDesc { int osfd; +#if defined(LINUX) && defined(_PR_PTHREADS) + int tcp_nodelay; /* used by pt_LinuxSendFile */ +#endif }; struct _MDDir { diff --git a/pr/include/md/_win16.h b/pr/include/md/_win16.h index 147ef77a..15edc7db 100644 --- a/pr/include/md/_win16.h +++ b/pr/include/md/_win16.h @@ -443,13 +443,6 @@ NSPR_API(void) _PR_UserDestroyThread(PRThread *thread); /* - * _PR_ShutdownLinker unloads all dlls loaded by the application via - * calls to PR_LoadLibrary - */ -void _PR_ShutdownLinker(void); - - -/* ** If thread emulation is used, then setjmp/longjmp stores the register ** state of each thread. ** diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h index 6a9bb271..f2e628f5 100644 --- a/pr/include/md/_win95.h +++ b/pr/include/md/_win95.h @@ -51,6 +51,26 @@ #define HAVE_DLL #undef HAVE_THREAD_AFFINITY +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE +#ifndef _PR_INET6 +#define AF_INET6 23 +/* newer ws2tcpip.h provides these */ +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x2 +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif +#endif +#define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #define PR_HAVE_WIN32_NAMED_SHARED_MEMORY @@ -92,6 +112,9 @@ struct _MDThread { struct PRThread *prev, *next; /* used by the cvar wait queue to * chain the PRThread structures * together */ + void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to + * pass its 'start' argument to + * pr_root. */ }; struct _MDThreadStack { @@ -112,6 +135,16 @@ struct _MDDir { PRUint32 magic; /* for debugging */ }; +#ifdef MOZ_UNICODE +struct _MDDirUTF16 { + HANDLE d_hdl; + WIN32_FIND_DATAW d_entry; + PRBool firstEntry; /* Is this the entry returned + * by FindFirstFileW()? */ + PRUint32 magic; /* for debugging */ +}; +#endif /* MOZ_UNICODE */ + struct _MDCVar { PRUint32 magic; struct PRThread *waitHead, *waitTail; /* the wait queue: a doubly- @@ -213,6 +246,15 @@ extern PRInt32 _MD_CloseFile(PRInt32 osfd); #define _MD_TLOCKFILE _PR_MD_TLOCKFILE #define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE +#ifdef MOZ_UNICODE +/* --- UTF16 IO stuff --- */ +#define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16 +#define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16 +#define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16 +#define _MD_CLOSE_DIR_UTF16 _PR_MD_CLOSE_DIR_UTF16 +#define _MD_GETFILEINFO64_UTF16 _PR_MD_GETFILEINFO64_UTF16 +#endif /* MOZ_UNICODE */ + /* --- Socket IO stuff --- */ #define _MD_EACCES WSAEACCES #define _MD_EADDRINUSE WSAEADDRINUSE @@ -243,7 +285,7 @@ extern void _MD_MakeNonblock(PRFileDesc *f); #define _MD_INIT_FD_INHERITABLE _PR_MD_INIT_FD_INHERITABLE #define _MD_QUERY_FD_INHERITABLE _PR_MD_QUERY_FD_INHERITABLE #define _MD_SHUTDOWN _PR_MD_SHUTDOWN -#define _MD_LISTEN(s, backlog) listen(s->secret->md.osfd,backlog) +#define _MD_LISTEN _PR_MD_LISTEN extern PRInt32 _MD_CloseSocket(PRInt32 osfd); #define _MD_CLOSE_SOCKET _MD_CloseSocket #define _MD_SENDTO _PR_MD_SENDTO @@ -394,7 +436,10 @@ extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process, extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process); #define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT -#define _MD_INIT_CONTEXT +#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ + PR_BEGIN_MACRO \ + *status = PR_TRUE; \ + PR_END_MACRO #define _MD_SWITCH_CONTEXT #define _MD_RESTORE_CONTEXT @@ -405,6 +450,9 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process); #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) +/* --- Time --- */ +extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm); + /* --- Native-Thread Specific Definitions ------------------------------- */ extern struct PRThread * _MD_CURRENT_THREAD(void); diff --git a/pr/include/md/_winnt.h b/pr/include/md/_winnt.h index de8a2cf7..1e7fe6d3 100644 --- a/pr/include/md/_winnt.h +++ b/pr/include/md/_winnt.h @@ -47,6 +47,9 @@ #include <windows.h> #include <winsock.h> +#ifdef __MINGW32__ +#include <mswsock.h> +#endif #include <errno.h> #include "prio.h" @@ -63,6 +66,26 @@ #define HAVE_DLL #define HAVE_CUSTOM_USER_THREADS #define HAVE_THREAD_AFFINITY +#define _PR_HAVE_GETADDRINFO +#define _PR_INET6_PROBE +#ifndef _PR_INET6 +#define AF_INET6 23 +/* newer ws2tcpip.h provides these */ +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x2 +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif +#endif +#define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #define _PR_HAVE_ATOMIC_CAS #define PR_HAVE_WIN32_NAMED_SHARED_MEMORY @@ -149,6 +172,9 @@ struct _MDThread { void *fiber_arg; /* arg to main fiber routine */ PRUint32 fiber_stacksize; /* stacksize for fiber */ PRInt32 fiber_last_error; /* last error for the fiber */ + void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to + * pass its 'start' argument to + * pr_root. */ }; struct _MDThreadStack { @@ -346,6 +372,8 @@ extern int _PR_NTFiberSafeSelect(int, fd_set *, fd_set *, fd_set *, #define _MD_INIT_THREAD _PR_MD_INIT_THREAD #define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD #define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD +#define _MD_JOIN_THREAD _PR_MD_JOIN_THREAD +#define _MD_END_THREAD _PR_MD_END_THREAD #define _MD_YIELD _PR_MD_YIELD #define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY #define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD @@ -449,6 +477,9 @@ extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process); #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) +/* --- Time --- */ +extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm); + /* --- Native-Thread Specific Definitions ------------------------------- */ extern BOOL _pr_use_static_tls; diff --git a/pr/include/obsolete/Makefile.in b/pr/include/obsolete/Makefile.in index 88342b0b..f2d78313 100644 --- a/pr/include/obsolete/Makefile.in +++ b/pr/include/obsolete/Makefile.in @@ -48,7 +48,7 @@ HEADERS = $(wildcard $(srcdir)/*.h) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/obsolete -includedir := $(includedir)/obsolete +include_subdir = obsolete include $(topsrcdir)/config/rules.mk diff --git a/pr/include/prcountr.h b/pr/include/prcountr.h index 1a7d1456..105135f1 100644 --- a/pr/include/prcountr.h +++ b/pr/include/prcountr.h @@ -116,7 +116,6 @@ typedef void * PRCounterHandle; #define PRCOUNTER_DESC_MAX 255 -#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) /* ----------------------------------------------------------------------- ** FUNCTION: PR_DEFINE_COUNTER() -- Define a PRCounterHandle @@ -135,8 +134,12 @@ typedef void * PRCounterHandle; ** to value. ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_INIT_COUNTER_HANDLE(handle,value)\ (handle) = (PRCounterHandle)(value) +#else +#define PR_INIT_COUNTER_HANDLE(handle,value) +#endif /* ----------------------------------------------------------------------- ** FUNCTION: PR_CreateCounter() -- Create a counter @@ -167,8 +170,12 @@ typedef void * PRCounterHandle; ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_CREATE_COUNTER(handle,qName,rName,description)\ (handle) = PR_CreateCounter((qName),(rName),(description)) +#else +#define PR_CREATE_COUNTER(handle,qName,rName,description) +#endif NSPR_API(PRCounterHandle) PR_CreateCounter( @@ -194,7 +201,11 @@ NSPR_API(PRCounterHandle) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_DESTROY_COUNTER(handle) PR_DestroyCounter((handle)) +#else +#define PR_DESTROY_COUNTER(handle) +#endif NSPR_API(void) PR_DestroyCounter( @@ -222,8 +233,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)\ (handle) = PR_GetCounterHandleFromName((qName),(rName)) +#else +#define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName) +#endif NSPR_API(PRCounterHandle) PR_GetCounterHandleFromName( @@ -251,8 +266,12 @@ NSPR_API(PRCounterHandle) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description)\ PR_GetCounterNameFromHandle((handle),(qName),(rName),(description)) +#else +#define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description ) +#endif NSPR_API(void) PR_GetCounterNameFromHandle( @@ -279,7 +298,11 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_INCREMENT_COUNTER(handle) PR_IncrementCounter(handle) +#else +#define PR_INCREMENT_COUNTER(handle) +#endif NSPR_API(void) PR_IncrementCounter( @@ -304,7 +327,11 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_DECREMENT_COUNTER(handle) PR_DecrementCounter(handle) +#else +#define PR_DECREMENT_COUNTER(handle) +#endif NSPR_API(void) PR_DecrementCounter( @@ -328,8 +355,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_ADD_TO_COUNTER(handle,value)\ PR_AddToCounter((handle),(value)) +#else +#define PR_ADD_TO_COUNTER(handle,value) +#endif NSPR_API(void) PR_AddToCounter( @@ -358,8 +389,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_SUBTRACT_FROM_COUNTER(handle,value)\ PR_SubtractFromCounter((handle),(value)) +#else +#define PR_SUBTRACT_FROM_COUNTER(handle,value) +#endif NSPR_API(void) PR_SubtractFromCounter( @@ -384,8 +419,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER(counter,handle)\ (counter) = PR_GetCounter((handle)) +#else +#define PR_GET_COUNTER(counter,handle) 0 +#endif NSPR_API(PRUint32) PR_GetCounter( @@ -412,7 +451,11 @@ NSPR_API(PRUint32) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_SET_COUNTER(handle,value) PR_SetCounter((handle),(value)) +#else +#define PR_SET_COUNTER(handle,value) +#endif NSPR_API(void) PR_SetCounter( @@ -450,8 +493,12 @@ NSPR_API(void) ** operations may cause unpredictable results. ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_FIND_NEXT_COUNTER_QNAME(next,handle)\ (next) = PR_FindNextCounterQname((handle)) +#else +#define PR_FIND_NEXT_COUNTER_QNAME(next,handle) NULL +#endif NSPR_API(PRCounterHandle) PR_FindNextCounterQname( @@ -489,8 +536,12 @@ NSPR_API(PRCounterHandle) ** operations may cause unpredictable results. ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)\ (next) = PR_FindNextCounterRname((rhandle),(qhandle)) +#else +#define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle) +#endif NSPR_API(PRCounterHandle) PR_FindNextCounterRname( @@ -498,31 +549,6 @@ NSPR_API(PRCounterHandle) 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/prerr.h b/pr/include/prerr.h index 530526b6..5bb6c9e8 100644 --- a/pr/include/prerr.h +++ b/pr/include/prerr.h @@ -263,8 +263,11 @@ /* Host is unreachable */ #define PR_HOST_UNREACHABLE_ERROR (-5927L) +/* The library is not loaded */ +#define PR_LIBRARY_NOT_LOADED_ERROR (-5926L) + /* Placeholder for the end of the list */ -#define PR_MAX_ERROR (-5926L) +#define PR_MAX_ERROR (-5925L) extern void nspr_InitializePRErrorTable(void); #define ERROR_TABLE_BASE_nspr (-6000L) diff --git a/pr/include/prinet.h b/pr/include/prinet.h index f5aea7eb..8dba5cd1 100644 --- a/pr/include/prinet.h +++ b/pr/include/prinet.h @@ -57,7 +57,7 @@ #define prinet_h__ #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) -#ifdef linux +#ifdef LINUX #undef __STRICT_ANSI__ #define __STRICT_ANSI__ #endif diff --git a/pr/include/prinit.h b/pr/include/prinit.h index 0e8e124c..a0a042d4 100644 --- a/pr/include/prinit.h +++ b/pr/include/prinit.h @@ -60,9 +60,9 @@ PR_BEGIN_EXTERN_C ** The format of the version string is ** "<major version>.<minor version>[.<patch level>] [<Beta>]" */ -#define PR_VERSION "4.2 Beta" +#define PR_VERSION "4.5 Beta" #define PR_VMAJOR 4 -#define PR_VMINOR 2 +#define PR_VMINOR 5 #define PR_VPATCH 0 #define PR_BETA PR_TRUE @@ -220,11 +220,19 @@ typedef struct PRCallOnceType { typedef PRStatus (PR_CALLBACK *PRCallOnceFN)(void); +typedef PRStatus (PR_CALLBACK *PRCallOnceWithArgFN)(void *arg); + NSPR_API(PRStatus) PR_CallOnce( PRCallOnceType *once, PRCallOnceFN func ); +NSPR_API(PRStatus) PR_CallOnceWithArg( + PRCallOnceType *once, + PRCallOnceWithArgFN func, + void *arg +); + PR_END_EXTERN_C diff --git a/pr/include/prio.h b/pr/include/prio.h index f60e1f1a..50bfa811 100644 --- a/pr/include/prio.h +++ b/pr/include/prio.h @@ -52,6 +52,10 @@ PR_BEGIN_EXTERN_C /* Typedefs */ typedef struct PRDir PRDir; typedef struct PRDirEntry PRDirEntry; +#ifdef MOZ_UNICODE +typedef struct PRDirUTF16 PRDirUTF16; +typedef struct PRDirEntryUTF16 PRDirEntryUTF16; +#endif /* MOZ_UNICODE */ typedef struct PRFileDesc PRFileDesc; typedef struct PRFileInfo PRFileInfo; typedef struct PRFileInfo64 PRFileInfo64; @@ -135,6 +139,10 @@ typedef enum PRTransmitFileFlags { #define PR_AF_INET6 100 #endif +#ifndef PR_AF_UNSPEC +#define PR_AF_UNSPEC 0 +#endif + /* ************************************************************************** ** A network address @@ -156,7 +164,7 @@ struct PRIPv6Addr { #define pr_s6_addr _S6_un._S6_u8 #define pr_s6_addr16 _S6_un._S6_u16 #define pr_s6_addr32 _S6_un._S6_u32 -#define pr_s6_addr64 _S6_un._S6_addr64 +#define pr_s6_addr64 _S6_un._S6_u64 typedef struct PRIPv6Addr PRIPv6Addr; @@ -186,10 +194,15 @@ union PRNetAddr { PRIPv6Addr ip; /* the actual 128 bits of address */ PRUint32 scope_id; /* set of interfaces for a scope */ } ipv6; -#if defined(XP_UNIX) +#if defined(XP_UNIX) || defined(XP_OS2) struct { /* Unix domain socket address */ PRUint16 family; /* address family (AF_UNIX) */ +#ifdef XP_OS2 + char path[108]; /* null-terminated pathname */ + /* bind fails if size is not 108. */ +#else char path[104]; /* null-terminated pathname */ +#endif } local; #endif }; @@ -650,6 +663,14 @@ NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); NSPR_API(PRFileDesc*) PR_OpenFile( const char *name, PRIntn flags, PRIntn mode); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRFileDesc*) PR_OpenFileUTF16( + const PRUnichar *name, PRIntn flags, PRIntn mode); +#endif /* MOZ_UNICODE */ + /* ************************************************************************** * FUNCTION: PR_Close @@ -830,6 +851,13 @@ struct PRFileInfo64 { NSPR_API(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info); NSPR_API(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info); +#endif /* MOZ_UNICODE */ + /* ************************************************************************** * FUNCTION: PR_GetOpenFileInfo, PR_GetOpenFileInfo64 @@ -984,6 +1012,13 @@ struct PRDirEntry { const char *name; /* name of entry, relative to directory name */ }; +#ifdef MOZ_UNICODE +struct PRDirEntryUTF16 { + const PRUnichar *name; /* name of entry in UTF16, relative to + * directory name */ +}; +#endif /* MOZ_UNICODE */ + #if !defined(NO_NSPR_10_SUPPORT) #define PR_DirName(dirEntry) (dirEntry->name) #endif @@ -1010,6 +1045,13 @@ struct PRDirEntry { NSPR_API(PRDir*) PR_OpenDir(const char *name); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name); +#endif /* MOZ_UNICODE */ + /* ************************************************************************* * FUNCTION: PR_ReadDir @@ -1043,6 +1085,13 @@ typedef enum PRDirFlags { NSPR_API(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags); +#endif /* MOZ_UNICODE */ + /* ************************************************************************* * FUNCTION: PR_CloseDir @@ -1062,6 +1111,13 @@ NSPR_API(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags); NSPR_API(PRStatus) PR_CloseDir(PRDir *dir); +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This function may be removed in a future release. + */ +NSPR_API(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir); +#endif /* MOZ_UNICODE */ + /* ************************************************************************* * FUNCTION: PR_MkDir @@ -1240,7 +1296,7 @@ NSPR_API(PRStatus) PR_Connect( * PR_Poll() * RETURN: PRStatus * If the nonblocking connect has successfully completed, - * PR_GetConnectStatus returns PR_SUCCESS. If PR_GetConnectStatus() + * PR_ConnectContinue returns PR_SUCCESS. If PR_ConnectContinue() * returns PR_FAILURE, call PR_GetError(): * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in * progress and has not completed yet. The caller should poll @@ -1880,9 +1936,12 @@ struct PRPollDesc { ** DESCRIPTION: ** ** The call returns as soon as I/O is ready on one or more of the underlying -** file/socket objects. A count of the number of ready descriptors is +** socket objects. A count of the number of ready descriptors is ** returned unless a timeout occurs in which case zero is returned. ** +** PRPollDesc.fd should be set to a pointer to a PRFileDesc object +** representing a socket. This field can be set to NULL to indicate to +** PR_Poll that this PRFileDesc object should be ignored. ** PRPollDesc.in_flags should be set to the desired request ** (read/write/except or some combination). Upon successful return from ** this call PRPollDesc.out_flags will be set to indicate what kind of diff --git a/pr/include/private/Makefile.in b/pr/include/private/Makefile.in index 31c82552..cafb86c8 100644 --- a/pr/include/private/Makefile.in +++ b/pr/include/private/Makefile.in @@ -49,7 +49,7 @@ RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/private HEADERS = $(RELEASE_HEADERS) $(srcdir)/pprmwait.h $(srcdir)/primpl.h -includedir := $(includedir)/private +include_subdir = private include $(topsrcdir)/config/rules.mk diff --git a/pr/include/private/pprthred.h b/pr/include/private/pprthred.h index 04525378..71148304 100644 --- a/pr/include/private/pprthred.h +++ b/pr/include/private/pprthred.h @@ -41,6 +41,12 @@ */ #include "nspr.h" +#if defined(XP_OS2) +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_WIN +#include <os2.h> +#endif PR_BEGIN_EXTERN_C @@ -336,6 +342,16 @@ NSPR_API(void) _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize); #endif /* IRIX */ +#if defined(XP_OS2) +/* +** These functions need to be called at the start and end of a thread. +** An EXCEPTIONREGISTRATIONRECORD must be declared on the stack and its +** address passed to the two functions. +*/ +NSPR_API(void) PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e); +NSPR_API(void) PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e); +#endif /* XP_OS2 */ + /* I think PR_GetMonitorEntryCount is useless. All you really want is this... */ #define PR_InMonitor(m) (PR_GetMonitorEntryCount(m) > 0) diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h index 8501c0e0..db323306 100644 --- a/pr/include/private/primpl.h +++ b/pr/include/private/primpl.h @@ -144,6 +144,9 @@ typedef struct _MDThread _MDThread; typedef struct _MDThreadStack _MDThreadStack; typedef struct _MDSemaphore _MDSemaphore; typedef struct _MDDir _MDDir; +#ifdef MOZ_UNICODE +typedef struct _MDDirUTF16 _MDDirUTF16; +#endif /* MOZ_UNICODE */ typedef struct _MDFileDesc _MDFileDesc; typedef struct _MDProcess _MDProcess; typedef struct _MDFileMap _MDFileMap; @@ -216,22 +219,13 @@ typedef struct PTDebug PRUintn cvars_notified, delayed_cv_deletes; } PTDebug; -NSPR_API(void) PT_GetStats(PTDebug* here); -NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); - -#else - -typedef PRUintn PTDebug; -#define PT_GetStats(_p) -#define PT_FPrintStats(_fd, _msg) - #endif /* defined(DEBUG) */ +NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); + #else /* defined(_PR_PTHREADS) */ -typedef PRUintn PTDebug; -#define PT_GetStats(_p) -#define PT_FPrintStats(_fd, _msg) +NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); /* ** This section is contains those parts needed to implement NSPR on @@ -310,7 +304,8 @@ typedef struct _PRInterruptTable { #define _PR_CPU_PTR(_qp) \ ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links))) -#if !defined(IRIX) && !defined(WIN32) +#if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \ + && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) #define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD()) #endif @@ -1022,6 +1017,12 @@ extern PRStatus _PR_MD_CREATE_THREAD( PRUint32 stackSize); #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD +extern void _PR_MD_JOIN_THREAD(_MDThread *md); +#define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD + +extern void _PR_MD_END_THREAD(void); +#define _PR_MD_END_THREAD _MD_END_THREAD + extern void _PR_MD_YIELD(void); #define _PR_MD_YIELD _MD_YIELD @@ -1138,6 +1139,24 @@ extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode); extern PRInt32 _PR_MD_RMDIR(const char *name); #define _PR_MD_RMDIR _MD_RMDIR +#ifdef MOZ_UNICODE +/* UTF16 File I/O related */ +extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name); +#define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF16 + +extern PRInt32 _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode); +#define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF16 + +extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags); +#define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF16 + +extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md); +#define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16 + +extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info); +#define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16 +#endif /* MOZ_UNICODE */ + /* Socket I/O related */ extern void _PR_MD_INIT_IO(void); #define _PR_MD_INIT_IO _MD_INIT_IO @@ -1376,7 +1395,7 @@ extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr); ** struct sockaddr_in6. */ -#if defined(XP_UNIX) +#if defined(XP_UNIX) || defined(XP_OS2) #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ @@ -1392,7 +1411,7 @@ extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr); #else -#if defined(XP_UNIX) +#if defined(XP_UNIX) || defined(XP_OS2) #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ @@ -1441,8 +1460,12 @@ struct PRCondVar { pthread_cond_t cv; /* underlying pthreads condition */ PRInt32 notify_pending; /* CV has destroy pending notification */ #elif defined(_PR_BTHREADS) - sem_id isem; /* Semaphore used to lock threadQ */ - int32 benaphoreCount; /* Number of people in lock */ + sem_id sem; /* the underlying lock */ + sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */ + sem_id signalSem; /* the lock for threads waiting for someone to notify */ + volatile int32 nw; /* the number waiting */ + volatile int32 ns; /* the number signalling */ + long signalBenCount; /* the number waiting on the underlying sem */ #else /* not pthreads or Be threads */ PRCList condQ; /* Condition variable wait Q */ _MDLock ilock; /* Internal Lock to protect condQ */ @@ -1716,6 +1739,13 @@ struct PRFilePrivate { PRBool appendMode; #endif _MDFileDesc md; +#ifdef _PR_STRICT_ADDR_LEN + PRUint16 af; /* If the platform requires passing the exact + * length of the sockaddr structure for the + * address family of the socket to socket + * functions like accept(), we need to save + * the address family of the socket. */ +#endif }; struct PRDir { @@ -1723,6 +1753,13 @@ struct PRDir { _MDDir md; }; +#ifdef MOZ_UNICODE +struct PRDirUTF16 { + PRDirEntry d; + _MDDirUTF16 md; +}; +#endif /* MOZ_UNICODE */ + extern void _PR_InitSegs(void); extern void _PR_InitStacks(void); extern void _PR_InitTPD(void); @@ -1741,10 +1778,18 @@ extern void _PR_InitMW(void); extern void _PR_InitRWLocks(void); extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me); extern void _PR_CleanupThread(PRThread *thread); +extern void _PR_CleanupCallOnce(void); +extern void _PR_CleanupMW(void); +extern void _PR_CleanupDtoa(void); +extern void _PR_ShutdownLinker(void); extern void _PR_CleanupEnv(void); extern void _PR_CleanupIO(void); +extern void _PR_CleanupNet(void); extern void _PR_CleanupLayerCache(void); extern void _PR_CleanupStacks(void); +#ifdef WINNT +extern void _PR_CleanupCPUs(void); +#endif extern void _PR_CleanupThreads(void); extern void _PR_CleanupTPD(void); extern void _PR_Cleanup(void); @@ -1800,7 +1845,7 @@ extern PRFileDesc *_pr_stderr; ** and functions with macros that expand to the native thread ** types and functions on each platform. */ -#if defined(_PR_PTHREADS) +#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #define _PR_ZONE_ALLOCATOR #endif diff --git a/pr/include/prlink.h b/pr/include/prlink.h index 3787a369..5ccd25f1 100644 --- a/pr/include/prlink.h +++ b/pr/include/prlink.h @@ -239,6 +239,14 @@ NSPR_API(PRFuncPtr) PR_FindFunctionSymbolAndLibrary(const char *name, NSPR_API(PRLibrary*) PR_LoadStaticLibrary( const char *name, const PRStaticLinkTable *table); +/* +** Return the pathname of the file that the library "name" was loaded +** from. "addr" is the address of a function defined in the library. +** +** The caller is responsible for freeing the result with PR_Free. +*/ +NSPR_API(char *) PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr); + PR_END_EXTERN_C #endif /* prlink_h___ */ diff --git a/pr/include/prlong.h b/pr/include/prlong.h index 898b2f6d..b72471e9 100644 --- a/pr/include/prlong.h +++ b/pr/include/prlong.h @@ -51,6 +51,7 @@ PR_BEGIN_EXTERN_C ** DEFINES: LL_MaxInt ** LL_MinInt ** LL_Zero +** LL_MaxUint ** DESCRIPTION: ** Various interesting constants and static variable ** initializer @@ -62,15 +63,19 @@ PRInt64 __pascal __loadds __export LL_MinInt(void); PRInt64 __pascal __loadds __export LL_Zero(void); +PRUint64 __pascal __loadds __export + LL_MaxUint(void); #else NSPR_API(PRInt64) LL_MaxInt(void); NSPR_API(PRInt64) LL_MinInt(void); NSPR_API(PRInt64) LL_Zero(void); +NSPR_API(PRUint64) LL_MaxUint(void); #endif #define LL_MAXINT LL_MaxInt() #define LL_MININT LL_MinInt() #define LL_ZERO LL_Zero() +#define LL_MAXUINT LL_MaxUint() #if defined(HAVE_LONG_LONG) diff --git a/pr/include/prnetdb.h b/pr/include/prnetdb.h index 1eb23dbe..a2456137 100644 --- a/pr/include/prnetdb.h +++ b/pr/include/prnetdb.h @@ -386,6 +386,88 @@ NSPR_API(PRStatus) PR_GetProtoByNumber( PRInt32 protocolnumber, char* buffer, PRInt32 bufsize, PRProtoEnt* result); /*********************************************************************** +** FUNCTION: +** DESCRIPTION: PR_GetAddrInfoByName() +** Lookup a host by name. Equivalent to getaddrinfo(host, NULL, ...) of +** RFC 3493. +** +** INPUTS: +** char *hostname Character string defining the host name of interest +** PRUint16 af Must be PR_AF_UNSPEC +** PRIntn flags Must be PR_AI_ADDRCONFIG +** RETURN: +** PRAddrInfo* Handle to a data structure containing the results +** of the host lookup. Use PR_EnumerateAddrInfo to +** inspect the PRNetAddr values stored in this object. +** When no longer needed, this handle must be destroyed +** with a call to PR_FreeAddrInfo. If a lookup error +** occurs, then NULL will be returned. +***********************************************************************/ +typedef struct PRAddrInfo PRAddrInfo; + +NSPR_API(PRAddrInfo*) PR_GetAddrInfoByName( + const char *hostname, PRUint16 af, PRIntn flags); + +/*********************************************************************** +** FUNCTION: +** DESCRIPTION: PR_FreeAddrInfo() +** Destroy the PRAddrInfo handle allocated by PR_GetAddrInfoByName(). +** +** INPUTS: +** PRAddrInfo *addrInfo +** The handle resulting from a successful call to +** PR_GetAddrInfoByName(). +** RETURN: +** void +***********************************************************************/ +NSPR_API(void) PR_FreeAddrInfo(PRAddrInfo *addrInfo); + +/*********************************************************************** +** FUNCTION: +** DESCRIPTION: PR_EnumerateAddrInfo() +** A stateless enumerator over a PRAddrInfo handle acquired from +** PR_GetAddrInfoByName() to inspect the possible network addresses. +** +** INPUTS: +** void *enumPtr Index pointer of the enumeration. The enumeration +** starts and ends with a value of NULL. +** PRAddrInfo *addrInfo +** The PRAddrInfo handle returned by a successful +** call to PR_GetAddrInfoByName(). +** PRUint16 port The port number to be assigned as part of the +** PRNetAddr. +** OUTPUTS: +** PRNetAddr *result A pointer to an address structure that will be +** filled in by the call to the enumeration if the +** result of the call is greater than zero. +** RETURN: +** void* The value that should be used for the next call +** of the enumerator ('enumPtr'). The enumeration +** is ended if this value is returned NULL. +***********************************************************************/ +NSPR_API(void *) PR_EnumerateAddrInfo( + void *enumPtr, const PRAddrInfo *addrInfo, PRUint16 port, PRNetAddr *result); + +/*********************************************************************** +** FUNCTION: +** DESCRIPTION: PR_GetCanonNameFromAddrInfo() +** Extracts the canonical name of the hostname passed to +** PR_GetAddrInfoByName(). +** +** INPUTS: +** PRAddrInfo *addrInfo +** The PRAddrInfo handle returned by a successful +** call to PR_GetAddrInfoByName(). +** RETURN: +** const char * A const pointer to the canonical hostname stored +** in the given PRAddrInfo handle. This pointer is +** invalidated once the PRAddrInfo handle is destroyed +** by a call to PR_FreeAddrInfo(). +***********************************************************************/ +NSPR_API(const char *) PR_GetCanonNameFromAddrInfo( + const PRAddrInfo *addrInfo); + +/*********************************************************************** ** FUNCTIONS: PR_ntohs, PR_ntohl, PR_ntohll, PR_htons, PR_htonl, PR_htonll ** ** DESCRIPTION: API entries for the common byte ordering routines. diff --git a/pr/include/prolock.h b/pr/include/prolock.h index 80b92e17..d0bdbe61 100644 --- a/pr/include/prolock.h +++ b/pr/include/prolock.h @@ -39,8 +39,6 @@ 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 @@ -80,7 +78,18 @@ PR_BEGIN_EXTERN_C ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) typedef void * PROrderedLock; +#else +/* +** Map PROrderedLock and methods onto PRLock when ordered locking +** is not compiled in. +** +*/ +#include "prlock.h" + +typedef PRLock PROrderedLock; +#endif /* ----------------------------------------------------------------------- ** FUNCTION: PR_CreateOrderedLock() -- Create an Ordered Lock @@ -98,8 +107,12 @@ typedef void * PROrderedLock; ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_CREATE_ORDERED_LOCK(order,name)\ PR_CreateOrderedLock((order),(name)) +#else +#define PR_CREATE_ORDERED_LOCK(order) PR_NewLock() +#endif NSPR_API(PROrderedLock *) PR_CreateOrderedLock( @@ -122,7 +135,11 @@ NSPR_API(PROrderedLock *) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyOrderedLock((lock)) +#else +#define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyLock((lock)) +#endif NSPR_API(void) PR_DestroyOrderedLock( @@ -146,7 +163,11 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_LOCK_ORDERED_LOCK(lock) PR_LockOrderedLock((lock)) +#else +#define PR_LOCK_ORDERED_LOCK(lock) PR_Lock((lock)) +#endif NSPR_API(void) PR_LockOrderedLock( @@ -170,43 +191,17 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_UNLOCK_ORDERED_LOCK(lock) PR_UnlockOrderedLock((lock)) +#else +#define PR_UNLOCK_ORDERED_LOCK(lock) PR_Unlock((lock)) +#endif NSPR_API(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/prsystem.h b/pr/include/prsystem.h index 9484148a..73404920 100644 --- a/pr/include/prsystem.h +++ b/pr/include/prsystem.h @@ -57,6 +57,13 @@ NSPR_API(char) PR_GetDirectorySeparator(void); NSPR_API(char) PR_GetDirectorySepartor(void); +/* +** Get the host' path separator. +** Paths are assumed to be of the form: +** <directory>[<sep><directory>]* +*/ + +NSPR_API(char) PR_GetPathSeparator(void); /* Types of information available via PR_GetSystemInfo(...) */ typedef enum { diff --git a/pr/include/prthread.h b/pr/include/prthread.h index a987202a..334116ce 100644 --- a/pr/include/prthread.h +++ b/pr/include/prthread.h @@ -159,7 +159,9 @@ NSPR_API(PRStatus) PR_JoinThread(PRThread *thread); ** Never returns NULL. */ NSPR_API(PRThread*) PR_GetCurrentThread(void); +#ifndef NO_NSPR_10_SUPPORT #define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */ +#endif /* NO_NSPR_10_SUPPORT */ /* ** Get the priority of "thread". diff --git a/pr/include/prtrace.h b/pr/include/prtrace.h index 9b0b0bb8..ebfe1baf 100644 --- a/pr/include/prtrace.h +++ b/pr/include/prtrace.h @@ -103,7 +103,6 @@ PR_BEGIN_EXTERN_C */ typedef void * PRTraceHandle; -#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) /* ** PRTraceEntry -- A trace entry in the in-memory trace buffer ** looks like this. @@ -153,8 +152,12 @@ typedef enum PRTraceOption ** to value. e.g. PR_INIT_TRACE_HANDLE( myHandle, NULL ); ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_INIT_TRACE_HANDLE(handle,value)\ (handle) = (PRCounterHandle)(value) +#else +#define PR_INIT_TRACE_HANDLE(handle,value) +#endif /* ----------------------------------------------------------------------- @@ -192,8 +195,12 @@ typedef enum PRTraceOption #define PRTRACE_NAME_MAX 31 #define PRTRACE_DESC_MAX 255 +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_CREATE_TRACE(handle,qName,rName,description)\ (handle) = PR_CreateTrace((qName),(rName),(description)) +#else +#define PR_CREATE_TRACE(handle,qName,rName,description) +#endif NSPR_API(PRTraceHandle) PR_CreateTrace( @@ -222,8 +229,12 @@ NSPR_API(PRTraceHandle) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_DESTROY_TRACE(handle)\ PR_DestroyTrace((handle)) +#else +#define PR_DESTROY_TRACE(handle) +#endif NSPR_API(void) PR_DestroyTrace( @@ -259,8 +270,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)\ PR_Trace((handle),(ud0),(ud1),(ud2),(ud3),(ud4),(ud5),(ud6),(ud7)) +#else +#define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7) +#endif NSPR_API(void) PR_Trace( @@ -342,8 +357,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_SET_TRACE_OPTION(command,value)\ PR_SetTraceOption((command),(value)) +#else +#define PR_SET_TRACE_OPTION(command,value) +#endif NSPR_API(void) PR_SetTraceOption( @@ -376,8 +395,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_OPTION(command,value)\ PR_GetTraceOption((command),(value)) +#else +#define PR_GET_TRACE_OPTION(command,value) +#endif NSPR_API(void) PR_GetTraceOption( @@ -408,8 +431,12 @@ NSPR_API(void) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)\ (handle) = PR_GetTraceHandleFromName((qName),(rName)) +#else +#define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName) +#endif NSPR_API(PRTraceHandle) PR_GetTraceHandleFromName( @@ -436,8 +463,12 @@ NSPR_API(PRTraceHandle) ** RESTRICTIONS: ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)\ PR_GetTraceNameFromHandle((handle),(qName),(rName),(description)) +#else +#define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description) +#endif NSPR_API(void) PR_GetTraceNameFromHandle( @@ -474,8 +505,12 @@ NSPR_API(void) ** See: PR_SetTraceOption( PRLockTraceHandles ). ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_FIND_NEXT_TRACE_QNAME(next,handle)\ (next) = PR_FindNextTraceQname((handle)) +#else +#define PR_FIND_NEXT_TRACE_QNAME(next,handle) +#endif NSPR_API(PRTraceHandle) PR_FindNextTraceQname( @@ -512,8 +547,12 @@ NSPR_API(PRTraceHandle) ** PR_SetTraceOption( PRLockTraceHandles ). ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)\ (next) = PR_FindNextTraceRname((rhandle),(qhandle)) +#else +#define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle) +#endif NSPR_API(PRTraceHandle) PR_FindNextTraceRname( @@ -564,8 +603,12 @@ NSPR_API(PRTraceHandle) ** On error, PR_RecordTraceEntries() may return prematurely. ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_RECORD_TRACE_ENTRIES()\ PR_RecordTraceEntries() +#else +#define PR_RECORD_TRACE_ENTRIES() +#endif NSPR_API(void) PR_RecordTraceEntries( @@ -612,9 +655,12 @@ NSPR_API(void) ** application may be realized. ... YMMV. ** */ +#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_ENTRIES(buffer,count,found)\ PR_GetTraceEntries((buffer),(count),(found)) - +#else +#define PR_GET_TRACE_ENTRIES(buffer,count,found) +#endif NSPR_API(PRIntn) PR_GetTraceEntries( @@ -623,28 +669,6 @@ NSPR_API(PRIntn) 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 b01673d0..819f9c16 100644 --- a/pr/include/prtypes.h +++ b/pr/include/prtypes.h @@ -79,20 +79,15 @@ ***********************************************************************/ #if defined(WIN32) -#if defined(__GNUC__) -#undef _declspec -#define _declspec(x) __declspec(x) -#endif - -#define PR_EXPORT(__type) extern _declspec(dllexport) __type -#define PR_EXPORT_DATA(__type) extern _declspec(dllexport) __type -#define PR_IMPORT(__type) _declspec(dllimport) __type -#define PR_IMPORT_DATA(__type) _declspec(dllimport) __type +#define PR_EXPORT(__type) extern __declspec(dllexport) __type +#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPORT(__type) __declspec(dllimport) __type +#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type -#define PR_EXTERN(__type) extern _declspec(dllexport) __type -#define PR_IMPLEMENT(__type) _declspec(dllexport) __type -#define PR_EXTERN_DATA(__type) extern _declspec(dllexport) __type -#define PR_IMPLEMENT_DATA(__type) _declspec(dllexport) __type +#define PR_EXTERN(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT(__type) __declspec(dllexport) __type +#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type +#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type #define PR_CALLBACK #define PR_CALLBACK_DECL @@ -163,21 +158,6 @@ #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x -#elif defined(XP_OS2_VACPP) - -#define PR_EXPORT(__type) extern __type -#define PR_EXPORT_DATA(__type) extern __type -#define PR_IMPORT(__type) extern __type -#define PR_IMPORT_DATA(__type) extern __type - -#define PR_EXTERN(__type) extern __type -#define PR_IMPLEMENT(__type) __type -#define PR_EXTERN_DATA(__type) extern __type -#define PR_IMPLEMENT_DATA(__type) __type -#define PR_CALLBACK _Optlink -#define PR_CALLBACK_DECL -#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK - #else /* Unix */ #define PR_EXPORT(__type) extern __type @@ -239,13 +219,15 @@ /*********************************************************************** ** MACROS: PR_ROUNDUP ** PR_MIN -** PR_MAX +** PR_MAX +** PR_ABS ** DESCRIPTION: ** Commonly used macros for operations on compatible types. ***********************************************************************/ #define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) #define PR_MIN(x,y) ((x)<(y)?(x):(y)) #define PR_MAX(x,y) ((x)>(y)?(x):(y)) +#define PR_ABS(x) ((x)<0?-(x):(x)) PR_BEGIN_EXTERN_C @@ -278,6 +260,18 @@ typedef signed char PRInt8; #endif /************************************************************************ + * MACROS: PR_INT8_MAX + * PR_INT8_MIN + * PR_UINT8_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt8 or PRUint8. +************************************************************************/ + +#define PR_INT8_MAX 127 +#define PR_INT8_MIN (-128) +#define PR_UINT8_MAX 255U + +/************************************************************************ ** TYPES: PRUint16 ** PRInt16 ** DESCRIPTION: @@ -291,6 +285,18 @@ typedef short PRInt16; #endif /************************************************************************ + * MACROS: PR_INT16_MAX + * PR_INT16_MIN + * PR_UINT16_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt16 or PRUint16. +************************************************************************/ + +#define PR_INT16_MAX 32767 +#define PR_INT16_MIN (-32768) +#define PR_UINT16_MAX 65535U + +/************************************************************************ ** TYPES: PRUint32 ** PRInt32 ** DESCRIPTION: @@ -311,6 +317,18 @@ typedef long PRInt32; #endif /************************************************************************ + * MACROS: PR_INT32_MAX + * PR_INT32_MIN + * PR_UINT32_MAX + * DESCRIPTION: + * The maximum and minimum values of a PRInt32 or PRUint32. +************************************************************************/ + +#define PR_INT32_MAX PR_INT32(2147483647) +#define PR_INT32_MIN (-PR_INT32_MAX - 1) +#define PR_UINT32_MAX PR_UINT32(4294967295) + +/************************************************************************ ** TYPES: PRUint64 ** PRInt64 ** DESCRIPTION: @@ -426,6 +444,20 @@ typedef PRUint8 PRPackedBool; */ typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; +#ifdef MOZ_UNICODE +/* + * EXPERIMENTAL: This type may be removed in a future release. + */ +#ifndef __PRUNICHAR__ +#define __PRUNICHAR__ +#if defined(WIN32) || defined(XP_MAC) +typedef wchar_t PRUnichar; +#else +typedef PRUint16 PRUnichar; +#endif +#endif +#endif /* MOZ_UNICODE */ + /* ** WARNING: The undocumented data types PRWord and PRUword are ** only used in the garbage collection and arena code. Do not diff --git a/pr/include/prwin16.h b/pr/include/prwin16.h index 68e8dc8b..7a561d35 100644 --- a/pr/include/prwin16.h +++ b/pr/include/prwin16.h @@ -108,7 +108,7 @@ struct PRMethodCallbackStr { void (PR_CALLBACK *free)( void *ptr ); void * (PR_CALLBACK *getenv)( const char *name); int (PR_CALLBACK *putenv)( const char *assoc); -// void * (PR_CALLBACK *perror)( const char *prefix ); +/* void * (PR_CALLBACK *perror)( const char *prefix ); */ }; NSPR_API(void) PR_MDRegisterCallbacks(struct PRMethodCallbackStr *); diff --git a/pr/src/Makefile.in b/pr/src/Makefile.in index d4af5676..600640cb 100644 --- a/pr/src/Makefile.in +++ b/pr/src/Makefile.in @@ -69,7 +69,17 @@ ifeq ($(OS_ARCH),SunOS) ifeq ($(OS_RELEASE),4.1.3_U1) OS_LIBS = -lm else # 4.1.3_U1 - +MAPFILE = $(OBJDIR)/nsprmap.sun +GARBAGE += $(MAPFILE) +ifdef NS_USE_GCC +ifdef GCC_USE_GNU_LD +MKSHLIB += -Wl,--version-script,$(MAPFILE) +else +MKSHLIB += -Wl,-M,$(MAPFILE) +endif +else +MKSHLIB += -M $(MAPFILE) +endif # # In Solaris 2.6 or earlier, -lrt is called -lposix4. # @@ -81,14 +91,19 @@ LIBRT=-lposix4 endif ifdef USE_PTHREADS -OS_LIBS = -lpthread -lthread ${LIBRT} -lsocket -lnsl -ldl +OS_LIBS = -lpthread -lthread ${LIBRT} -lsocket -lnsl -ldl -lc else ifdef LOCAL_THREADS_ONLY -OS_LIBS = -lsocket -lnsl -ldl +OS_LIBS = -lsocket -lnsl -ldl -lc else -OS_LIBS = -lthread ${LIBRT} -lsocket -lnsl -ldl +OS_LIBS = -lthread ${LIBRT} -lsocket -lnsl -ldl -lc endif # LOCAL_THREADS_ONLY endif # USE_PTHREADS +ifeq ($(OS_TEST),sun4u) +ifndef USE_64 +DSO_LDOPTS += -Wl,-f,\$$ORIGIN/cpu/\$$ISALIST/lib$(ULTRASPARC_LIBRARY)$(LIBRARY_VERSION).so +endif +endif # sun4u endif # 4.1.3_U1 endif # SunOS @@ -126,6 +141,13 @@ endif endif endif +ifeq ($(OS_ARCH),OS2) +MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def +ADD_TO_DEF_FILE = cat $(srcdir)/os2extra.def >> $(MAPFILE) +GARBAGE += $(MAPFILE) +MKSHLIB += $(MAPFILE) +endif + ifeq ($(OS_ARCH),OSF1) ifeq ($(USE_PTHREADS), 1) OS_LIBS = -lpthread -lrt @@ -137,9 +159,9 @@ endif ifeq ($(OS_ARCH),Linux) ifeq ($(USE_PTHREADS), 1) -OS_LIBS = -lpthread -ldl -lc +OS_LIBS = -lpthread -ldl else -OS_LIBS = -ldl -lc +OS_LIBS = -ldl endif endif @@ -170,8 +192,16 @@ OS_LIBS = -lsocket -lnsl -lgen -lresolv endif ifeq ($(OS_ARCH),WINNT) +ifdef NS_USE_GCC +OS_LIBS = -ladvapi32 -lwsock32 +else OS_LIBS = advapi32.lib wsock32.lib endif +endif + +ifeq ($(OS_TARGET),MacOSX) +OS_LIBS = -framework CoreServices -framework CoreFoundation +endif ifdef GC_LEAK_DETECTOR EXTRA_LIBS = -L$(dist_libdir) -lboehm @@ -281,7 +311,11 @@ OBJS += memory/$(OBJDIR)/prgcleak.$(OBJ_SUFFIX) endif ifeq ($(OS_ARCH), WINNT) +ifdef NS_USE_GCC +DLLBASE=-Wl,--image-base -Wl,0x30000000 +else DLLBASE=/BASE:0x30000000 +endif # GCC RES=$(OBJDIR)/nspr.res RESNAME=nspr.rc endif # WINNT @@ -320,7 +354,7 @@ NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now SH_DATE = $(shell date "+%Y-%m-%d %T") SH_NOW = $(shell $(NOW)) -ifeq ($(OS_ARCH), WINNT) +ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) SUF = i64 else SUF = LL @@ -342,7 +376,7 @@ $(TINC): $(OBJDIR)/prvrsion.$(OBJ_SUFFIX): prvrsion.c $(TINC) -ifeq ($(OS_ARCH), WINNT) +ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $< else ifeq ($(MOZ_OS2_TOOLS), VACPP) diff --git a/pr/src/bthreads/btcvar.c b/pr/src/bthreads/btcvar.c index 3ca8c1f4..ce16de78 100644 --- a/pr/src/bthreads/btcvar.c +++ b/pr/src/bthreads/btcvar.c @@ -55,8 +55,14 @@ PR_IMPLEMENT(PRCondVar*) if( NULL != cv ) { cv->lock = lock; - cv->isem = create_sem( 1, "nspr_sem"); - PR_ASSERT( cv->isem >= B_NO_ERROR ); + cv->sem = create_sem(0, "CVSem"); + cv->handshakeSem = create_sem(0, "CVHandshake"); + cv->signalSem = create_sem( 0, "CVSignal"); + cv->signalBenCount = 0; + cv->ns = cv->nw = 0; + PR_ASSERT( cv->sem >= B_NO_ERROR ); + PR_ASSERT( cv->handshakeSem >= B_NO_ERROR ); + PR_ASSERT( cv->signalSem >= B_NO_ERROR ); } return cv; } /* PR_NewCondVar */ @@ -70,10 +76,15 @@ PR_IMPLEMENT(PRCondVar*) PR_IMPLEMENT(void) PR_DestroyCondVar (PRCondVar *cvar) { - status_t result; + status_t result = delete_sem( cvar->sem ); + PR_ASSERT( result == B_NO_ERROR ); + + result = delete_sem( cvar->handshakeSem ); + PR_ASSERT( result == B_NO_ERROR ); - result = delete_sem( cvar->isem ); + result = delete_sem( cvar->signalSem ); PR_ASSERT( result == B_NO_ERROR ); + PR_DELETE( cvar ); } @@ -108,51 +119,59 @@ PR_IMPLEMENT(void) PR_IMPLEMENT(PRStatus) PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout) { - status_t result; - bigtime_t interval; + status_t err; + if( timeout == PR_INTERVAL_NO_WAIT ) + { + PR_Unlock( cvar->lock ); + PR_Lock( cvar->lock ); + return PR_SUCCESS; + } + + if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) + { + if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) + { + atomic_add( &cvar->signalBenCount, -1 ); + return PR_FAILURE; + } + } + cvar->nw += 1; + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } PR_Unlock( cvar->lock ); + if( timeout==PR_INTERVAL_NO_TIMEOUT ) + { + err = acquire_sem(cvar->sem); + } + else + { + err = acquire_sem_etc(cvar->sem, 1, B_RELATIVE_TIMEOUT, PR_IntervalToMicroseconds(timeout) ); + } - switch (timeout) { - case PR_INTERVAL_NO_WAIT: - /* nothing to do */ - break; - - case PR_INTERVAL_NO_TIMEOUT: - /* wait as long as necessary */ - if( acquire_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE; - break; - - default: - interval = (bigtime_t)PR_IntervalToMicroseconds(timeout); - - /* - ** in R5, this problem seems to have been resolved, so we - ** won't bother with it - */ -#if !defined(B_BEOS_VERSION_5) || (B_BEOS_VERSION < B_BEOS_VERSION_5) - /* - ** This is an entirely stupid bug, but... If you call - ** acquire_sem_etc with a timeout of exactly 1,000,000 microseconds - ** it returns immediately with B_NO_ERROR. 1,000,010 microseconds - ** returns as expected. Running BeOS/Intel R3.1 at this time. - ** Forwarded to Be, Inc. for resolution, Bug ID 980624-225956 - ** - ** Update: Be couldn't reproduce it, but removing timeout++ still - ** exhibits the problem on BeOS/Intel R4 and BeOS/PPC R4. - */ - if (interval == 1000000) - interval = 1000010; -#endif /* !defined(B_BEOS_VERSION_5) || (B_BEOS_VERSION < B_BEOS_VERSION_5) */ - - result = acquire_sem_etc( cvar->isem, 1, B_RELATIVE_TIMEOUT, interval); - if( result != B_NO_ERROR && result != B_TIMED_OUT ) - return PR_FAILURE; - break; + if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) + { + while (acquire_sem(cvar->signalSem) == B_INTERRUPTED); } - PR_Lock( cvar->lock ); + if (cvar->ns > 0) + { + release_sem(cvar->handshakeSem); + cvar->ns -= 1; + } + cvar->nw -= 1; + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } + PR_Lock( cvar->lock ); + if(err!=B_NO_ERROR) + { + return PR_FAILURE; + } return PR_SUCCESS; } @@ -172,8 +191,36 @@ PR_IMPLEMENT(PRStatus) PR_IMPLEMENT(PRStatus) PR_NotifyCondVar (PRCondVar *cvar) { - if( release_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE; + status_t err ; + if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) + { + if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) + { + atomic_add( &cvar->signalBenCount, -1 ); + return PR_FAILURE; + } + } + if (cvar->nw > cvar->ns) + { + cvar->ns += 1; + release_sem(cvar->sem); + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } + while (acquire_sem(cvar->handshakeSem) == B_INTERRUPTED) + { + err = B_INTERRUPTED; + } + } + else + { + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } + } return PR_SUCCESS; } @@ -188,13 +235,39 @@ PR_IMPLEMENT(PRStatus) PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar (PRCondVar *cvar) { - sem_info semInfo; + int32 handshakes; + status_t err = B_OK; - if( get_sem_info( cvar->isem, &semInfo ) != B_NO_ERROR ) - return PR_FAILURE; + if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) + { + if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) + { + atomic_add( &cvar->signalBenCount, -1 ); + return PR_FAILURE; + } + } - if( release_sem_etc( cvar->isem, semInfo.count, 0 ) != B_NO_ERROR ) - return PR_FAILURE; + if (cvar->nw > cvar->ns) + { + handshakes = cvar->nw - cvar->ns; + cvar->ns = cvar->nw; + release_sem_etc(cvar->sem, handshakes, 0); + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } + while (acquire_sem_etc(cvar->handshakeSem, handshakes, 0, 0) == B_INTERRUPTED) + { + err = B_INTERRUPTED; + } + } + else + { + if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) + { + release_sem(cvar->signalSem); + } + } return PR_SUCCESS; } diff --git a/pr/src/bthreads/btmon.c b/pr/src/bthreads/btmon.c index da588c3a..5f88ad34 100644 --- a/pr/src/bthreads/btmon.c +++ b/pr/src/bthreads/btmon.c @@ -78,7 +78,10 @@ PR_IMPLEMENT(PRMonitor*) PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); - mon->name = name; + if( mon ) + { + mon->name = name; + } return mon; } diff --git a/pr/src/io/Makefile.in b/pr/src/io/Makefile.in index 179656aa..e7316b38 100644 --- a/pr/src/io/Makefile.in +++ b/pr/src/io/Makefile.in @@ -81,5 +81,13 @@ DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk +# An OS/2 Optimization bug causes PR_snprintf() to produce wrong result. +# This suppresses optimization for this single compilation unit. +ifeq ($(MOZ_OS2_TOOLS),VACPP) +$(OBJDIR)/prprf.obj: prprf.c + @$(MAKE_OBJDIR) + $(CC) -Fo$@ -c $(filter-out /O+, $(CFLAGS)) $< +endif + export:: $(TARGETS) diff --git a/pr/src/io/prdir.c b/pr/src/io/prdir.c index d0f469e9..8aa66435 100644 --- a/pr/src/io/prdir.c +++ b/pr/src/io/prdir.c @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Roy Yokoyama <yokoyama@netscape.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -109,3 +110,52 @@ PRInt32 rv; return PR_SUCCESS; } +#ifdef MOZ_UNICODE +/* + * UTF16 Interface + */ +PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name) +{ + PRDirUTF16 *dir; + PRStatus sts; + + dir = PR_NEW(PRDirUTF16); + if (dir) { + sts = _PR_MD_OPEN_DIR_UTF16(&dir->md,name); + if (sts != PR_SUCCESS) { + PR_DELETE(dir); + return NULL; + } + } else { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + } + return dir; +} + +PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags) +{ + /* + * _MD_READ_DIR_UTF16 return a PRUnichar* to the name; allocation in + * machine-dependent code + */ + PRUnichar* name = _PR_MD_READ_DIR_UTF16(&dir->md, flags); + dir->d.name = name; + return name ? &dir->d : NULL; +} + +PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir) +{ + PRInt32 rv; + + if (dir) { + rv = _PR_MD_CLOSE_DIR_UTF16(&dir->md); + PR_DELETE(dir); + if (rv < 0) + return PR_FAILURE; + else + return PR_SUCCESS; + } + return PR_SUCCESS; +} + +#endif /* MOZ_UNICODE */ diff --git a/pr/src/io/prfdcach.c b/pr/src/io/prfdcach.c index 8803a419..82cbf058 100644 --- a/pr/src/io/prfdcach.c +++ b/pr/src/io/prfdcach.c @@ -73,7 +73,7 @@ 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 *_PR_Getfd(void) { PRFileDesc *fd; /* @@ -248,7 +248,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high) return PR_SUCCESS; } /* PR_SetFDCacheSize */ -void _PR_InitFdCache() +void _PR_InitFdCache(void) { /* ** The fd caching is enabled by default for DEBUG builds, diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c index e19705c7..25354453 100644 --- a/pr/src/io/prfile.c +++ b/pr/src/io/prfile.c @@ -203,7 +203,7 @@ static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd) return PR_SUCCESS; } -static PRStatus PR_CALLBACK FileInfo(PRFileDesc *fd, PRFileInfo *info) +static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info) { PRInt32 rv; @@ -214,7 +214,7 @@ static PRStatus PR_CALLBACK FileInfo(PRFileDesc *fd, PRFileInfo *info) return PR_SUCCESS; } -static PRStatus PR_CALLBACK FileInfo64(PRFileDesc *fd, PRFileInfo64 *info) +static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info) { #ifdef XP_MAC #pragma unused( fd, info ) @@ -276,8 +276,8 @@ static PRIOMethods _pr_fileMethods = { FileSync, FileSeek, FileSeek64, - FileInfo, - FileInfo64, + FileGetInfo, + FileGetInfo64, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, @@ -422,14 +422,18 @@ PRInt32 PR_GetSysfdTableMax(void) return rlim.rlim_max; #elif defined(AIX) || defined(NEXTSTEP) || defined(QNX) return sysconf(_SC_OPEN_MAX); -#elif defined(WIN32) || defined(OS2) +#elif defined(WIN32) /* * There is a systemwide limit of 65536 user handles. - * Not sure on OS/2, but sounds good. */ return 16384; #elif defined (WIN16) return FOPEN_MAX; +#elif defined(XP_OS2) + ULONG ulReqCount = 0; + ULONG ulCurMaxFH = 0; + DosSetRelMaxFH(&ulReqCount, &ulCurMaxFH); + return ulCurMaxFH; #elif defined (XP_MAC) || defined(XP_BEOS) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; @@ -464,9 +468,19 @@ PRInt32 PR_SetSysfdTableSize(int table_size) } return rlim.rlim_cur; +#elif defined(XP_OS2) + PRInt32 tableMax = PR_GetSysfdTableMax(); + if (table_size > tableMax) { + APIRET rc = NO_ERROR; + rc = DosSetMaxFH(table_size); + if (rc == NO_ERROR) + return table_size; + else + return -1; + } + return tableMax; #elif defined(AIX) || defined(NEXTSTEP) || defined(QNX) \ - || defined(WIN32) || defined(WIN16) || defined(OS2) \ - || defined(XP_BEOS) + || defined(WIN32) || defined(WIN16) || defined(XP_BEOS) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; #elif defined (XP_MAC) @@ -735,7 +749,7 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe( (*readPipe)->secret->inheritable = _PR_TRI_TRUE; (*writePipe)->secret->inheritable = _PR_TRI_TRUE; return PR_SUCCESS; -#elif defined(XP_UNIX) || defined(XP_OS2) +#elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) #ifdef XP_OS2 HFILE pipefd[2]; #else @@ -765,9 +779,13 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe( close(pipefd[1]); return PR_FAILURE; } - _MD_MakeNonblock(*readPipe); +#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */ + _PR_MD_MAKE_NONBLOCK(*readPipe); +#endif _PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE); - _MD_MakeNonblock(*writePipe); +#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */ + _PR_MD_MAKE_NONBLOCK(*writePipe); +#endif _PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE); return PR_SUCCESS; #else @@ -775,3 +793,51 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe( return PR_FAILURE; #endif } + +#ifdef MOZ_UNICODE +/* ================ UTF16 Interfaces ================================ */ +PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16( + const PRUnichar *name, PRIntn flags, PRIntn mode) +{ + PRInt32 osfd; + PRFileDesc *fd = 0; +#if !defined(XP_UNIX) /* BugZilla: 4090 */ + PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE; +#endif + + if (!_pr_initialized) _PR_ImplicitInitialization(); + + /* Map pr open flags and mode to os specific flags */ + osfd = _PR_MD_OPEN_FILE_UTF16(name, flags, mode); + if (osfd != -1) { + fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); + if (!fd) { + (void) _PR_MD_CLOSE_FILE(osfd); + } else { +#if !defined(XP_UNIX) /* BugZilla: 4090 */ + fd->secret->appendMode = appendMode; +#endif + _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); + } + } + return fd; +} + +PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ +#ifdef XP_MAC +#pragma unused (fn, info) +#endif + PRInt32 rv; + + if (!_pr_initialized) _PR_ImplicitInitialization(); + rv = _PR_MD_GETFILEINFO64_UTF16(fn, info); + if (rv < 0) { + return PR_FAILURE; + } else { + return PR_SUCCESS; + } +} + +/* ================ UTF16 Interfaces ================================ */ +#endif /* MOZ_UNICODE */ diff --git a/pr/src/io/prio.c b/pr/src/io/prio.c index 250d9b6f..66ecd7cc 100644 --- a/pr/src/io/prio.c +++ b/pr/src/io/prio.c @@ -164,7 +164,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable( PRFileDesc *fd, PRBool inheritable) { -#if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2) +#if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2) || defined(XP_BEOS) /* * Only a non-layered, NSPR file descriptor can be inherited * by a child process. @@ -188,3 +188,12 @@ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable( return PR_FAILURE; #endif } + +/* +** This function only has a useful implementation in the debug build of +** the pthreads version. +*/ +PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) +{ + /* do nothing */ +} /* PT_FPrintStats */ diff --git a/pr/src/io/priometh.c b/pr/src/io/priometh.c index a2b8e9c8..251d46a9 100644 --- a/pr/src/io/priometh.c +++ b/pr/src/io/priometh.c @@ -34,6 +34,8 @@ */ #include "primpl.h" +#include <string.h> + /*****************************************************************************/ /************************** Invalid I/O method object ************************/ /*****************************************************************************/ @@ -76,21 +78,21 @@ PRIOMethods _pr_faulty_methods = { (PRReservedFN)_PR_InvalidInt }; -PRIntn _PR_InvalidInt() +PRIntn _PR_InvalidInt(void) { PR_ASSERT(!"I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } /* _PR_InvalidInt */ -PRInt16 _PR_InvalidInt16() +PRInt16 _PR_InvalidInt16(void) { PR_ASSERT(!"I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } /* _PR_InvalidInt */ -PRInt64 _PR_InvalidInt64() +PRInt64 _PR_InvalidInt64(void) { PRInt64 rv; LL_I2L(rv, -1); @@ -103,7 +105,7 @@ PRInt64 _PR_InvalidInt64() * An invalid method that returns PRStatus */ -PRStatus _PR_InvalidStatus() +PRStatus _PR_InvalidStatus(void) { PR_ASSERT(!"I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); @@ -114,7 +116,7 @@ PRStatus _PR_InvalidStatus() * An invalid method that returns a pointer */ -PRFileDesc *_PR_InvalidDesc() +PRFileDesc *_PR_InvalidDesc(void) { PR_ASSERT(!"I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); diff --git a/pr/src/io/pripv6.c b/pr/src/io/pripv6.c index fd104677..a5c2360f 100644 --- a/pr/src/io/pripv6.c +++ b/pr/src/io/pripv6.c @@ -276,51 +276,41 @@ static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf, #if defined(_PR_INET6_PROBE) PRBool _pr_ipv6_is_present; -PR_EXTERN(PRBool) _pr_test_ipv6_socket(); -#if defined(_PR_HAVE_GETIPNODEBYNAME) -void *_pr_getipnodebyname_fp; -void *_pr_getipnodebyaddr_fp; -void *_pr_freehostent_fp; +extern PRBool _pr_test_ipv6_socket(void); + +#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) +extern PRStatus _pr_find_getipnodebyname(void); +#endif + +#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) +extern PRStatus _pr_find_getaddrinfo(void); #endif + +static PRBool +_pr_probe_ipv6_presence(void) +{ +#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) + if (_pr_find_getipnodebyname() != PR_SUCCESS) + return PR_FALSE; #endif +#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) + if (_pr_find_getaddrinfo() != PR_SUCCESS) + return PR_FALSE; +#endif + + return _pr_test_ipv6_socket(); +} +#endif /* _PR_INET6_PROBE */ + PRStatus _pr_init_ipv6() { const PRIOMethods *stubMethods; #if defined(_PR_INET6_PROBE) - -#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) - PRLibrary *lib; -#if defined(VMS) -#define GETIPNODEBYNAME getenv("GETIPNODEBYNAME") -#define GETIPNODEBYADDR getenv("GETIPNODEBYADDR") -#define FREEHOSTENT getenv("FREEHOSTENT") -#else -#define GETIPNODEBYNAME "getipnodebyname" -#define GETIPNODEBYADDR "getipnodebyaddr" -#define FREEHOSTENT "freehostent" -#endif - _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib); - if (NULL != _pr_getipnodebyname_fp) { - _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT); - if (NULL != _pr_freehostent_fp) { - _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR); - if (NULL != _pr_getipnodebyaddr_fp) - _pr_ipv6_is_present = PR_TRUE; - else - _pr_ipv6_is_present = PR_FALSE; - } else - _pr_ipv6_is_present = PR_FALSE; - (void)PR_UnloadLibrary(lib); - } else - _pr_ipv6_is_present = PR_FALSE; - if (PR_TRUE == _pr_ipv6_is_present) -#endif - - _pr_ipv6_is_present = _pr_test_ipv6_socket(); - if (PR_TRUE == _pr_ipv6_is_present) - return PR_SUCCESS; + _pr_ipv6_is_present = _pr_probe_ipv6_presence(); + if (PR_TRUE == _pr_ipv6_is_present) + return PR_SUCCESS; #endif _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer"); diff --git a/pr/src/io/prlayer.c b/pr/src/io/prlayer.c index d74fa8be..d377f546 100644 --- a/pr/src/io/prlayer.c +++ b/pr/src/io/prlayer.c @@ -459,7 +459,7 @@ static PRIOMethods pl_methods = { (PRReservedFN)_PR_InvalidInt }; -PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods() +PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void) { return &pl_methods; } /* PR_GetDefaultIOMethods */ @@ -736,7 +736,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity i return NULL; } /* PR_GetIdentitiesLayer */ -void _PR_InitLayerCache() +void _PR_InitLayerCache(void) { memset(&identity_cache, 0, sizeof(identity_cache)); identity_cache.ml = PR_NewLock(); diff --git a/pr/src/io/prlog.c b/pr/src/io/prlog.c index 16f68823..b73543f8 100644 --- a/pr/src/io/prlog.c +++ b/pr/src/io/prlog.c @@ -194,13 +194,16 @@ void _PR_InitLog(void) ev = PR_GetEnv("NSPR_LOG_MODULES"); if (ev && ev[0]) { - char module[64]; + char module[64]; /* Security-Critical: If you change this + * size, you must also change the sscanf + * format string to be size-1. + */ PRBool isSync = PR_FALSE; PRIntn evlen = strlen(ev), pos = 0; PRInt32 bufSize = DEFAULT_BUF_SIZE; while (pos < evlen) { PRIntn level = 1, count = 0, delta = 0; - count = sscanf(&ev[pos], "%64[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n", + count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n", module, &delta, &level, &delta); pos += delta; if (count == 0) break; @@ -232,7 +235,7 @@ void _PR_InitLog(void) /*found:*/ count = sscanf(&ev[pos], " , %n", &delta); pos += delta; - if (count == -1) break; + if (count == EOF) break; } PR_SetLogBuffering(isSync ? bufSize : 0); @@ -266,7 +269,13 @@ void _PR_LogCleanup(void) PR_LogFlush(); #ifdef _PR_USE_STDIO_FOR_LOGGING - if (logFile && logFile != stdout && logFile != stderr) { + if (logFile + && logFile != stdout + && logFile != stderr +#ifdef XP_PC + && logFile != WIN32_DEBUG_FILE +#endif + ) { fclose(logFile); } #else @@ -277,11 +286,16 @@ void _PR_LogCleanup(void) while (lm != NULL) { PRLogModuleInfo *next = lm->next; - PR_Free((/*const*/ char *)lm->name); + free((/*const*/ char *)lm->name); PR_Free(lm); lm = next; } logModules = NULL; + + if (_pr_logLock) { + PR_DestroyLock(_pr_logLock); + _pr_logLock = NULL; + } } static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm ) @@ -290,12 +304,15 @@ static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm ) ev = PR_GetEnv("NSPR_LOG_MODULES"); if (ev && ev[0]) { - char module[64]; + char module[64]; /* Security-Critical: If you change this + * size, you must also change the sscanf + * format string to be size-1. + */ PRIntn evlen = strlen(ev), pos = 0; while (pos < evlen) { PRIntn level = 1, count = 0, delta = 0; - count = sscanf(&ev[pos], "%64[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n", + count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n", module, &delta, &level, &delta); pos += delta; if (count == 0) break; @@ -314,7 +331,7 @@ static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm ) } count = sscanf(&ev[pos], " , %n", &delta); pos += delta; - if (count == -1) break; + if (count == EOF) break; } } } /* end _PR_SetLogModuleLevel() */ @@ -344,24 +361,33 @@ PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file) #ifdef XP_PC if ( strcmp( file, "WinDebug") == 0) { - logFile = WIN32_DEBUG_FILE; - return(PR_TRUE); + newLogFile = WIN32_DEBUG_FILE; } + else #endif - newLogFile = fopen(file, "w"); - if (newLogFile) { + { + newLogFile = fopen(file, "w"); + if (!newLogFile) + return PR_FALSE; + /* We do buffering ourselves. */ setvbuf(newLogFile, NULL, _IONBF, 0); - if (logFile && logFile != stdout && logFile != stderr) { - fclose(logFile); - } - logFile = newLogFile; } - return (PRBool) (newLogFile != 0); + if (logFile + && logFile != stdout + && logFile != stderr +#ifdef XP_PC + && logFile != WIN32_DEBUG_FILE +#endif + ) { + fclose(logFile); + } + logFile = newLogFile; + return PR_TRUE; #else PRFileDesc *newLogFile; - newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE, 0666); + newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0666); if (newLogFile) { if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) { PR_Close(logFile); @@ -482,8 +508,7 @@ PR_IMPLEMENT(void) PR_Abort(void) #include <builtin.h> static void DebugBreak(void) { _interrupt(3); } #elif defined(XP_OS2_EMX) -/* Force a trap */ -static void DebugBreak(void) { int *pTrap=NULL; *pTrap = 1; } +static void DebugBreak(void) { asm("int $3"); } #else static void DebugBreak(void) { } #endif diff --git a/pr/src/io/prmapopt.c b/pr/src/io/prmapopt.c index f017c36a..2e6d219a 100644 --- a/pr/src/io/prmapopt.c +++ b/pr/src/io/prmapopt.c @@ -46,10 +46,20 @@ * includes winsock.h, with _WIN32_WINNT undefined. */ -#ifdef WINNT +#if defined(WINNT) || defined(__MINGW32__) #include <winsock.h> #endif +/* MinGW doesn't define these in its winsock.h. */ +#ifdef __MINGW32__ +#ifndef IP_TTL +#define IP_TTL 7 +#endif +#ifndef IP_TOS +#define IP_TOS 8 +#endif +#endif + #include "primpl.h" #if defined(NEXTSTEP) @@ -57,7 +67,7 @@ #include <netinet/in_systm.h> /* n_short, n_long, n_time */ #endif -#if defined(XP_UNIX) || defined(OS2) +#if defined(XP_UNIX) || defined(OS2) || (defined(XP_BEOS) && defined(BONE_VERSION)) #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */ #endif @@ -86,7 +96,7 @@ PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionDat { case PR_SockOpt_Linger: { -#if !defined(XP_BEOS) +#if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; length = sizeof(linger); rv = _PR_MD_GETSOCKOPT( @@ -244,7 +254,7 @@ PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOpt { case PR_SockOpt_Linger: { -#if !defined(XP_BEOS) +#if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; linger.l_onoff = data->value.linger.polarity; linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger); diff --git a/pr/src/io/prmwait.c b/pr/src/io/prmwait.c index a48fbc19..65ea1cd6 100644 --- a/pr/src/io/prmwait.c +++ b/pr/src/io/prmwait.c @@ -58,19 +58,8 @@ typedef struct TimerEvent { struct { PRLock *ml; PRCondVar *new_timer; - PRCondVar *cancel_timer; /* The cancel_timer condition variable is - * used to cancel a timer (i.e., remove a - * timer event from the timer queue). At - * startup I'm borrowing this condition - * variable for a different purpose (to - * tell the primordial thread that the - * timer manager thread has started) so - * that I don't need to create a new - * condition variable just for this one - * time use. - */ + PRCondVar *cancel_timer; PRThread *manager_thread; - PRBool manager_started; PRCList timer_queue; } tm_vars; @@ -88,11 +77,6 @@ static void TimerManager(void *arg) TimerEvent *timer; PR_Lock(tm_vars.ml); - /* tell the primordial thread that we have started */ - tm_vars.manager_started = PR_TRUE; - if (!_native_threads_only) { - PR_NotifyCondVar(tm_vars.cancel_timer); - } while (1) { if (PR_CLIST_IS_EMPTY(&tm_vars.timer_queue)) @@ -216,16 +200,6 @@ static PRStatus TimerInit(void) { goto failed; } - /* - * Need to wait until the timer manager thread starts - * if the timer manager thread is a local thread. - */ - if (!_native_threads_only) { - PR_Lock(tm_vars.ml); - while (!tm_vars.manager_started) - PR_WaitCondVar(tm_vars.cancel_timer, PR_INTERVAL_NO_TIMEOUT); - PR_Unlock(tm_vars.ml); - } return PR_SUCCESS; failed: @@ -269,6 +243,17 @@ void _PR_InitMW(void) max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL); } /* _PR_InitMW */ +void _PR_CleanupMW(void) +{ + PR_DestroyLock(mw_lock); + mw_lock = NULL; + if (mw_state->group) { + PR_DestroyWaitGroup(mw_state->group); + /* mw_state->group is set to NULL as a side effect. */ + } + PR_DELETE(mw_state); +} /* _PR_CleanupMW */ + static PRWaitGroup *MW_Init2(void) { PRWaitGroup *group = mw_state->group; /* it's the null group */ diff --git a/pr/src/io/prprf.c b/pr/src/io/prprf.c index 2d6a78d8..5f4de6f4 100644 --- a/pr/src/io/prprf.c +++ b/pr/src/io/prprf.c @@ -51,8 +51,12 @@ ** Note: on some platforms va_list is defined as an array, ** and requires array notation. */ -#if (defined(LINUX) && defined(__powerpc__)) || defined(WIN16) || \ - defined(QNX) || \ +#if (defined(LINUX) && defined(__x86_64__)) +#define VARARGS_ASSIGN(foo, bar) __va_copy((foo), (bar)) +#elif (defined(LINUX) && defined(__powerpc__)) || \ + (defined(LINUX) && defined(__s390__)) || \ + (defined(LINUX) && defined(__s390x__)) || \ + defined(WIN16) || defined(QNX) || \ (defined(__NetBSD__) && defined(__powerpc__) && \ __NetBSD_Version__ < 105000000) #define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0] @@ -89,9 +93,6 @@ struct NumArgState{ va_list ap; /* point to the corresponding position on ap */ }; -static PRBool l10n_debug_init = PR_FALSE; -static PRBool l10n_debug = PR_FALSE; - #define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */ @@ -108,11 +109,11 @@ static PRBool l10n_debug = PR_FALSE; #define TYPE_INTSTR 10 #define TYPE_UNKNOWN 20 -#define _LEFT 0x1 -#define _SIGNED 0x2 -#define _SPACED 0x4 -#define _ZEROS 0x8 -#define _NEG 0x10 +#define FLAG_LEFT 0x1 +#define FLAG_SIGNED 0x2 +#define FLAG_SPACED 0x4 +#define FLAG_ZEROS 0x8 +#define FLAG_NEG 0x10 /* ** Fill into the buffer using the data in src @@ -124,8 +125,8 @@ static int fill2(SprintfState *ss, const char *src, int srclen, int width, int rv; width -= srclen; - if ((width > 0) && ((flags & _LEFT) == 0)) { /* Right adjusting */ - if (flags & _ZEROS) { + if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */ + if (flags & FLAG_ZEROS) { space = '0'; } while (--width >= 0) { @@ -142,7 +143,7 @@ static int fill2(SprintfState *ss, const char *src, int srclen, int width, return rv; } - if ((width > 0) && ((flags & _LEFT) != 0)) { /* Left adjusting */ + if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */ while (--width >= 0) { rv = (*ss->stuff)(ss, &space, 1); if (rv < 0) { @@ -169,13 +170,13 @@ static int fill_n(SprintfState *ss, const char *src, int srclen, int width, char sign; if ((type & 1) == 0) { - if (flags & _NEG) { + if (flags & FLAG_NEG) { sign = '-'; signwidth = 1; - } else if (flags & _SIGNED) { + } else if (flags & FLAG_SIGNED) { sign = '+'; signwidth = 1; - } else if (flags & _SPACED) { + } else if (flags & FLAG_SPACED) { sign = ' '; signwidth = 1; } @@ -189,14 +190,14 @@ static int fill_n(SprintfState *ss, const char *src, int srclen, int width, } } - if ((flags & _ZEROS) && (prec < 0)) { + if ((flags & FLAG_ZEROS) && (prec < 0)) { if (width > cvtwidth) { zerowidth = width - cvtwidth; /* Zero filling */ cvtwidth += zerowidth; } } - if (flags & _LEFT) { + if (flags & FLAG_LEFT) { if (width > cvtwidth) { /* Space filling on the right (i.e. left adjusting) */ rightspaces = width - cvtwidth; @@ -412,20 +413,6 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, /* - ** set the l10n_debug flag - ** this routine should be executed only once - ** 'cause getenv does take time - */ - if( !l10n_debug_init ){ - l10n_debug_init = PR_TRUE; - p = getenv( "NETSCAPE_LOCALIZATION_DEBUG" ); - if( ( p != NULL ) && ( *p == '1' ) ){ - l10n_debug = PR_TRUE; - } - } - - - /* ** first pass: ** detemine how many legal % I have got, then allocate space */ @@ -444,23 +431,17 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, if( c == '$' ){ /* numbered argument csae */ if( i > 0 ){ *rv = -1; - if( l10n_debug ) - printf( "either no *OR* all arguments are numbered \"%s\"\n", fmt ); return NULL; } number++; - break; - } else{ /* non-numbered argument case */ if( number > 0 ){ - if( l10n_debug ) - printf( "either no *OR* all arguments are numbered \"%s\"\n", fmt ); *rv = -1; return NULL; } i = 1; - break; } + break; } c = *p++; @@ -476,8 +457,6 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, nas = (struct NumArgState*)PR_MALLOC( number * sizeof( struct NumArgState ) ); if( !nas ){ *rv = -1; - if( l10n_debug ) - printf( "PR_MALLOC() error for \"%s\"\n", fmt ); return NULL; } } else { @@ -508,8 +487,6 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, if( !c || cn < 1 || cn > number ){ *rv = -1; - if( l10n_debug ) - printf( "invalid argument number (valid range [1, %d]), \"%s\"\n", number, fmt ); break; } @@ -524,13 +501,11 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, if (c == '*') { /* not supported feature, for the argument is not numbered */ *rv = -1; - if( l10n_debug ) - printf( "* width specifier not support for numbered arguments \"%s\"\n", fmt ); break; - } else { - while ((c >= '0') && (c <= '9')) { - c = *p++; - } + } + + while ((c >= '0') && (c <= '9')) { + c = *p++; } /* precision */ @@ -538,14 +513,12 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, c = *p++; if (c == '*') { /* not supported feature, for the argument is not numbered */ - if( l10n_debug ) - printf( "* precision specifier not support for numbered arguments \"%s\"\n", fmt ); *rv = -1; break; - } else { - while ((c >= '0') && (c <= '9')) { - c = *p++; - } + } + + while ((c >= '0') && (c <= '9')) { + c = *p++; } } @@ -622,8 +595,6 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, /* get a legal para. */ if( nas[ cn ].type == TYPE_UNKNOWN ){ - if( l10n_debug ) - printf( "unknown type \"%s\"\n", fmt ); *rv = -1; break; } @@ -757,8 +728,6 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) } if( nas[i-1].type == TYPE_UNKNOWN ){ - if( l10n_debug ) - printf( "numbered argument type unknown\n" ); if( nas && ( nas != nasArray ) ) PR_DELETE( nas ); return -1; @@ -777,14 +746,14 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) * on this feature. */ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) { - if (c == '-') flags |= _LEFT; - if (c == '+') flags |= _SIGNED; - if (c == ' ') flags |= _SPACED; - if (c == '0') flags |= _ZEROS; + if (c == '-') flags |= FLAG_LEFT; + if (c == '+') flags |= FLAG_SIGNED; + if (c == ' ') flags |= FLAG_SPACED; + if (c == '0') flags |= FLAG_ZEROS; c = *fmt++; } - if (flags & _SIGNED) flags &= ~_SPACED; - if (flags & _LEFT) flags &= ~_ZEROS; + if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED; + if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS; /* width */ if (c == '*') { @@ -866,7 +835,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) u.l = va_arg(ap, int); if (u.l < 0) { u.l = -u.l; - flags |= _NEG; + flags |= FLAG_NEG; } goto do_long; case TYPE_UINT16: @@ -876,7 +845,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) u.l = va_arg(ap, int); if (u.l < 0) { u.l = -u.l; - flags |= _NEG; + flags |= FLAG_NEG; } goto do_long; case TYPE_UINTN: @@ -887,7 +856,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) u.l = va_arg(ap, PRInt32); if (u.l < 0) { u.l = -u.l; - flags |= _NEG; + flags |= FLAG_NEG; } goto do_long; case TYPE_UINT32: @@ -903,7 +872,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) u.ll = va_arg(ap, PRInt64); if (!LL_GE_ZERO(u.ll)) { LL_NEG(u.ll, u.ll); - flags |= _NEG; + flags |= FLAG_NEG; } goto do_longlong; case TYPE_UINT64: @@ -939,7 +908,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) case 'c': u.ch = va_arg(ap, int); - if ((flags & _LEFT) == 0) { + if ((flags & FLAG_LEFT) == 0) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { @@ -951,7 +920,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) if (rv < 0) { return rv; } - if (flags & _LEFT) { + if (flags & FLAG_LEFT) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { @@ -1044,7 +1013,7 @@ PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg, const char *fmt, ...) { va_list ap; - int rv; + PRUint32 rv; va_start(ap, fmt); rv = PR_vsxprintf(func, arg, fmt, ap); @@ -1168,7 +1137,7 @@ static int LimitStuff(SprintfState *ss, const char *sp, PRUint32 len) PR_IMPLEMENT(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...) { va_list ap; - int rv; + PRUint32 rv; PR_ASSERT((PRInt32)outlen > 0); if ((PRInt32)outlen <= 0) { diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c index 2483f963..999fc03d 100644 --- a/pr/src/io/prsocket.c +++ b/pr/src/io/prsocket.c @@ -44,7 +44,7 @@ PRBool IsValidNetAddr(const PRNetAddr *addr) { if ((addr != NULL) -#ifdef XP_UNIX +#if defined(XP_UNIX) || defined(XP_OS2) && (addr->raw.family != PR_AF_LOCAL) #endif && (addr->raw.family != PR_AF_INET6) @@ -61,7 +61,7 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) * is not uniform, so we don't check it. */ if ((addr != NULL) -#ifdef XP_UNIX +#if defined(XP_UNIX) || defined(XP_OS2) && (addr->raw.family != AF_UNIX) #endif && (PR_NETADDR_SIZE(addr) != addr_len)) { @@ -338,27 +338,16 @@ static PRStatus PR_CALLBACK SocketConnectContinue( #elif defined(XP_OS2) - if (out_flags & PR_POLL_EXCEPT) { - int len = sizeof(err); - if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) - < 0) { - _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno()); - return PR_FAILURE; - } - if (err != 0) { - _PR_MD_MAP_CONNECT_ERROR(err); - } else { - PR_SetError(PR_UNKNOWN_ERROR, 0); - } + err = _MD_os2_get_nonblocking_connect_error(osfd); + if (err != 0) { + _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } - - PR_ASSERT(out_flags & PR_POLL_WRITE); return PR_SUCCESS; #elif defined(XP_MAC) - err = _MD_mac_get_nonblocking_connect_error(osfd); + err = _MD_mac_get_nonblocking_connect_error(fd); if (err == -1) return PR_FAILURE; else @@ -366,13 +355,23 @@ static PRStatus PR_CALLBACK SocketConnectContinue( #elif defined(XP_BEOS) +#ifdef BONE_VERSION /* bug 122364 */ + /* temporary workaround until getsockopt(SO_ERROR) works in BONE */ + if (out_flags & PR_POLL_EXCEPT) { + PR_SetError(PR_CONNECT_REFUSED_ERROR, 0); + return PR_FAILURE; + } + PR_ASSERT(out_flags & PR_POLL_WRITE); + return PR_SUCCESS; +#else err = _MD_beos_get_nonblocking_connect_error(fd); if( err != 0 ) { - _PR_MD_MAP_CONNECT_ERROR(err); - return PR_FAILURE; + _PR_MD_MAP_CONNECT_ERROR(err); + return PR_FAILURE; } else - return PR_SUCCESS; + return PR_SUCCESS; +#endif /* BONE_VERSION */ #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); @@ -1274,7 +1273,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) if (!_pr_initialized) _PR_ImplicitInitialization(); if (PR_AF_INET != domain && PR_AF_INET6 != domain -#if defined(XP_UNIX) +#if defined(XP_UNIX) || defined(XP_OS2) && PR_AF_LOCAL != domain #endif ) { @@ -1396,7 +1395,7 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[]) */ SOCKET listenSock; SOCKET osfd[2]; - struct sockaddr_in selfAddr; + struct sockaddr_in selfAddr, peerAddr; int addrLen; if (!_pr_initialized) _PR_ImplicitInitialization(); @@ -1440,10 +1439,24 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[]) addrLen) == SOCKET_ERROR) { goto failed; } - osfd[1] = accept(listenSock, NULL, NULL); + /* + * A malicious local process may connect to the listening + * socket, so we need to verify that the accepted connection + * is made from our own socket osfd[0]. + */ + if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, + &addrLen) == SOCKET_ERROR) { + goto failed; + } + osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); if (osfd[1] == INVALID_SOCKET) { goto failed; } + if (peerAddr.sin_port != selfAddr.sin_port) { + /* the connection we accepted is not from osfd[0] */ + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); + goto failed; + } closesocket(listenSock); f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); @@ -1480,7 +1493,7 @@ failed: * default implementation */ PRFileDesc *listenSock; - PRNetAddr selfAddr; + PRNetAddr selfAddr, peerAddr; PRUint16 port; f[0] = f[1] = NULL; @@ -1503,6 +1516,17 @@ failed: if (f[0] == NULL) { goto failed; } +#ifdef _PR_CONNECT_DOES_NOT_BIND + /* + * If connect does not implicitly bind the socket (e.g., on + * BeOS), we have to bind the socket so that we can get its + * port with getsockname later. + */ + PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); + if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) { + goto failed; + } +#endif PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); /* @@ -1518,10 +1542,23 @@ failed: == PR_FAILURE) { goto failed; } - f[1] = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); + /* + * A malicious local process may connect to the listening + * socket, so we need to verify that the accepted connection + * is made from our own socket f[0]. + */ + if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) { + goto failed; + } + f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); if (f[1] == NULL) { goto failed; } + if (peerAddr.inet.port != selfAddr.inet.port) { + /* the connection we accepted is not from f[0] */ + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); + goto failed; + } PR_Close(listenSock); return PR_SUCCESS; @@ -1532,6 +1569,9 @@ failed: if (f[0]) { PR_Close(f[0]); } + if (f[1]) { + PR_Close(f[1]); + } return PR_FAILURE; #endif } @@ -1539,20 +1579,14 @@ failed: PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *fd) { - if (fd) { - /* - * The fd may be layered. Chase the links to the - * bottom layer to get the osfd. - */ - PRFileDesc *bottom = fd; - while (bottom->lower != NULL) { - bottom = bottom->lower; - } - return bottom->secret->md.osfd; - } else { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return -1; - } + if (fd) { + fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); + } + if (!fd) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + return fd->secret->md.osfd; } PR_IMPLEMENT(void) diff --git a/pr/src/io/prstdio.c b/pr/src/io/prstdio.c index 4ae2f267..de4c39de 100644 --- a/pr/src/io/prstdio.c +++ b/pr/src/io/prstdio.c @@ -56,7 +56,45 @@ PR_IMPLEMENT(PRUint32) PR_vfprintf(PRFileDesc* fd, const char *fmt, va_list ap) PRUint32 rv, len; char* msg = PR_vsmprintf(fmt, ap); len = strlen(msg); +#ifdef XP_OS2 + /* + * OS/2 really needs a \r for every \n. + * In the future we should try to use scatter-gather instead of a + * succession of PR_Write. + */ + if (isatty(PR_FileDesc2NativeHandle(fd))) { + PRUint32 last = 0, idx; + PRInt32 tmp; + rv = 0; + for (idx = 0; idx < len+1; idx++) { + if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) { + tmp = PR_Write(fd, msg + last, idx - last); + if (tmp >= 0) { + rv += tmp; + } + last = idx; + } + /* + * if current character is \n, and + * previous character isn't \r, and + * next character isn't \r + */ + if (('\n' == msg[idx]) && + ((0 == idx) || ('\r' != msg[idx-1])) && + ('\r' != msg[idx+1])) { + /* add extra \r */ + tmp = PR_Write(fd, "\r", 1); + if (tmp >= 0) { + rv += tmp; + } + } + } + } else { + rv = PR_Write(fd, msg, len); + } +#else rv = PR_Write(fd, msg, len); +#endif PR_DELETE(msg); return rv; } diff --git a/pr/src/linking/Makefile.in b/pr/src/linking/Makefile.in index 1c5de3c1..1e66c460 100644 --- a/pr/src/linking/Makefile.in +++ b/pr/src/linking/Makefile.in @@ -58,6 +58,16 @@ TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private +# For Dl_info and dladdr. +ifeq ($(OS_TARGET),Linux) +DEFINES += -D_GNU_SOURCE +endif + +# On Mac OS X use flat #includes. +ifeq ($(OS_TARGET),MacOSX) +INCLUDES += -I$(NEXT_ROOT)/Developer/Headers/FlatCarbon +endif + DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c index b3802055..991ba3d6 100644 --- a/pr/src/linking/prlink.c +++ b/pr/src/linking/prlink.c @@ -17,7 +17,7 @@ * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): Steve Streeter (Hewlett-Packard Company) * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -40,21 +40,26 @@ #include <image.h> #endif -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) #include <CodeFragments.h> #include <TextUtils.h> #include <Types.h> -#include <Strings.h> #include <Aliases.h> #if TARGET_CARBON #include <CFURL.h> #include <CFBundle.h> #include <CFString.h> +#include <CFDictionary.h> +#include <CFData.h> #endif +#if defined(XP_MACOSX) +#define PStrFromCStr(src, dst) c2pstrcpy(dst, src) +#else #include "macdll.h" #include "mdmac.h" +#endif /* XP_MACOSX */ #endif #ifdef XP_UNIX @@ -73,6 +78,13 @@ #ifndef RTLD_LOCAL #define RTLD_LOCAL 0 #endif +#ifdef AIX +#include <sys/ldr.h> +#endif +#ifdef OSF1 +#include <loader.h> +#include <rld_interface.h> +#endif #elif defined(USE_HPSHL) #include <dl.h> #elif defined(USE_MACH_DYLD) @@ -82,12 +94,76 @@ #define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY +#ifdef VMS +/* These are all require for the PR_GetLibraryFilePathname implementation */ +#include <descrip.h> +#include <dvidef.h> +#include <fibdef.h> +#include <iodef.h> +#include <lib$routines.h> +#include <ssdef.h> +#include <starlet.h> +#include <stsdef.h> +#include <unixlib.h> + +#pragma __nostandard +#pragma __member_alignment __save +#pragma __nomember_alignment +#ifdef __INITIAL_POINTER_SIZE +#pragma __required_pointer_size __save +#pragma __required_pointer_size __short +#endif + +typedef struct _imcb { + struct _imcb *imcb$l_flink; + struct _imcb *imcb$l_blink; + unsigned short int imcb$w_size; + unsigned char imcb$b_type; + char imcb$b_resv_1; + unsigned char imcb$b_access_mode; + unsigned char imcb$b_act_code; + unsigned short int imcb$w_chan; + unsigned int imcb$l_flags; + char imcb$t_image_name [40]; + unsigned int imcb$l_symvec_size; + unsigned __int64 imcb$q_ident; + void *imcb$l_starting_address; + void *imcb$l_end_address; +} IMCB; + +#pragma __member_alignment __restore +#ifdef __INITIAL_POINTER_SIZE +#pragma __required_pointer_size __restore +#endif +#pragma __standard + +typedef struct { + short buflen; + short itmcode; + void *buffer; + void *retlen; +} ITMLST; + +typedef struct { + short cond; + short count; + int rest; +} IOSB; + +typedef unsigned long int ulong_t; + +struct _imcb *IAC$GL_IMAGE_LIST = NULL; + +#define MAX_DEVNAM 64 +#define MAX_FILNAM 255 +#endif /* VMS */ + /* * On these platforms, symbols have a leading '_'. */ #if defined(SUNOS4) || defined(DARWIN) || defined(NEXTSTEP) \ - || defined(OPENBSD) || defined(WIN16) \ - || (defined(NETBSD) && !defined(__ELF__)) + || defined(WIN16) || defined(XP_OS2) \ + || ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)) #define NEED_LEADING_UNDERSCORE #endif @@ -111,14 +187,19 @@ struct PRLibrary { #endif #endif -#ifdef XP_MAC - CFragConnectionID dlh; +#if defined(XP_MAC) || defined(XP_MACOSX) + CFragConnectionID connection; #if TARGET_CARBON CFBundleRef bundle; #endif Ptr main; + +#if defined(XP_MACOSX) + CFMutableDictionaryRef wrappers; + const struct mach_header* image; +#endif /* XP_MACOSX */ #endif #ifdef XP_UNIX @@ -185,7 +266,7 @@ static void DLLErrorInternal(PRIntn oserr) void _PR_InitLinker(void) { -#ifndef XP_MAC +#if !defined(XP_MAC) && !defined(XP_BEOS) PRLibrary *lm; #endif #if defined(XP_UNIX) @@ -254,7 +335,7 @@ void _PR_InitLinker(void) #endif /* HAVE_DLL */ #endif /* XP_UNIX */ -#ifndef XP_MAC +#if !defined(XP_MAC) && !defined(XP_BEOS) PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (init)", lm?lm->name:"NULL")); #endif @@ -262,6 +343,10 @@ void _PR_InitLinker(void) } #if defined(WIN16) +/* + * _PR_ShutdownLinker unloads all dlls loaded by the application via + * calls to PR_LoadLibrary + */ void _PR_ShutdownLinker(void) { PR_EnterMonitor(pr_linker_lock); @@ -282,6 +367,32 @@ void _PR_ShutdownLinker(void) PR_DestroyMonitor(pr_linker_lock); pr_linker_lock = NULL; } +#else +/* + * _PR_ShutdownLinker was originally only used on WIN16 (see above), + * but I think it should also be used on other platforms. However, + * I disagree with the original implementation's unloading the dlls + * for the application. Any dlls that still remain on the pr_loadmap + * list when NSPR shuts down are application programming errors. The + * only exception is pr_exe_loadmap, which was added to the list by + * NSPR and hence should be cleaned up by NSPR. + */ +void _PR_ShutdownLinker(void) +{ + /* FIXME: pr_exe_loadmap should be destroyed. */ + + PR_DestroyMonitor(pr_linker_lock); + pr_linker_lock = NULL; + + if (_pr_currentLibPath) { + free(_pr_currentLibPath); + _pr_currentLibPath = NULL; + } + +#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) + PR_DELETE(errStrBuf); +#endif +} #endif /******************************************************************************/ @@ -292,7 +403,9 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path) if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); - PR_FREEIF(_pr_currentLibPath); + if (_pr_currentLibPath) { + free(_pr_currentLibPath); + } if (path) { _pr_currentLibPath = strdup(path); if (!_pr_currentLibPath) { @@ -310,7 +423,7 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path) ** Return the library path for finding shared libraries. */ PR_IMPLEMENT(char *) -PR_GetLibraryPath() +PR_GetLibraryPath(void) { char *ev; char *copy = NULL; /* a copy of _pr_currentLibPath */ @@ -342,7 +455,7 @@ PR_GetLibraryPath() ev = ""; len = strlen(ev) + 1; /* +1 for the null */ - p = (char*) PR_MALLOC(len); + p = (char*) malloc(len); if (p) { strcpy(p, ev); } @@ -369,7 +482,7 @@ PR_GetLibraryPath() #endif len = strlen(ev) + 1; /* +1 for the null */ - p = (char*) PR_MALLOC(len); + p = (char*) malloc(len); if (p) { strcpy(p, ev); } /* if (p) */ @@ -410,20 +523,40 @@ 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); + if (path) { + fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX); + } else { + fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX); + } } else { - fullname = PR_smprintf("%s\\%s", path, lib); + if (path) { + fullname = PR_smprintf("%s\\%s", path, lib); + } else { + fullname = PR_smprintf("%s", lib); + } } #endif /* XP_PC */ #ifdef XP_MAC - fullname = PR_smprintf("%s%s", path, lib); + if (path) { + fullname = PR_smprintf("%s%s", path, lib); + } else { + fullname = PR_smprintf("%s", lib); + } #endif #if defined(XP_UNIX) || defined(XP_BEOS) if (strstr(lib, PR_DLL_SUFFIX) == NULL) { - fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX); + if (path) { + fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX); + } else { + fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX); + } } else { - fullname = PR_smprintf("%s/%s", path, lib); + if (path) { + fullname = PR_smprintf("%s/%s", path, lib); + } else { + fullname = PR_smprintf("%s", lib); + } } #endif /* XP_UNIX || XP_BEOS */ return fullname; @@ -447,9 +580,11 @@ pr_UnlockedFindLibrary(const char *name) while (lm) { const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR); cp = cp ? cp + 1 : lm->name; -#ifdef XP_PC +#ifdef WIN32 /* Windows DLL names are case insensitive... */ if (strcmpi(np, cp) == 0) +#elif defined(XP_OS2) + if (stricmp(np, cp) == 0) #else if (strcmp(np, cp) == 0) #endif @@ -501,37 +636,277 @@ PR_LoadLibrary(const char *name) return PR_LoadLibraryWithFlags(libSpec, 0); } +#if defined(USE_MACH_DYLD) +static NSModule +pr_LoadMachDyldModule(const char *name) +{ + NSObjectFileImage ofi; + NSModule h = NULL; + if (NSCreateObjectFileImageFromFile(name, &ofi) + == NSObjectFileImageSuccess) { + h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE + | NSLINKMODULE_OPTION_RETURN_ON_ERROR); + /* + * TODO: If NSLinkModule fails, use NSLinkEditError to retrieve + * error information. + */ + if (NSDestroyObjectFileImage(ofi) == FALSE) { + if (h) { + (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE); + h = NULL; + } + } + } + return h; +} +#endif + +#if defined(XP_MAC) || defined(XP_MACOSX) + +#ifdef XP_MACOSX +static void* TV2FP(CFMutableDictionaryRef dict, const char* name, void *tvp) +{ + static uint32 glue[6] = { 0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420 }; + uint32* newGlue = NULL; + + if (tvp != NULL) { + CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); + if (nameRef) { + CFMutableDataRef glueData = (CFMutableDataRef) CFDictionaryGetValue(dict, nameRef); + if (glueData == NULL) { + glueData = CFDataCreateMutable(NULL, sizeof(glue)); + if (glueData != NULL) { + newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); + memcpy(newGlue, glue, sizeof(glue)); + newGlue[0] |= ((UInt32)tvp >> 16); + newGlue[1] |= ((UInt32)tvp & 0xFFFF); + MakeDataExecutable(newGlue, sizeof(glue)); + CFDictionaryAddValue(dict, nameRef, glueData); + CFRelease(glueData); + + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: created wrapper for CFM function %s().", name)); + } + } else { + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: found wrapper for CFM function %s().", name)); + + newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); + } + CFRelease(nameRef); + } + } + + return newGlue; +} +#endif + +/* +** macLibraryLoadProc is a function definition for a Mac shared library +** loading method. The "name" param is the same full or partial pathname +** that was passed to pr_LoadLibraryByPathName. The function must fill +** in the fields of "lm" which apply to its library type. Returns +** PR_SUCCESS if successful. +*/ + +typedef PRStatus (*macLibraryLoadProc)(const char *name, PRLibrary *lm); + +static PRStatus +pr_LoadViaCFM(const char *name, PRLibrary *lm) +{ + OSErr err; + char cName[64]; + Str255 errName; + +#if !defined(XP_MACOSX) + Str255 pName; + /* + * 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); + + /* + * beard: NSGetSharedLibrary was so broken that I just decided to + * use GetSharedLibrary for now. This will need to change for + * plugins, but those should go in the Extensions folder anyhow. + */ + err = GetSharedLibrary(pName, kCompiledCFragArch, kReferenceCFrag, + &lm->connection, &lm->main, errName); + if (err != noErr) + return PR_FAILURE; + } + else +#endif + { + /* + * 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). Make an FSSpec from + * the full path and call GetDiskFragment. + */ + FSSpec fileSpec; + Boolean tempUnusedBool; + +#if defined(XP_MACOSX) + { + /* Use direct conversion of POSIX path to FSRef to FSSpec. */ + FSRef ref; + err = FSPathMakeRef((const UInt8*)name, &ref, NULL); + if (err == noErr) + err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, + &fileSpec, NULL); + } +#else + PStrFromCStr(name, pName); + err = FSMakeFSSpec(0, 0, pName, &fileSpec); +#endif + if (err != noErr) + return PR_FAILURE; + + /* Resolve an alias if this was one */ + err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool, + &tempUnusedBool); + if (err != noErr) + return PR_FAILURE; + + /* Finally, try to load the library */ + err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name, + kLoadCFrag, &lm->connection, &lm->main, errName); + #if TARGET_CARBON + p2cstrcpy(cName, fileSpec.name); +#else + memcpy(cName, fileSpec.name + 1, fileSpec.name[0]); + cName[fileSpec.name[0]] = '\0'; +#endif + +#ifdef XP_MACOSX + if (err == noErr && lm->connection) { + /* + * if we're a mach-o binary, need to wrap all CFM function + * pointers. need a hash-table of already seen function + * pointers, etc. + */ + lm->wrappers = CFDictionaryCreateMutable(NULL, 16, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (lm->wrappers) { + lm->main = TV2FP(lm->wrappers, "main", lm->main); + } else + err = memFullErr; + } +#endif + } + return (err == noErr) ? PR_SUCCESS : PR_FAILURE; +} /* -** Returns a CFBundleRef if the FSSpec refers to a Mac OS X bundle directory. -** The caller is responsible for calling CFRelease() to deallocate. +** Creates a CFBundleRef if the pathname refers to a Mac OS X bundle +** directory. The caller is responsible for calling CFRelease() to +** deallocate. */ -static CFBundleRef getLibraryBundle(const FSSpec* spec) + +#if TARGET_CARBON +static PRStatus +pr_LoadCFBundle(const char *name, PRLibrary *lm) { + CFURLRef bundleURL; CFBundleRef bundle = NULL; - FSRef ref; - OSErr err = FSpMakeFSRef(spec, &ref); - char path[512]; - if (err == noErr && ((UInt32)(FSRefMakePath) != kUnresolvedCFragSymbolAddress)) { - err = FSRefMakePath(&ref, (UInt8*)path, sizeof(path) - 1); - if (err == noErr) { - CFStringRef pathRef = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8); - if (pathRef) { - CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef, kCFURLPOSIXPathStyle, true); - if (bundleURL != NULL) { - bundle = CFBundleCreate(NULL, bundleURL); - CFRelease(bundleURL); - } - CFRelease(pathRef); - } + +#ifdef XP_MACOSX + char pathBuf[PATH_MAX]; + const char *resolvedPath; + CFStringRef pathRef; + + /* Takes care of relative paths and symlinks */ + resolvedPath = realpath(name, pathBuf); + if (!resolvedPath) + return PR_FAILURE; + + pathRef = CFStringCreateWithCString(NULL, pathBuf, kCFStringEncodingUTF8); + if (pathRef) { + bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef, + kCFURLPOSIXPathStyle, true); + if (bundleURL) { + bundle = CFBundleCreate(NULL, bundleURL); + CFRelease(bundleURL); } + CFRelease(pathRef); + } +#else + OSErr err; + Str255 pName; + FSSpec fsSpec; + FSRef fsRef; + + if ((UInt32)(CFURLCreateFromFSRef) == kUnresolvedCFragSymbolAddress) + return PR_FAILURE; + PStrFromCStr(name, pName); + err = FSMakeFSSpec(0, 0, pName, &fsSpec); + if (err != noErr) + return PR_FAILURE; + err = FSpMakeFSRef(&fsSpec, &fsRef); + if (err != noErr) + return PR_FAILURE; + bundleURL = CFURLCreateFromFSRef(NULL, &fsRef); + if (bundleURL) { + bundle = CFBundleCreate(NULL, bundleURL); + CFRelease(bundleURL); } - return bundle; +#endif + + lm->bundle = bundle; + return (bundle != NULL) ? PR_SUCCESS : PR_FAILURE; } +#endif +#ifdef XP_MACOSX +static PRStatus +pr_LoadViaDyld(const char *name, PRLibrary *lm) +{ + lm->dlh = pr_LoadMachDyldModule(name); + if (lm->dlh == NULL) { + lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR + | NSADDIMAGE_OPTION_WITH_SEARCHING); + /* + * TODO: If NSAddImage fails, use NSLinkEditError to retrieve + * error information. + */ + } + return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE; +} #endif +#endif /* defined(XP_MAC) || defined(XP_MACOSX) */ + /* ** Dynamically load a library. Only load libraries once, so scan the load ** map first. @@ -564,8 +939,7 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) UCHAR pszError[_MAX_PATH]; ULONG ulRc = NO_ERROR; - retry: - ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h); + ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h); if (ulRc != NO_ERROR) { oserr = ulRc; PR_DELETE(lm); @@ -594,163 +968,57 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) lm->next = pr_loadmap; pr_loadmap = lm; - /* - ** Try to load a table of "static functions" provided by the DLL - */ + /* + ** Try to load a table of "static functions" provided by the DLL + */ - pfn = (NODL_PROC *)GetProcAddress(h, "NODL_TABLE"); - if (pfn != NULL) { - lm->staticTable = (*pfn)(); - } + pfn = (NODL_PROC *)GetProcAddress(h, "NODL_TABLE"); + if (pfn != NULL) { + lm->staticTable = (*pfn)(); + } } #endif /* WIN32 || WIN16 */ -#if defined(XP_MAC) && TARGET_RT_MAC_CFM +#if defined(XP_MAC) || defined(XP_MACOSX) { - OSErr err; - 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); - - /* - * beard: NSGetSharedLibrary was so broken that I just decided to - * use GetSharedLibrary for now. This will need to change for - * plugins, but those should go in the Extensions folder anyhow. - */ -#if 0 - err = NSGetSharedLibrary(pName, &connectionID, &lm->main); + int i; + PRStatus status; + + static const macLibraryLoadProc loadProcs[] = { +#if defined(XP_MACOSX) + pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM +#elif TARGET_CARBON + pr_LoadViaCFM, pr_LoadCFBundle #else - err = GetSharedLibrary(pName, kCompiledCFragArch, kReferenceCFrag, - &connectionID, &lm->main, errName); + pr_LoadViaCFM #endif - if (err != noErr) - { - oserr = err; - PR_DELETE(lm); - 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. - */ - FSSpec fileSpec; - Boolean tempUnusedBool; - - PStrFromCStr(name, pName); - err = FSMakeFSSpec(0, 0, pName, &fileSpec); - if (err != noErr) { - oserr = _MD_ERRNO(); - PR_DELETE(lm); - goto unlock; - } + }; - /* Resolve an alias if this was one */ - err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool, &tempUnusedBool); - if (err != noErr) - { - oserr = err; - PR_DELETE(lm); - goto unlock; - } - - /* Finally, try to load the library */ - err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name, - kLoadCFrag, &connectionID, &lm->main, errName); - - memcpy(cName, fileSpec.name + 1, fileSpec.name[0]); - cName[fileSpec.name[0]] = '\0'; - libName = cName; - - if (err != noErr) - { -#if TARGET_CARBON - /* If not a CFM library, perhaps it's a CFBundle. */ - lm->bundle = getLibraryBundle(&fileSpec); -#ifdef DEBUG - fprintf(stderr, "*** loading bundle for library '%s' [%s]. ***\n", - libName, lm->bundle ? "SUCCEEDED" : "FAILED"); -#endif - if (lm->bundle == NULL) { - oserr = err; - PR_DELETE(lm); - goto unlock; - } -#else - oserr = err; - PR_DELETE(lm); - goto unlock; -#endif - } + for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) { + if ((status = loadProcs[i](name, lm)) == PR_SUCCESS) + break; } - - lm->name = strdup(libName); - lm->dlh = connectionID; + if (status != PR_SUCCESS) { + oserr = cfragNoLibraryErr; + PR_DELETE(lm); + goto unlock; + } + lm->name = strdup(name); lm->next = pr_loadmap; pr_loadmap = lm; } -#elif defined(XP_MAC) && !TARGET_RT_MAC_CFM - { - - } #endif -#ifdef XP_UNIX +#if defined(XP_UNIX) && !defined(XP_MACOSX) #ifdef HAVE_DLL { #if defined(USE_DLFCN) #ifdef NTO /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */ int dl_flags = RTLD_GROUP; +#elif defined(AIX) + /* AIX needs RTLD_MEMBER to load an archive member. (bug 228899) */ + int dl_flags = RTLD_MEMBER; #else int dl_flags = 0; #endif @@ -790,12 +1058,7 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */ h = shl_load(name, shl_flags, 0L); #elif defined(USE_MACH_DYLD) - NSObjectFileImage ofi; - NSModule h = NULL; - if (NSCreateObjectFileImageFromFile(name, &ofi) - == NSObjectFileImageSuccess) { - h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE); - } + NSModule h = pr_LoadMachDyldModule(name); #else #error Configuration error #endif @@ -866,14 +1129,14 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) cookie = 0; while (get_next_image_info(0, &cookie, &info) == B_OK) { - char *endOfSystemName = strrchr(info.name, '/'); - char *endOfPassedName = strrchr(name, '/'); + const char *endOfSystemName = strrchr(info.name, '/'); + const char *endOfPassedName = strrchr(name, '/'); if( 0 == endOfSystemName ) - endOfSystemName=info.name; + endOfSystemName = info.name; else endOfSystemName++; if( 0 == endOfPassedName ) - endOfPassedName=name; + endOfPassedName = name; else endOfPassedName++; if (strcmp(endOfSystemName, endOfPassedName) == 0) { @@ -971,7 +1234,7 @@ pr_Mac_LoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName) goto unlock; newLib->name = strdup(fragmentName); - newLib->dlh = connectionID; + newLib->connection = connectionID; newLib->next = pr_loadmap; pr_loadmap = newLib; @@ -1037,7 +1300,7 @@ pr_Mac_LoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragIndex) } newLib->name = fragmentName; /* was malloced in NSLoadIndexedFragment */ - newLib->dlh = connectionID; + newLib->connection = connectionID; newLib->next = pr_loadmap; pr_loadmap = newLib; @@ -1094,7 +1357,7 @@ PR_UnloadLibrary(PRLibrary *lib) #elif defined(USE_HPSHL) result = shl_unload(lib->dlh); #elif defined(USE_MACH_DYLD) - result = NSUnLinkModule(lib->dlh, FALSE); + result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1; #else #error Configuration error #endif @@ -1107,14 +1370,19 @@ PR_UnloadLibrary(PRLibrary *lib) } #endif /* XP_PC */ -#if defined(XP_MAC) && TARGET_RT_MAC_CFM +#if defined(XP_MAC) || defined(XP_MACOSX) /* Close the connection */ + if (lib->connection) + CloseConnection(&(lib->connection)); #if TARGET_CARBON if (lib->bundle) CFRelease(lib->bundle); - else #endif - CloseConnection(&(lib->dlh)); +#if defined(XP_MACOSX) + if (lib->wrappers) + CFRelease(lib->wrappers); + /* No way to unload an image (lib->image) */ +#endif #endif /* unlink from library search list */ @@ -1148,9 +1416,10 @@ PR_UnloadLibrary(PRLibrary *lib) freeLib: PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name)); - PR_DELETE(lib->name); + free(lib->name); + lib->name = NULL; PR_DELETE(lib); - if (result == -1) { + if (result != 0) { PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); status = PR_FAILURE; @@ -1165,14 +1434,17 @@ static void* pr_FindSymbolInLib(PRLibrary *lm, const char *name) { void *f = NULL; +#ifdef XP_OS2 + int rc; +#endif 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!! @@ -1184,36 +1456,75 @@ pr_FindSymbolInLib(PRLibrary *lm, const char *name) } #ifdef XP_OS2 - DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); + rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); +#if defined(NEED_LEADING_UNDERSCORE) + /* + * Older plugins (not built using GCC) will have symbols that are not + * underscore prefixed. We check for that here. + */ + if (rc != NO_ERROR) { + name++; + DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); + } +#endif #endif /* XP_OS2 */ #if defined(WIN32) || defined(WIN16) f = GetProcAddress(lm->dlh, name); #endif /* WIN32 || WIN16 */ -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) +#if defined(NEED_LEADING_UNDERSCORE) +#define SYM_OFFSET 1 +#else +#define SYM_OFFSET 0 +#endif #if TARGET_CARBON - if (lm->bundle) - { - CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); + if (lm->bundle) { + CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII); if (nameRef) { f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef); CFRelease(nameRef); } } - else #endif - { + if (lm->connection) { Ptr symAddr; CFragSymbolClass symClass; Str255 pName; - - PStrFromCStr(name, pName); - f = (NSFindSymbol(lm->dlh, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL; + PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_OFFSET)); + + PStrFromCStr(name + SYM_OFFSET, pName); + +#if defined(XP_MACOSX) + f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL; +#else + f = (NSFindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL; +#endif + +#if defined(XP_MACOSX) + /* callers expect mach-o function pointers, so must wrap tvectors with glue. */ + if (f && symClass == kTVectorCFragSymbol) { + f = TV2FP(lm->wrappers, name + SYM_OFFSET, f); + } +#endif - if (f == NULL && strcmp(name, "main") == 0) f = lm->main; + if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main; } +#if defined(XP_MACOSX) + if (lm->image) { + NSSymbol symbol; + symbol = NSLookupSymbolInImage(lm->image, name, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + if (symbol != NULL) + f = NSAddressOfSymbol(symbol); + else + f = NULL; + } +#endif +#undef SYM_OFFSET #endif /* XP_MAC */ #ifdef XP_BEOS @@ -1231,7 +1542,7 @@ pr_FindSymbolInLib(PRLibrary *lm, const char *name) f = NULL; } #elif defined(USE_MACH_DYLD) - { + if (lm->dlh) { NSSymbol symbol; symbol = NSLookupSymbolInModule(lm->dlh, name); if (symbol != NULL) @@ -1385,7 +1696,11 @@ PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt) lm->name = strdup(name); lm->refCount = 1; +#if defined(XP_MAC) + lm->connection = pr_exe_loadmap ? pr_exe_loadmap->connection : 0; +#else lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0; +#endif lm->staticTable = slt; lm->next = pr_loadmap; pr_loadmap = lm; @@ -1397,3 +1712,342 @@ PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt) PR_ExitMonitor(pr_linker_lock); return result; } + +PR_IMPLEMENT(char *) +PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr) +{ +#if defined(SOLARIS) || defined(LINUX) + Dl_info dli; + char *result; + + if (dladdr((void *)addr, &dli) == 0) { + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); + DLLErrorInternal(_MD_ERRNO()); + return NULL; + } + result = PR_Malloc(strlen(dli.dli_fname)+1); + if (result != NULL) { + strcpy(result, dli.dli_fname); + } + return result; +#elif defined(USE_MACH_DYLD) + char *result; + char *image_name; + int i, count = _dyld_image_count(); + + for (i = 0; i < count; i++) { + image_name = _dyld_get_image_name(i); + if (strstr(image_name, name) != NULL) { + result = PR_Malloc(strlen(image_name)+1); + if (result != NULL) { + strcpy(result, image_name); + } + return result; + } + } + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); + return NULL; +#elif defined(AIX) + char *result; +#define LD_INFO_INCREMENT 64 + struct ld_info *info; + unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info); + struct ld_info *infop; + + for (;;) { + info = PR_Malloc(info_length); + if (info == NULL) { + return NULL; + } + /* If buffer is too small, loadquery fails with ENOMEM. */ + if (loadquery(L_GETINFO, info, info_length) != -1) { + break; + } + PR_Free(info); + if (errno != ENOMEM) { + /* should not happen */ + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); + return NULL; + } + /* retry with a larger buffer */ + info_length += LD_INFO_INCREMENT * sizeof(struct ld_info); + } + + for (infop = info; + ; + infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) { + if (strstr(infop->ldinfo_filename, name) != NULL) { + result = PR_Malloc(strlen(infop->ldinfo_filename)+1); + if (result != NULL) { + strcpy(result, infop->ldinfo_filename); + } + break; + } + if (!infop->ldinfo_next) { + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); + result = NULL; + break; + } + } + PR_Free(info); + return result; +#elif defined(OSF1) + /* Contributed by Steve Streeter of HP */ + ldr_process_t process, ldr_my_process(); + ldr_module_t mod_id; + ldr_module_info_t info; + ldr_region_t regno; + ldr_region_info_t reginfo; + size_t retsize; + int rv; + char *result; + + /* Get process for which dynamic modules will be listed */ + + process = ldr_my_process(); + + /* Attach to process */ + + rv = ldr_xattach(process); + if (rv) { + /* should not happen */ + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); + return NULL; + } + + /* Print information for list of modules */ + + mod_id = LDR_NULL_MODULE; + + for (;;) { + + /* Get information for the next module in the module list. */ + + ldr_next_module(process, &mod_id); + if (ldr_inq_module(process, mod_id, &info, sizeof(info), + &retsize) != 0) { + /* No more modules */ + break; + } + if (retsize < sizeof(info)) { + continue; + } + + /* + * Get information for each region in the module and check if any + * contain the address of this function. + */ + + for (regno = 0; ; regno++) { + if (ldr_inq_region(process, mod_id, regno, ®info, + sizeof(reginfo), &retsize) != 0) { + /* No more regions */ + break; + } + if (((unsigned long)reginfo.lri_mapaddr <= + (unsigned long)addr) && + (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) > + (unsigned long)addr)) { + /* Found it. */ + result = PR_Malloc(strlen(info.lmi_name)+1); + if (result != NULL) { + strcpy(result, info.lmi_name); + } + return result; + } + } + } + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); + return NULL; +#elif defined(VMS) + /* Contributed by Colin Blake of HP */ + struct _imcb *icb; + ulong_t status; + char device_name[MAX_DEVNAM]; + int device_name_len; + $DESCRIPTOR (device_name_desc, device_name); + struct fibdef fib; + struct dsc$descriptor_s fib_desc = + { sizeof(struct fibdef), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&fib } ; + IOSB iosb; + ITMLST devlst[2] = { + {MAX_DEVNAM, DVI$_ALLDEVNAM, device_name, &device_name_len}, + {0,0,0,0}}; + short file_name_len; + char file_name[MAX_FILNAM+1]; + char *result = NULL; + struct dsc$descriptor_s file_name_desc = + { MAX_FILNAM, DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *) &file_name[0] } ; + + /* + ** The address for the process image list could change in future versions + ** of the operating system. 7FFD0688 is valid for V7.2 and V7.3 releases, + ** so we use that for the default, but allow an environment variable + ** (logical name) to override. + */ + if (IAC$GL_IMAGE_LIST == NULL) { + char *p = getenv("MOZILLA_IAC_GL_IMAGE_LIST"); + if (p) + IAC$GL_IMAGE_LIST = (struct _imcb *) strtol(p,NULL,0); + else + IAC$GL_IMAGE_LIST = (struct _imcb *) 0x7FFD0688; + } + + for (icb = IAC$GL_IMAGE_LIST->imcb$l_flink; + icb != IAC$GL_IMAGE_LIST; + icb = icb->imcb$l_flink) { + if (((void *)addr >= icb->imcb$l_starting_address) && + ((void *)addr <= icb->imcb$l_end_address)) { + /* + ** This is the correct image. + ** Get the device name. + */ + status = sys$getdviw(0,icb->imcb$w_chan,0,&devlst,0,0,0,0); + if ($VMS_STATUS_SUCCESS(status)) + device_name_desc.dsc$w_length = device_name_len; + + /* + ** Get the FID. + */ + memset(&fib,0,sizeof(struct fibdef)); + status = sys$qiow(0,icb->imcb$w_chan,IO$_ACCESS,&iosb, + 0,0,&fib_desc,0,0,0,0,0); + + /* + ** If we got the FID, now look up its name (if for some reason + ** we didn't get the device name, this call will fail). + */ + if (($VMS_STATUS_SUCCESS(status)) && ($VMS_STATUS_SUCCESS(iosb.cond))) { + status = lib$fid_to_name ( + &device_name_desc, + &fib.fib$w_fid, + &file_name_desc, + &file_name_len, + 0, 0); + + /* + ** If we succeeded then remove the version number and + ** return a copy of the UNIX format version of the file name. + */ + if ($VMS_STATUS_SUCCESS(status)) { + char *p, *result; + file_name[file_name_len] = 0; + p = strrchr(file_name,';'); + if (p) *p = 0; + p = decc$translate_vms(&file_name[0]); + result = PR_Malloc(strlen(p)+1); + if (result != NULL) { + strcpy(result, p); + } + return result; + } + } + } + } + + /* Didn't find it */ + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); + return NULL; + +#elif defined(HPUX) && defined(USE_HPSHL) + int index; + struct shl_descriptor desc; + char *result; + + for (index = 0; shl_get_r(index, &desc) == 0; index++) { + if (strstr(desc.filename, name) != NULL) { + result = PR_Malloc(strlen(desc.filename)+1); + if (result != NULL) { + strcpy(result, desc.filename); + } + return result; + } + } + /* + * Since the index value of a library is decremented if + * a library preceding it in the shared library search + * list was unloaded, it is possible that we missed some + * libraries as we went up the list. So we should go + * down the list to be sure that we not miss anything. + */ + for (index--; index >= 0; index--) { + if ((shl_get_r(index, &desc) == 0) + && (strstr(desc.filename, name) != NULL)) { + result = PR_Malloc(strlen(desc.filename)+1); + if (result != NULL) { + strcpy(result, desc.filename); + } + return result; + } + } + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); + return NULL; +#elif defined(HPUX) && defined(USE_DLFCN) + struct load_module_desc desc; + char *result; + const char *module_name; + + if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) { + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); + DLLErrorInternal(_MD_ERRNO()); + return NULL; + } + module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0); + if (module_name == NULL) { + /* should not happen */ + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); + DLLErrorInternal(_MD_ERRNO()); + return NULL; + } + result = PR_Malloc(strlen(module_name)+1); + if (result != NULL) { + strcpy(result, module_name); + } + return result; +#elif defined(WIN32) + HMODULE handle; + char module_name[MAX_PATH]; + char *result; + + handle = GetModuleHandle(name); + if (handle == NULL) { + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); + DLLErrorInternal(_MD_ERRNO()); + return NULL; + } + if (GetModuleFileName(handle, module_name, sizeof module_name) == 0) { + /* should not happen */ + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); + return NULL; + } + result = PR_Malloc(strlen(module_name)+1); + if (result != NULL) { + strcpy(result, module_name); + } + return result; +#elif defined(XP_OS2) + HMODULE module = NULL; + char module_name[_MAX_PATH]; + char *result; + APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr); + if ((NO_ERROR != ulrc) || (NULL == module) ) { + PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); + DLLErrorInternal(_MD_ERRNO()); + return NULL; + } + ulrc = DosQueryModuleName(module, sizeof module_name, module_name); + if (NO_ERROR != ulrc) { + /* should not happen */ + _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); + return NULL; + } + result = PR_Malloc(strlen(module_name)+1); + if (result != NULL) { + strcpy(result, module_name); + } + return result; +#else + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; +#endif +} diff --git a/pr/src/malloc/prmem.c b/pr/src/malloc/prmem.c index 0a70b439..ef8fdc74 100644 --- a/pr/src/malloc/prmem.c +++ b/pr/src/malloc/prmem.c @@ -97,20 +97,79 @@ _PR_DestroyZones(void) while (mz->head) { MemBlockHdr *hdr = mz->head; mz->head = hdr->s.next; /* unlink it */ - pr_ZoneFree(hdr); + free(hdr); mz->elements--; } } } + use_zone_allocator = PR_FALSE; } +/* +** pr_FindSymbolInProg +** +** Find the specified data symbol in the program and return +** its address. +*/ + +#ifdef USE_DLFCN + +#include <dlfcn.h> + +static void * +pr_FindSymbolInProg(const char *name) +{ + void *h; + void *sym; + + h = dlopen(0, RTLD_LAZY); + if (h == NULL) + return NULL; + sym = dlsym(h, name); + (void)dlclose(h); + return sym; +} + +#elif defined(USE_HPSHL) + +#include <dl.h> + +static void * +pr_FindSymbolInProg(const char *name) +{ + shl_t h = NULL; + void *sym; + + if (shl_findsym(&h, name, TYPE_DATA, &sym) == -1) + return NULL; + return sym; +} + +#elif defined(USE_MACH_DYLD) + +static void * +pr_FindSymbolInProg(const char *name) +{ + /* FIXME: not implemented */ + return NULL; +} + +#else + +#error "The zone allocator is not supported on this platform" + +#endif + void _PR_InitZones(void) { int i, j; char *envp; + PRBool *sym; - if (envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) { + if ((sym = (PRBool *)pr_FindSymbolInProg("nspr_use_zone_allocator")) != NULL) { + use_zone_allocator = *sym; + } else if ((envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) != NULL) { use_zone_allocator = (atoi(envp) == 1); } @@ -174,7 +233,7 @@ pr_ZoneMalloc(PRUint32 size) } if (zone < MEM_ZONES) { pthread_t me = pthread_self(); - unsigned int pool = (ptrdiff_t)me % THREAD_POOLS; + unsigned int pool = (PRUptrdiff)me % THREAD_POOLS; PRUint32 wasLocked; mz = &zones[zone][pool]; wasLocked = mz->locked; @@ -275,6 +334,11 @@ pr_ZoneRealloc(void *oldptr, PRUint32 bytes) PR_ASSERT(mb->s.magic == ZONE_MAGIC); if (mb->s.magic != ZONE_MAGIC) { /* Maybe this just came from ordinary malloc */ +#ifdef DEBUG + fprintf(stderr, + "Warning: reallocing memory block %p from ordinary malloc\n", + oldptr); +#endif /* We don't know how big it is. But we can fix that. */ oldptr = realloc(oldptr, bytes); if (!oldptr) { @@ -329,6 +393,10 @@ pr_ZoneFree(void *ptr) if (mb->s.magic != ZONE_MAGIC) { /* maybe this came from ordinary malloc */ +#ifdef DEBUG + fprintf(stderr, + "Warning: freeing memory block %p from ordinary malloc\n", ptr); +#endif free(ptr); return; } @@ -342,7 +410,7 @@ pr_ZoneFree(void *ptr) if (!mz) { PR_ASSERT(blockSize > 65536); /* This block was not in any zone. Just free it. */ - free(ptr); + free(mb); return; } PR_ASSERT(mz->blockSize == blockSize); diff --git a/pr/src/md/beos/bfile.c b/pr/src/md/beos/bfile.c index e80181cc..95206f30 100644 --- a/pr/src/md/beos/bfile.c +++ b/pr/src/md/beos/bfile.c @@ -118,18 +118,45 @@ _MD_make_nonblock (PRFileDesc *fd) } +PRStatus +_MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable) +{ + int rv; + + rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC); + if (-1 == rv) { + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); + return PR_FAILURE; + } + return PR_SUCCESS; +} + void _MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported) { - /* XXX this function needs to be implemented */ - fd->secret->inheritable = _PR_TRI_UNKNOWN; + if (imported) { + fd->secret->inheritable = _PR_TRI_UNKNOWN; + } else { + int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); + if (flags == -1) { + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); + return; + } + fd->secret->inheritable = (flags & FD_CLOEXEC) ? + _PR_TRI_TRUE : _PR_TRI_FALSE; + } } void _MD_query_fd_inheritable (PRFileDesc *fd) { - /* XXX this function needs to be implemented */ - PR_ASSERT(0); + int flags; + + PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); + flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); + PR_ASSERT(-1 != flags); + fd->secret->inheritable = (flags & FD_CLOEXEC) ? + _PR_TRI_FALSE : _PR_TRI_TRUE; } PRInt32 @@ -223,12 +250,14 @@ _MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount) return( rv ); } +#ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */ PRInt32 -_MD_writev (PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size, +_MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { return PR_NOT_IMPLEMENTED_ERROR; } +#endif PRInt32 _MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence) @@ -524,191 +553,280 @@ int rv, err; } PRInt32 -_MD_pr_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) +_MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { - PRInt32 rc = 0; - fd_set rd, wr; - struct timeval tv, *tvp = NULL; + PRInt32 rv = 0; + PRThread *me = _PR_MD_CURRENT_THREAD(); + /* + * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL(). + */ + fd_set rd, wt, ex; + PRFileDesc *bottom; PRPollDesc *pd, *epd; - int i = 0, j = 0; - int maxfd = -1; - PRInt32 osfd; - PRInt16 in_flags; - PRFileDesc *bottom; + PRInt32 maxfd = -1, ready, err; + PRIntervalTime remaining, elapsed, start; - /*printf("POLL: entering _MD_pr_poll\n");*/ - - /* - * Is it an empty set? If so, just sleep for the timeout and return - */ - if (npds < 1) - { - /*printf("POLL: empty set. exiting _MD_pr_poll\n");*/ - PR_Sleep(timeout); - return rc; - } + struct timeval tv, *tvp = NULL; + + if (_PR_PENDING_INTERRUPT(me)) + { + me->flags &= ~_PR_INTERRUPT; + PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); + return -1; + } + + if (0 == npds) { + PR_Sleep(timeout); + return rv; + } - FD_ZERO(&rd); - FD_ZERO(&wr); + FD_ZERO(&rd); + FD_ZERO(&wt); + FD_ZERO(&ex); - /* - * first, sort out the new connects, the reads, and the writes - */ - epd = pds + npds; - for(pd = pds; pd < epd; pd++) + ready = 0; + for (pd = pds, epd = pd + npds; pd < epd; pd++) { - in_flags = pd->in_flags; - bottom = pd->fd; + PRInt16 in_flags_read = 0, in_flags_write = 0; + PRInt16 out_flags_read = 0, out_flags_write = 0; - if(bottom != 0 && in_flags != 0) + if ((NULL != pd->fd) && (0 != pd->in_flags)) { - while(bottom->lower != 0) + if (pd->in_flags & PR_POLL_READ) { - bottom = bottom->lower; + in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } - osfd = bottom->secret->md.osfd; - - if(in_flags & PR_POLL_WRITE || in_flags & PR_POLL_EXCEPT) + if (pd->in_flags & PR_POLL_WRITE) { - /*printf("POLL: adding to write\n");*/ - FD_SET(osfd, &wr); - if( osfd > maxfd ) maxfd = osfd; + 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; } - if(in_flags & PR_POLL_READ || in_flags & PR_POLL_EXCEPT) + else { - /*printf("POLL: adding to read\n");*/ - FD_SET(osfd, &rd); - if( osfd > maxfd ) maxfd = osfd; + 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 */ + } } } - - - } + else + { + pd->out_flags = 0; + } + } + + if (0 != ready) return ready; /* no need to block */ - if(maxfd >= 0) + remaining = timeout; + start = PR_IntervalNow(); + + retry: + if (timeout != PR_INTERVAL_NO_TIMEOUT) + { + PRInt32 ticksPerSecond = PR_TicksPerSecond(); + tv.tv_sec = remaining / ticksPerSecond; + tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); + tvp = &tv; + } + + ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); + + if (ready == -1 && errno == EINTR) { - PRInt32 n; - do { - PRIntervalTime start = PR_IntervalNow(); - if (timeout != PR_INTERVAL_NO_TIMEOUT) + if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; + else + { + elapsed = (PRIntervalTime) (PR_IntervalNow() - start); + if (elapsed > timeout) ready = 0; /* timed out */ + else { - /*printf("POLL: timeout = %ld\n", (long) PR_IntervalToMicroseconds(timeout));*/ - tv.tv_sec = PR_IntervalToSeconds(timeout); - tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC; - tvp = &tv; + remaining = timeout - elapsed; + goto retry; } + } + } - - n = select(maxfd + 1, &rd, &wr, 0, tvp); - /*printf("POLL: maxfd = %d, select returns %d, errno = %d %s\n", maxfd, n, errno, strerror(errno));*/ - if (n == 0 || (n < 0 && errno == EINTR)) + /* + ** 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)) { - if (timeout != PR_INTERVAL_NO_TIMEOUT) - { - timeout -= PR_IntervalNow() - start; - if(timeout <= 0) + 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)) { - /* timed out */ - n = 0; + 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; } - } - } - - } while(n < 0 && errno == EINTR); - - if(n > 0) - { - epd = pds + npds; - for(pd = pds; pd < epd; pd++) - { - int selected; - in_flags = pd->in_flags; - bottom = pd->fd; - selected = 0; - - if(bottom != 0 && in_flags != 0) + if (FD_ISSET(osfd, &wt)) { - while(bottom->lower != 0) - { - bottom = bottom->lower; - } - osfd = bottom->secret->md.osfd; - if (FD_ISSET(osfd, &rd)) - { - pd->out_flags |= PR_POLL_READ; - selected++; - } - if (FD_ISSET(osfd, &wr)) - { - pd->out_flags |= PR_POLL_WRITE; - selected++; - } - - if(selected > 0) + 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; + +/* Workaround for nonblocking connects under net_server */ +#ifndef BONE_VERSION + if (out_flags) + { + /* check if it is a pending connect */ + int i = 0, j = 0; + PR_Lock( _connectLock ); + for( i = 0; i < connectCount; i++ ) { - rc++; - /* - * check if it is a pending connect - */ - PR_Lock( _connectLock ); - for( i = 0; i < connectCount; i++ ) + if(connectList[i].osfd == osfd) { - if(connectList[i].osfd == osfd) + int connectError; + int connectResult; + + connectResult = connect(connectList[i].osfd, + &connectList[i].addr, + connectList[i].addrlen); + connectError = errno; + + if(connectResult < 0 ) { - int connectError; - int connectResult; - - connectResult = connect(connectList[i].osfd, - &connectList[i].addr, - connectList[i].addrlen); - connectError = errno; - - if(connectResult < 0 ) + if(connectError == EINTR || connectError == EWOULDBLOCK || + connectError == EINPROGRESS || connectError == EALREADY) { - if(connectError == EINTR || connectError == EWOULDBLOCK - || connectError == EINPROGRESS || connectError == EALREADY) - { - break; - } + break; } - - if(i == (connectCount - 1)) + } + + if(i == (connectCount - 1)) + { + connectList[i].osfd = -1; + } else { + for(j = i; j < connectCount; j++ ) { - connectList[i].osfd = -1; - } else { - for(j = i; j < connectCount; j++ ) - { - memcpy( &connectList[j], &connectList[j+1], - sizeof(connectList[j])); - } + memcpy( &connectList[j], &connectList[j+1], + sizeof(connectList[j])); } - connectCount--; - - bottom->secret->md.connectReturnValue = connectResult; - bottom->secret->md.connectReturnError = connectError; - bottom->secret->md.connectValueValid = PR_TRUE; - break; } + connectCount--; + + bottom->secret->md.connectReturnValue = connectResult; + bottom->secret->md.connectReturnError = connectError; + bottom->secret->md.connectValueValid = PR_TRUE; + break; } - - - PR_Unlock( _connectLock ); } - } else { - pd->out_flags = 0; - continue; + PR_Unlock( _connectLock ); } - +#endif } - } else if (n < 0) { - /* hit error that's not EINTR. */ - rc = -1; + pd->out_flags = out_flags; + if (out_flags) ready++; } + PR_ASSERT(ready > 0); } - - /*printf("POLL: exiting _MD_pr_poll with %d\n", rc);*/ - return rc; -} + 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; +} /* _MD_pr_poll */ /* * File locking. diff --git a/pr/src/md/beos/bmisc.c b/pr/src/md/beos/bmisc.c index 634bea11..056d26a9 100644 --- a/pr/src/md/beos/bmisc.c +++ b/pr/src/md/beos/bmisc.c @@ -37,8 +37,12 @@ #include <stdlib.h> PRLock *_connectLock = NULL; + +#ifndef BONE_VERSION +/* Workaround for nonblocking connects under net_server */ PRUint32 connectCount = 0; ConnectListNode connectList[64]; +#endif void _MD_cleanup_before_exit (void) @@ -63,7 +67,10 @@ _MD_final_init (void) { _connectLock = PR_NewLock(); PR_ASSERT(NULL != _connectLock); +#ifndef BONE_VERSION + /* Workaround for nonblocking connects under net_server */ connectCount = 0; +#endif } void diff --git a/pr/src/md/beos/bmmap.c b/pr/src/md/beos/bmmap.c index 2af102cc..27759693 100644 --- a/pr/src/md/beos/bmmap.c +++ b/pr/src/md/beos/bmmap.c @@ -37,6 +37,7 @@ PR_EXTERN(PRStatus) _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size) { + PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } @@ -57,11 +58,13 @@ _PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len) PR_EXTERN(PRStatus) _PR_MD_MEM_UNMAP(void *addr, PRUint32 size) { + PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } PR_EXTERN(PRStatus) _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap) { + PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } diff --git a/pr/src/md/beos/bnet.c b/pr/src/md/beos/bnet.c index 86943b3b..0b4fa149 100644 --- a/pr/src/md/beos/bnet.c +++ b/pr/src/md/beos/bnet.c @@ -1,5 +1,5 @@ /* -*- Mode: C++; c-basic-offset: 4 -*- */ -/* +/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of @@ -49,6 +49,7 @@ */ #define _PRSockLen_t int + /* ** Global lock variable used to bracket calls into rusty libraries that ** aren't thread safe (like libc, libX, etc). @@ -56,135 +57,154 @@ static PRLock *_pr_rename_lock = NULL; static PRMonitor *_pr_Xfe_mon = NULL; -/* +#define READ_FD 1 +#define WRITE_FD 2 + +/* ** This is a support routine to handle "deferred" i/o on sockets. ** It uses "select", so it is subject to all of the BeOS limitations ** (only READ notification, only sockets) */ -#define READ_FD 1 -#define WRITE_FD 2 + +/* + * socket_io_wait -- + * + * wait for socket i/o, periodically checking for interrupt + * + */ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, - PRIntervalTime timeout) + 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); - } - if( _PR_PENDING_INTERRUPT(me)) { - me->flags &= ~_PR_INTERRUPT; - PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); - rv = -1; - break; - } - 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; + PRBool wait_for_remaining; + PRInt32 syserror; + fd_set rd_wr; + + switch (timeout) { + case PR_INTERVAL_NO_WAIT: + PR_SetError(PR_IO_TIMEOUT_ERROR, 0); + break; + case PR_INTERVAL_NO_TIMEOUT: + /* + * 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) { +#ifdef BONE_VERSION + _PR_MD_MAP_SELECT_ERROR(syserror); +#else + if (syserror == EBADF) { + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF); + } else { + PR_SetError(PR_UNKNOWN_ERROR, syserror); + } +#endif + 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. + */ + wait_for_remaining = PR_TRUE; + tv.tv_sec = PR_IntervalToSeconds(remaining); + if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { + wait_for_remaining = PR_FALSE; + tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; + tv.tv_usec = 0; + } else { + tv.tv_usec = PR_IntervalToMicroseconds( + remaining - + PR_SecondsToInterval(tv.tv_sec)); + } + FD_SET(osfd, &rd_wr); + if (fd_type == READ_FD) + rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); + else + rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); + /* + * we don't consider EINTR a real error + */ + if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { +#ifdef BONE_VERSION + _PR_MD_MAP_SELECT_ERROR(syserror); +#else + if (syserror == EBADF) { + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF); + } else { + PR_SetError(PR_UNKNOWN_ERROR, syserror); + } +#endif + 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) { + if (wait_for_remaining) { + now += remaining; + } else { + now += PR_SecondsToInterval(tv.tv_sec) + + PR_MicrosecondsToInterval(tv.tv_usec); + } + } else { + now = PR_IntervalNow(); + } + elapsed = (PRIntervalTime) (now - epoch); + if (elapsed >= timeout) { + PR_SetError(PR_IO_TIMEOUT_ERROR, 0); + rv = -1; + break; + } else { + remaining = timeout - elapsed; + } + } + } while (rv == 0 || (rv == -1 && syserror == EINTR)); + break; + } + return(rv); } - - PRInt32 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout) @@ -193,33 +213,44 @@ _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags, PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); +#ifndef BONE_VERSION if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) { - _PR_MD_MAP_RECV_ERROR(EPIPE); - return -1; + _PR_MD_MAP_RECV_ERROR(EPIPE); + return -1; } +#endif + +#ifdef BONE_VERSION + /* + ** Gah, stupid hack. If reading a zero amount, instantly return success. + ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of + ** mozilla use to check for socket availability. + */ + + if( 0 == amount ) return(0); +#endif while ((rv = recv(osfd, buf, amount, flags)) == -1) { - err = _MD_ERRNO(); + err = _MD_ERRNO(); - if ((err == EAGAIN) || (err == EWOULDBLOCK)) { - if (fd->secret->nonblocking) { - break; - } - /* If socket was supposed to be blocking, - wait a while for the condition to be - satisfied. */ - if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) - goto done; - } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ - continue; + if ((err == EAGAIN) || (err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; + } + /* If socket was supposed to be blocking, + wait a while for the condition to be + satisfied. */ + if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) + goto done; + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ + continue; - } else { - break; - } + } else + break; } if (rv < 0) { - _PR_MD_MAP_RECV_ERROR(err); + _PR_MD_MAP_RECV_ERROR(err); } done: @@ -235,31 +266,38 @@ _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, 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; - } + ((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 ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; - } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { - continue; - - } else { - break; - } + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { + continue; + } else { + break; + } } if (rv < 0) { - _PR_MD_MAP_RECVFROM_ERROR(err); + _PR_MD_MAP_RECVFROM_ERROR(err); } done: +#ifdef _PR_HAVE_SOCKADDR_LEN + if (rv != -1) { + /* ignore the sa_len field of struct sockaddr */ + if (addr) { + addr->raw.family = ((struct sockaddr *) addr)->sa_family; + } + } +#endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); } @@ -271,46 +309,71 @@ _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags, PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); +#ifndef BONE_VERSION if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE) { - _PR_MD_MAP_SEND_ERROR(EPIPE); - return -1; + _PR_MD_MAP_SEND_ERROR(EPIPE); + return -1; } +#endif while ((rv = send(osfd, buf, amount, flags)) == -1) { - err = _MD_ERRNO(); + err = _MD_ERRNO(); - if ((err == EAGAIN) || (err == EWOULDBLOCK)) { - if (fd->secret->nonblocking) { - break; - } + if ((err == EAGAIN) || (err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; + } - if( _PR_PENDING_INTERRUPT(me)) { +#ifndef BONE_VERSION + if( _PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } - /* in UNIX implementations, you could do a socket_io_wait here. - * but since BeOS doesn't yet support WRITE notification in select, - * you're spanked. - */ - snooze( 10000L ); - continue; - - } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { - continue; + /* in UNIX implementations, you could do a socket_io_wait here. + * but since BeOS doesn't yet support WRITE notification in select, + * you're spanked. + */ + snooze( 10000L ); + continue; +#else /* BONE_VERSION */ + if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) + goto done; +#endif + + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { + continue; - } else { - break; - } + } else { + break; + } } +#ifdef BONE_VERSION + /* + * 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 (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { + rv = -1; + goto done; + } + } +#endif /* BONE_VERSION */ + if (rv < 0) { - _PR_MD_MAP_SEND_ERROR(err); + _PR_MD_MAP_SEND_ERROR(err); } +#ifdef BONE_VERSION +done: +#endif return(rv); } @@ -321,32 +384,111 @@ _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); +#ifdef _PR_HAVE_SOCKADDR_LEN + PRNetAddr addrCopy; + addrCopy = *addr; + ((struct sockaddr *) &addrCopy)->sa_len = addrlen; + ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; + + while ((rv = sendto(osfd, buf, amount, flags, + (struct sockaddr *) &addrCopy, addrlen)) == -1) { +#else while ((rv = sendto(osfd, buf, amount, flags, - (struct sockaddr *) addr, addrlen)) == -1) { - err = _MD_ERRNO(); + (struct sockaddr *) addr, addrlen)) == -1) { +#endif + err = _MD_ERRNO(); - if ((err == EAGAIN) || (err == EWOULDBLOCK)) { - if (fd->secret->nonblocking) { - break; - } + if ((err == EAGAIN) || (err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; + } - printf( "This should be a blocking sendto call!!!\n" ); - } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { - continue; +#ifdef BONE_VERSION + if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) + goto done; +#endif + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { + continue; - } else { - break; - } + } else { + break; + } } if (rv < 0) { - _PR_MD_MAP_SENDTO_ERROR(err); + _PR_MD_MAP_SENDTO_ERROR(err); } +#ifdef BONE_VERSION +done: +#endif return(rv); } +#ifdef BONE_VERSION + +PRInt32 _MD_writev( + PRFileDesc *fd, const 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; + } + } + + 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 ((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 (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { + rv = -1; + goto done; + } + } + + + if (rv < 0) { + _PR_MD_MAP_WRITEV_ERROR(err); + } +done: + return(rv); +} + +#endif /* BONE_VERSION */ + PRInt32 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) @@ -356,42 +498,39 @@ _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, 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 it's SUPPOSED to be a blocking thread, wait - * a while to see if the triggering condition gets - * satisfied. - */ - /* Assume that we're always using a native thread */ - if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) - goto done; - } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { - continue; - } else { - break; - } - } - - if (addr) addr->raw.family = AF_INET; + (_PRSockLen_t *)addrlen)) == -1) { + err = _MD_ERRNO(); + if ((err == EAGAIN) || (err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; + } + /* If it's SUPPOSED to be a blocking thread, wait + * a while to see if the triggering condition gets + * satisfied. + */ + /* Assume that we're always using a native thread */ + 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); + _PR_MD_MAP_ACCEPT_ERROR(err); + } else if (addr != NULL) { + /* bug 134099 */ + err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); } done: #ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { - /* 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 - } + /* Mask off the first byte of struct sockaddr (the length field) */ + if (addr) { + addr->raw.family = ((struct sockaddr *) addr)->sa_family; + } } #endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); @@ -401,62 +540,118 @@ PRInt32 _MD_connect (PRFileDesc *fd, 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; +#ifndef BONE_VERSION fd->secret->md.connectValueValid = PR_FALSE; +#endif +#ifdef _PR_HAVE_SOCKADDR_LEN + PRNetAddr addrCopy; + + addrCopy = *addr; + ((struct sockaddr *) &addrCopy)->sa_len = addrlen; + ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; +#endif + + /* (Copied from unix.c) + * We initiate the connection setup by making a nonblocking connect() + * call. If the connect() call fails, there are two cases we handle + * specially: + * 1. The connect() call was interrupted by a signal. In this case + * we simply retry connect(). + * 2. The NSPR socket is nonblocking and connect() fails with + * EINPROGRESS. We first wait until the socket becomes writable. + * Then we try to find out whether the connection setup succeeded + * or failed. + */ retry: +#ifdef _PR_HAVE_SOCKADDR_LEN + if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) { +#else if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) { +#endif err = _MD_ERRNO(); - fd->secret->md.connectReturnValue = rv; - fd->secret->md.connectReturnError = err; - fd->secret->md.connectValueValid = PR_TRUE; - - if( err == EINTR ) { +#ifndef BONE_VERSION + fd->secret->md.connectReturnValue = rv; + fd->secret->md.connectReturnError = err; + fd->secret->md.connectValueValid = PR_TRUE; +#endif + if( err == EINTR ) { - if( _PR_PENDING_INTERRUPT(me)) { + if( _PR_PENDING_INTERRUPT(me)) { - me->flags &= ~_PR_INTERRUPT; + me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } - snooze( 100000L ); +#ifndef BONE_VERSION + snooze( 100000L ); +#endif goto retry; } +#ifndef BONE_VERSION if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) { - /* - ** There's no timeout on this connect, but that's not - ** a big deal, since the connect times out anyways - ** after 30 seconds. Just sleep for 1/10th of a second - ** and retry until we go through or die. - */ + /* + ** There's no timeout on this connect, but that's not + ** a big deal, since the connect times out anyways + ** after 30 seconds. Just sleep for 1/10th of a second + ** and retry until we go through or die. + */ - if( _PR_PENDING_INTERRUPT(me)) { + if( _PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; - } + } - goto retry; - } + goto retry; + } - if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) { - PR_Lock(_connectLock); - connectList[connectCount].osfd = osfd; - memcpy(&connectList[connectCount].addr, addr, addrlen); - connectList[connectCount].addrlen = addrlen; - connectList[connectCount].timeout = timeout; - connectCount++; - PR_Unlock(_connectLock); - _PR_MD_MAP_CONNECT_ERROR(err); - return rv; - } + if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) { + PR_Lock(_connectLock); + if (connectCount < sizeof(connectList)/sizeof(connectList[0])) { + connectList[connectCount].osfd = osfd; + memcpy(&connectList[connectCount].addr, addr, addrlen); + connectList[connectCount].addrlen = addrlen; + connectList[connectCount].timeout = timeout; + connectCount++; + PR_Unlock(_connectLock); + _PR_MD_MAP_CONNECT_ERROR(err); + } else { + PR_Unlock(_connectLock); + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); + } + return rv; + } +#else /* BONE_VERSION */ + if(!fd->secret->nonblocking && (err == EINTR)) { + + rv = socket_io_wait(osfd, WRITE_FD, timeout); + if (rv == -1) { + return -1; + } + + PR_ASSERT(rv == 1); + if (_PR_PENDING_INTERRUPT(me)) { + me->flags &= ~_PR_INTERRUPT; + PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); + return -1; + } + err = _MD_beos_get_nonblocking_connect_error(osfd); + if (err != 0) { + _PR_MD_MAP_CONNECT_ERROR(err); + return -1; + } + return 0; + } +#endif - _PR_MD_MAP_CONNECT_ERROR(err); + _PR_MD_MAP_CONNECT_ERROR(err); } return rv; @@ -466,9 +661,16 @@ PRInt32 _MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv, err; +#ifdef _PR_HAVE_SOCKADDR_LEN + PRNetAddr addrCopy; + addrCopy = *addr; + ((struct sockaddr *) &addrCopy)->sa_len = addrlen; + ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; + rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen); +#else rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); - +#endif if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_BIND_ERROR(err); @@ -482,12 +684,14 @@ _MD_listen (PRFileDesc *fd, PRIntn backlog) { PRInt32 rv, err; +#ifndef BONE_VERSION /* Bug workaround! Setting listen to 0 on Be accepts no connections. ** On most UN*Xes this sets the default. */ if( backlog == 0 ) backlog = 5; - +#endif + rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) { err = _MD_ERRNO(); @@ -502,15 +706,24 @@ _MD_shutdown (PRFileDesc *fd, PRIntn how) { PRInt32 rv, err; +#ifndef BONE_VERSION if (how == PR_SHUTDOWN_SEND) - fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE; + fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE; else if (how == PR_SHUTDOWN_RCV) - fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ; + fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ; else if (how == PR_SHUTDOWN_BOTH) { - fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ); + fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ); } return 0; +#else /* BONE_VERSION */ + rv = shutdown(fd->secret->md.osfd, how); + if (rv < 0) { + err = _MD_ERRNO(); + _PR_MD_MAP_SHUTDOWN_ERROR(err); + } + return(rv); +#endif } PRInt32 @@ -522,7 +735,11 @@ _MD_socketpair (int af, int type, int flags, PRInt32 *osfd) PRInt32 _MD_close_socket (PRInt32 osfd) { +#ifdef BONE_VERSION + close( osfd ); +#else closesocket( osfd ); +#endif } PRStatus @@ -532,7 +749,14 @@ _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) rv = getsockname(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); - +#ifdef _PR_HAVE_SOCKADDR_LEN + if (rv == 0) { + /* ignore the sa_len field of struct sockaddr */ + if (addr) { + addr->raw.family = ((struct sockaddr *) addr)->sa_family; + } + } +#endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKNAME_ERROR(err); @@ -549,6 +773,15 @@ _MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) rv = getpeername(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); +#ifdef _PR_HAVE_SOCKADDR_LEN + if (rv == 0) { + /* ignore the sa_len field of struct sockaddr */ + if (addr) { + addr->raw.family = ((struct sockaddr *) addr)->sa_family; + } + } +#endif /* _PR_HAVE_SOCKADDR_LEN */ + if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETPEERNAME_ERROR(err); @@ -560,9 +793,6 @@ PRStatus _MD_getsockopt (PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { - return PR_NOT_IMPLEMENTED_ERROR; - -#if 0 PRInt32 rv, err; rv = getsockopt(fd->secret->md.osfd, level, optname, @@ -573,7 +803,6 @@ _MD_getsockopt (PRFileDesc *fd, PRInt32 level, } return rv==0?PR_SUCCESS:PR_FAILURE; -#endif } PRStatus @@ -597,6 +826,7 @@ _MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, return PR_NOT_IMPLEMENTED_ERROR; } +#ifndef BONE_VERSION PRInt32 _MD_socket (int af, int type, int flags) { @@ -606,17 +836,43 @@ _MD_socket (int af, int type, int flags) if( -1 == osfd ) { - err = _MD_ERRNO(); - _PR_MD_MAP_SOCKET_ERROR( err ); + err = _MD_ERRNO(); + _PR_MD_MAP_SOCKET_ERROR( err ); } return( osfd ); } +#else +PRInt32 +_MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto) +{ + PRInt32 osfd, err; + + osfd = socket(domain, type, proto); + + if (osfd == -1) { + err = _MD_ERRNO(); + _PR_MD_MAP_SOCKET_ERROR(err); + } + + return(osfd); +} +#endif PRInt32 _MD_socketavailable (PRFileDesc *fd) { +#ifdef BONE_VERSION + PRInt32 result; + + if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) { + _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO()); + return -1; + } + return result; +#else return PR_NOT_IMPLEMENTED_ERROR; +#endif } PRInt32 @@ -628,32 +884,25 @@ _MD_get_socket_error (void) PRStatus _MD_gethostname (char *name, PRUint32 namelen) { -PRInt32 rv, err; + PRInt32 rv, err; rv = gethostname(name, namelen); if (rv == 0) { - err = _MD_ERRNO(); - _PR_MD_MAP_GETHOSTNAME_ERROR(err); - return PR_FAILURE; + err = _MD_ERRNO(); + _PR_MD_MAP_GETHOSTNAME_ERROR(err); + return PR_FAILURE; } return PR_SUCCESS; } +#ifndef BONE_VERSION PRInt32 _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd) { int rv; int flags = 0; - if( fd->secret->md.connectValueValid == PR_TRUE ) - - if( fd->secret->md.connectReturnValue == -1 ) - - return fd->secret->md.connectReturnError; - else - return 0; /* No error */ - rv = recv(fd->secret->md.osfd, NULL, 0, flags); PR_ASSERT(-1 == rv || 0 == rv); if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) { @@ -661,3 +910,17 @@ _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd) } return 0; /* no error */ } +#else +PRInt32 +_MD_beos_get_nonblocking_connect_error(int osfd) +{ + return PR_NOT_IMPLEMENTED_ERROR; + // int err; + // _PRSockLen_t optlen = sizeof(err); + // if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) { + // return errno; + // } else { + // return err; + // } +} +#endif /* BONE_VERSION */ diff --git a/pr/src/md/beos/bproc.c b/pr/src/md/beos/bproc.c index 5d9ac0a5..54ccaa0f 100644 --- a/pr/src/md/beos/bproc.c +++ b/pr/src/md/beos/bproc.c @@ -1,4 +1,4 @@ -/* -*- Mode: C++; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file @@ -33,28 +33,202 @@ */ #include "primpl.h" +#include <stdio.h> +#include <signal.h> + +#define _PR_SIGNALED_EXITSTATUS 256 PRProcess* _MD_create_process (const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { - return NULL; + PRProcess *process; + int nEnv, idx; + char *const *childEnvp; + char **newEnvp = NULL; + int flags; + + process = PR_NEW(PRProcess); + if (!process) { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + + childEnvp = envp; + if (attr && attr->fdInheritBuffer) { + if (NULL == childEnvp) { + childEnvp = environ; + } + for (nEnv = 0; childEnvp[nEnv]; nEnv++) { + } + newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *)); + if (NULL == newEnvp) { + PR_DELETE(process); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + for (idx = 0; idx < nEnv; idx++) { + newEnvp[idx] = childEnvp[idx]; + } + newEnvp[idx++] = attr->fdInheritBuffer; + newEnvp[idx] = NULL; + childEnvp = newEnvp; + } + + process->md.pid = fork(); + + if ((pid_t) -1 == process->md.pid) { + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno); + PR_DELETE(process); + if (newEnvp) { + PR_DELETE(newEnvp); + } + return NULL; + } else if (0 == process->md.pid) { /* the child process */ + /* + * If the child process needs to exit, it must call _exit(). + * Do not call exit(), because exit() will flush and close + * the standard I/O file descriptors, and hence corrupt + * the parent process's standard I/O data structures. + */ + + if (attr) { + /* the osfd's to redirect stdin, stdout, and stderr to */ + int in_osfd = -1, out_osfd = -1, err_osfd = -1; + + if (attr->stdinFd + && attr->stdinFd->secret->md.osfd != 0) { + in_osfd = attr->stdinFd->secret->md.osfd; + if (dup2(in_osfd, 0) != 0) { + _exit(1); /* failed */ + } + flags = fcntl(0, F_GETFL, 0); + if (flags & O_NONBLOCK) { + fcntl(0, F_SETFL, flags & ~O_NONBLOCK); + } + } + if (attr->stdoutFd + && attr->stdoutFd->secret->md.osfd != 1) { + out_osfd = attr->stdoutFd->secret->md.osfd; + if (dup2(out_osfd, 1) != 1) { + _exit(1); /* failed */ + } + flags = fcntl(1, F_GETFL, 0); + if (flags & O_NONBLOCK) { + fcntl(1, F_SETFL, flags & ~O_NONBLOCK); + } + } + if (attr->stderrFd + && attr->stderrFd->secret->md.osfd != 2) { + err_osfd = attr->stderrFd->secret->md.osfd; + if (dup2(err_osfd, 2) != 2) { + _exit(1); /* failed */ + } + flags = fcntl(2, F_GETFL, 0); + if (flags & O_NONBLOCK) { + fcntl(2, F_SETFL, flags & ~O_NONBLOCK); + } + } + if (in_osfd != -1) { + close(in_osfd); + } + if (out_osfd != -1 && out_osfd != in_osfd) { + close(out_osfd); + } + if (err_osfd != -1 && err_osfd != in_osfd + && err_osfd != out_osfd) { + close(err_osfd); + } + if (attr->currentDirectory) { + if (chdir(attr->currentDirectory) < 0) { + _exit(1); /* failed */ + } + } + } + + if (childEnvp) { + (void)execve(path, argv, childEnvp); + } else { + /* Inherit the environment of the parent. */ + (void)execv(path, argv); + } + /* Whoops! It returned. That's a bad sign. */ + _exit(1); + } + + if (newEnvp) { + PR_DELETE(newEnvp); + } + + return process; } PRStatus _MD_detach_process (PRProcess *process) { - return PR_NOT_IMPLEMENTED_ERROR; + /* If we kept a process table like unix does, + * we'd remove the entry here. + * Since we dont', just delete the process variable + */ + PR_DELETE(process); + return PR_SUCCESS; } PRStatus _MD_wait_process (PRProcess *process, PRInt32 *exitCode) { - return PR_NOT_IMPLEMENTED_ERROR; + PRStatus retVal = PR_SUCCESS; + int ret, status; + + /* Ignore interruptions */ + do { + ret = waitpid(process->md.pid, &status, 0); + } while (ret == -1 && errno == EINTR); + + /* + * waitpid() cannot return 0 because we did not invoke it + * with the WNOHANG option. + */ + PR_ASSERT(0 != ret); + + if (ret < 0) { + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); + return PR_FAILURE; + } + + /* If child process exited normally, return child exit code */ + if (WIFEXITED(status)) { + *exitCode = WEXITSTATUS(status); + } else { + PR_ASSERT(WIFSIGNALED(status)); + *exitCode = _PR_SIGNALED_EXITSTATUS; + } + + PR_DELETE(process); + return PR_SUCCESS; } PRStatus _MD_kill_process (PRProcess *process) { - return PR_NOT_IMPLEMENTED_ERROR; + PRErrorCode prerror; + PRInt32 oserror; + + if (kill(process->md.pid, SIGKILL) == 0) { + return PR_SUCCESS; + } + oserror = errno; + switch (oserror) { + case EPERM: + prerror = PR_NO_ACCESS_RIGHTS_ERROR; + break; + case ESRCH: + prerror = PR_INVALID_ARGUMENT_ERROR; + break; + default: + prerror = PR_UNKNOWN_ERROR; + break; + } + PR_SetError(prerror, oserror); + return PR_FAILURE; } diff --git a/pr/src/md/mac/macdll.c b/pr/src/md/mac/macdll.c index 2cfe79db..23b32759 100644 --- a/pr/src/md/mac/macdll.c +++ b/pr/src/md/mac/macdll.c @@ -218,7 +218,7 @@ GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, v // see if this symbol is in this fragment if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength)) - tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, pFilterData->inName, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName); + tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName); else return; @@ -503,19 +503,30 @@ done: OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID) { - UInt32 fragOffset, fragLength; - Ptr main; - Str255 fragName = "\p"; - Str255 errName; - OSErr err; - - err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength); - if (err != noErr) return err; - - err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName, - kLoadCFrag, outConnectionID, &main, errName); - - return err; + UInt32 fragOffset, fragLength; + short fragNameLength; + Ptr main; + Str255 fragName; + Str255 errName; + OSErr err; + + err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength); + if (err != noErr) return err; + + // convert fragment name to pascal string + fragNameLength = strlen(fragmentName); + if (fragNameLength > 255) + fragNameLength = 255; + BlockMoveData(fragmentName, &fragName[1], fragNameLength); + fragName[0] = fragNameLength; + + // Note that we pass the fragment name as the 4th param to GetDiskFragment. + // This value affects the ability of debuggers, and the Talkback system, + // to match code fragments with symbol files + err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName, + kLoadCFrag, outConnectionID, &main, errName); + + return err; } @@ -532,39 +543,42 @@ OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFra -----------------------------------------------------------------*/ OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex, - char** outFragName, CFragConnectionID *outConnectionID) + char** outFragName, CFragConnectionID *outConnectionID) { - UInt32 fragOffset, fragLength; - char *fragNameBlock = NULL; - Ptr main; - Str255 fragName = "\p"; - Str255 errName; - OSErr err; - - *outFragName = NULL; - - err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock); - if (err != noErr) return err; - - if (fragNameBlock) - { - UInt32 nameLen = strlen(fragNameBlock); - if (nameLen > 63) - nameLen = 63; - BlockMoveData(fragNameBlock, &fragName[1], nameLen); - fragName[0] = nameLen; - } - - err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName, - kLoadCFrag, outConnectionID, &main, errName); - if (err != noErr) - { - free(fragNameBlock); - return err; - } - - *outFragName = fragNameBlock; - return noErr; + UInt32 fragOffset, fragLength; + char *fragNameBlock = NULL; + Ptr main; + Str255 fragName = "\p"; + Str255 errName; + OSErr err; + + *outFragName = NULL; + + err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock); + if (err != noErr) return err; + + if (fragNameBlock) + { + UInt32 nameLen = strlen(fragNameBlock); + if (nameLen > 63) + nameLen = 63; + BlockMoveData(fragNameBlock, &fragName[1], nameLen); + fragName[0] = nameLen; + } + + // Note that we pass the fragment name as the 4th param to GetDiskFragment. + // This value affects the ability of debuggers, and the Talkback system, + // to match code fragments with symbol files + err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName, + kLoadCFrag, outConnectionID, &main, errName); + if (err != noErr) + { + free(fragNameBlock); + return err; + } + + *outFragName = fragNameBlock; + return noErr; } diff --git a/pr/src/md/mac/macio.c b/pr/src/md/mac/macio.c index 0a546635..f4bb60a4 100644 --- a/pr/src/md/mac/macio.c +++ b/pr/src/md/mac/macio.c @@ -81,15 +81,16 @@ static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr) if (_PR_MD_GET_INTSOFF()) { thread->md.missedIONotify = PR_TRUE; cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - return; - } + } else { + _PR_INTSOFF(is); - _PR_INTSOFF(is); + thread->md.osErrCode = noErr; + DoneWaitingOnThisThread(thread); - thread->md.osErrCode = noErr; - DoneWaitingOnThisThread(thread); + _PR_FAST_INTSON(is); + } - _PR_FAST_INTSON(is); + SignalIdleSemaphore(); } void _MD_SetError(OSErr oserror) @@ -266,7 +267,7 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op) a 32 byte Ptr in the heap, so only do this once */ if (!sCompletionUPP) - sCompletionUPP = NewIOCompletionProc((IOCompletionProcPtr)&AsyncIOCompletion); + sCompletionUPP = NewIOCompletionUPP((IOCompletionProcPtr)&AsyncIOCompletion); /* grab the thread so we know which one to post to at completion */ pbAsync.thread = me; @@ -1295,7 +1296,9 @@ ConvertUnixPathToMacPath(const char *unixPath, char **macPath) FSSpec foundSpec; short pathBufferSize; +#if DEBUG char *temp; +#endif int tempLen; // Are we dealing with the temp folder? @@ -1905,14 +1908,12 @@ PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { #pragma unused (fmap, size) - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRInt32 _MD_GetMemMapAlignment(void) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } @@ -1924,7 +1925,6 @@ void * _MD_MemMap( { #pragma unused (fmap, offset, len) - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } @@ -1933,7 +1933,6 @@ PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { #pragma unused (addr, len) - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } @@ -1942,7 +1941,6 @@ PRStatus _MD_CloseFileMap(PRFileMap *fmap) { #pragma unused (fmap) - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } diff --git a/pr/src/md/mac/macsocket.h b/pr/src/md/mac/macsocket.h index b1045e36..b9194c52 100644 --- a/pr/src/md/mac/macsocket.h +++ b/pr/src/md/mac/macsocket.h @@ -39,6 +39,7 @@ // Interface visible to xp code // C socket type definitions and routines // from sys/socket.h +#include <Files.h> #include <OpenTptInternet.h> // All the internet typedefs #include <utime.h> // For timeval /* diff --git a/pr/src/md/mac/macsockotpt.c b/pr/src/md/mac/macsockotpt.c index ef15a56b..6c54de4c 100644 --- a/pr/src/md/mac/macsockotpt.c +++ b/pr/src/md/mac/macsockotpt.c @@ -38,6 +38,7 @@ #include <string.h> #include <Gestalt.h> +#include <Files.h> #include <OpenTransport.h> #include <OSUtils.h> @@ -173,9 +174,9 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O if (_PR_MD_GET_INTSOFF()) { dnsContext.thread->md.missedIONotify = PR_TRUE; cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - return; + } else { + DoneWaitingOnThisThread(dnsContext.thread); } - DoneWaitingOnThisThread(dnsContext.thread); break; case kOTProviderWillClose: @@ -189,9 +190,9 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O if (_PR_MD_GET_INTSOFF()) { dnsContext.thread->md.missedIONotify = PR_TRUE; cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - return; + } else { + DoneWaitingOnThisThread(dnsContext.thread); } - DoneWaitingOnThisThread(dnsContext.thread); break; default: // or else we don't handle the event @@ -199,6 +200,8 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O } // or else we don't handle the event + + SignalIdleSemaphore(); } @@ -296,10 +299,12 @@ WakeUpNotifiedThread(PRThread *thread, OTResult result) if (_PR_MD_GET_INTSOFF()) { thread->md.missedIONotify = PR_TRUE; cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - return; + } else { + DoneWaitingOnThisThread(thread); } - DoneWaitingOnThisThread(thread); } + + SignalIdleSemaphore(); } // Notification routine @@ -369,6 +374,8 @@ static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResul PR_ASSERT(err == kOTNoError); secret->md.exceptReady = PR_TRUE; // XXX Check this + md->disconnectError = discon.reason; // save for _MD_mac_get_nonblocking_connect_error + // wake up waiting threads, if any result = -3199 - discon.reason; // obtain the negative error code if ((readThread = secret->md.read.thread) != NULL) { @@ -1080,12 +1087,12 @@ typedef struct RawEndpointAndThread // A5 is OK. Cannot allocate memory here static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) { - RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr; + RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr; PRThread * thread = endthr->thread; EndpointRef * endpoint = endthr->endpoint; _PRCPU * cpu = _PR_MD_CURRENT_CPU(); - OSStatus err; - OTResult resultOT; + OSStatus err; + OTResult resultOT; switch (code) { @@ -1169,10 +1176,12 @@ static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode co if (_PR_MD_GET_INTSOFF()) { thread->md.asyncNotifyPending = PR_TRUE; cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - return; + } else { + DoneWaitingOnThisThread(thread); } - DoneWaitingOnThisThread(thread); } + + SignalIdleSemaphore(); } PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) @@ -1309,7 +1318,7 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva err = kEFAULTErr; goto ErrorExit; } - + // Bind to a local port; let the system assign it. bindAddr.inet.family = AF_INET; @@ -1320,19 +1329,19 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva bindReq.addr.buf = (UInt8*) &bindAddr; bindReq.qlen = 0; - PR_Lock(fd->secret->md.miscLock); + PR_Lock(fd->secret->md.miscLock); PrepareForAsyncCompletion(me, fd->secret->md.osfd); - fd->secret->md.misc.thread = me; + fd->secret->md.misc.thread = me; err = OTBind(endpoint, &bindReq, NULL); if (err != kOTNoError) { - me->io_pending = PR_FALSE; - PR_Unlock(fd->secret->md.miscLock); - goto ErrorExit; - } + me->io_pending = PR_FALSE; + PR_Unlock(fd->secret->md.miscLock); + goto ErrorExit; + } WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); - PR_Unlock(fd->secret->md.miscLock); + PR_Unlock(fd->secret->md.miscLock); err = me->md.osErrCode; if (err != kOTNoError) @@ -1344,26 +1353,26 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva sndCall.addr.len = addrlen; sndCall.addr.buf = (UInt8*) addr; - if (!fd->secret->nonblocking) { - PrepareForAsyncCompletion(me, fd->secret->md.osfd); - PR_ASSERT(fd->secret->md.write.thread == NULL); - fd->secret->md.write.thread = me; + if (!fd->secret->nonblocking) { + PrepareForAsyncCompletion(me, fd->secret->md.osfd); + PR_ASSERT(fd->secret->md.write.thread == NULL); + fd->secret->md.write.thread = me; } - + err = OTConnect (endpoint, &sndCall, NULL); - if (err == kOTNoError) { - PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!"); - } - if (fd->secret->nonblocking) { - if (err == kOTNoDataErr) - err = EINPROGRESS; - goto ErrorExit; - } else { - if (err != kOTNoError && err != kOTNoDataErr) { - me->io_pending = PR_FALSE; - goto ErrorExit; - } - } + if (err == kOTNoError) { + PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!"); + } + if (fd->secret->nonblocking) { + if (err == kOTNoDataErr) + err = EINPROGRESS; + goto ErrorExit; + } else { + if (err != kOTNoError && err != kOTNoDataErr) { + me->io_pending = PR_FALSE; + goto ErrorExit; + } + } WaitOnThisThread(me, timeout); @@ -1583,7 +1592,6 @@ static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount, PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 bytesLeft = amount; TUnitData dgram; - OTResult result; PR_ASSERT(flags == 0); @@ -1618,13 +1626,13 @@ static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount, fd->secret->md.write.thread = me; fd->secret->md.writeReady = PR_FALSE; // expect the worst err = OTSndUData(endpoint, &dgram); - if (result != kOTFlowErr) // hope for the best + if (err != kOTFlowErr) // hope for the best fd->secret->md.writeReady = PR_TRUE; } else { fd->secret->md.read.thread = me; fd->secret->md.readReady = PR_FALSE; // expect the worst err = OTRcvUData(endpoint, &dgram, NULL); - if (result != kOTNoDataErr) // hope for the best + if (err != kOTNoDataErr) // hope for the best fd->secret->md.readReady = PR_TRUE; } @@ -1754,83 +1762,131 @@ static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PR } // check to see if any of the poll descriptors have data available +// for reading or writing, by calling their poll methods (layered IO). +static PRInt32 CheckPollDescMethods(PRPollDesc *pds, PRIntn npds, PRInt16 *outReadFlags, PRInt16 *outWriteFlags) +{ + PRInt32 ready = 0; + PRPollDesc *pd, *epd; + PRInt16 *readFlag, *writeFlag; + + for (pd = pds, epd = pd + npds, readFlag = outReadFlags, writeFlag = outWriteFlags; + pd < epd; + pd++, readFlag++, writeFlag++) + { + PRInt16 in_flags_read = 0, in_flags_write = 0; + PRInt16 out_flags_read = 0, out_flags_write = 0; + + pd->out_flags = 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; + } + + *readFlag = in_flags_read; + *writeFlag = in_flags_write; + } + + return ready; +} + +// check to see if any of OT endpoints of the poll descriptors have data available // for reading or writing. -static PRInt32 CheckPollDescs(PRPollDesc *pds, PRIntn npds) +static PRInt32 CheckPollDescEndpoints(PRPollDesc *pds, PRIntn npds, const PRInt16 *inReadFlags, const PRInt16 *inWriteFlags) { PRInt32 ready = 0; PRPollDesc *pd, *epd; + const PRInt16 *readFlag, *writeFlag; - 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; + for (pd = pds, epd = pd + npds, readFlag = inReadFlags, writeFlag = inWriteFlags; + pd < epd; + pd++, readFlag++, writeFlag++) + { + PRFileDesc *bottomFD; + PRBool readReady, writeReady, exceptReady; + PRInt16 in_flags_read = *readFlag; + PRInt16 in_flags_write = *writeFlag; - if (NULL == pd->fd || pd->in_flags == 0) continue; + 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 *bottomFD; - PRBool readReady, writeReady, exceptReady; + if ((pd->in_flags & ~pd->out_flags) == 0) { + ready++; + continue; + } - pd->out_flags = 0; /* pre-condition */ - bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); - /* bottomFD can be NULL for pollable sockets */ - if (bottomFD) + bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); + /* bottomFD can be NULL for pollable sockets */ + if (bottomFD) + { + if (_PR_FILEDESC_OPEN == bottomFD->secret->state) + { + if (GetState(bottomFD, &readReady, &writeReady, &exceptReady)) { - if (_PR_FILEDESC_OPEN == bottomFD->secret->state) + 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 (GetState(bottomFD, &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++; - } + 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; } - else /* bad state */ + if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT)) { - ready += 1; /* this will cause an abrupt return */ - pd->out_flags = PR_POLL_NVAL; /* bogii */ + pd->out_flags |= PR_POLL_EXCEPT; } } + if (0 != pd->out_flags) ready++; + } + else /* bad state */ + { + ready += 1; /* this will cause an abrupt return */ + pd->out_flags = PR_POLL_NVAL; /* bogii */ } } + } return ready; } -// set or clear md.poll.thread on the poll descriptors + +// see how many of the poll descriptors are ready +static PRInt32 CountReadyPollDescs(PRPollDesc *pds, PRIntn npds) +{ + PRInt32 ready = 0; + PRPollDesc *pd, *epd; + + for (pd = pds, epd = pd + npds; pd < epd; pd++) + { + if (pd->out_flags) + ready ++; + } + + return ready; +} + +// set or clear the poll thread on the poll descriptors static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread) { PRInt32 ready = 0; @@ -1862,43 +1918,82 @@ static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread) bottomFD->secret->md.write.thread = thread; } } - } + } } } + +#define DESCRIPTOR_FLAGS_ARRAY_SIZE 32 + PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { + PRInt16 readFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE]; + PRInt16 writeFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE]; + + PRInt16 *readFlags = readFlagsArray; + PRInt16 *writeFlags = writeFlagsArray; + + PRInt16 *ioFlags = NULL; + PRThread *thread = _PR_MD_CURRENT_THREAD(); - intn is; - PRInt32 ready; + PRInt32 ready; - if (timeout == PR_INTERVAL_NO_WAIT) { - return CheckPollDescs(pds, npds); + if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE) + { + // we allocate a single double-size array. The first half is used + // for read flags, and the second half for write flags. + ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2); + if (!ioFlags) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return -1; + } + + readFlags = ioFlags; + writeFlags = &ioFlags[npds]; } - - _PR_INTSOFF(is); - PR_Lock(thread->md.asyncIOLock); - // ensure that we don't miss the firing of the notifier while checking socket status - // need to set up the thread - PrepareForAsyncCompletion(thread, 0); + // we have to be outside the lock when calling this, since + // it can call arbitrary user code (including other socket + // entry points) + ready = CheckPollDescMethods(pds, npds, readFlags, writeFlags); - SetDescPollThread(pds, npds, thread); - ready = CheckPollDescs(pds, npds); + if (!ready && timeout != PR_INTERVAL_NO_WAIT) { + intn is; + - PR_Unlock(thread->md.asyncIOLock); - _PR_FAST_INTSON(is); + _PR_INTSOFF(is); + PR_Lock(thread->md.asyncIOLock); + PrepareForAsyncCompletion(thread, 0); - if (ready == 0) { - WaitOnThisThread(thread, timeout); - ready = CheckPollDescs(pds, npds); + SetDescPollThread(pds, npds, thread); - } else { + (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); + + PR_Unlock(thread->md.asyncIOLock); + _PR_FAST_INTSON(is); + + ready = CountReadyPollDescs(pds, npds); + + if (ready == 0) { + WaitOnThisThread(thread, timeout); + + // since we may have been woken by a pollable event firing, + // we have to check both poll methods and endpoints. + (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags); + ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); + } + thread->io_pending = PR_FALSE; + SetDescPollThread(pds, npds, NULL); + } + else { + ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags); } - SetDescPollThread(pds, npds, NULL); - + if (readFlags != readFlagsArray) + PR_Free(ioFlags); + return ready; } @@ -2192,25 +2287,32 @@ ErrorExit: } -int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd) +int _MD_mac_get_nonblocking_connect_error(PRFileDesc* fd) { - OTResult resultOT; - EndpointRef endpoint = (EndpointRef) osfd; + EndpointRef endpoint = (EndpointRef)fd->secret->md.osfd; + OTResult resultOT = OTGetEndpointState(endpoint); - resultOT = OTGetEndpointState(endpoint); switch (resultOT) { case T_OUTCON: macsock_map_error(EINPROGRESS); return -1; + case T_DATAXFER: return 0; + case T_IDLE: + macsock_map_error(fd->secret->md.disconnectError); + fd->secret->md.disconnectError = 0; return -1; + case T_INREL: macsock_map_error(ENOTCONN); return -1; + default: PR_ASSERT(0); return -1; } + + return -1; // not reached } diff --git a/pr/src/md/mac/macthr.c b/pr/src/md/mac/macthr.c index 0df8a590..fd3b489d 100644 --- a/pr/src/md/mac/macthr.c +++ b/pr/src/md/mac/macthr.c @@ -39,7 +39,7 @@ #include <MacTypes.h> #include <Timer.h> #include <OSUtils.h> - +#include <Math64.h> #include <LowMem.h> #include <Multiprocessing.h> #include <Gestalt.h> @@ -49,6 +49,8 @@ TimerUPP gTimerCallbackUPP = NULL; PRThread * gPrimaryThread = NULL; +ProcessSerialNumber gApplicationProcess; + PR_IMPLEMENT(PRThread *) PR_GetPrimaryThread() { return gPrimaryThread; @@ -159,7 +161,21 @@ extern void _MD_ClearStack(PRThreadStack *ts) #pragma mark - #pragma mark TIME MANAGER-BASED CLOCK -TMTask gTimeManagerTaskElem; +// On Mac OS X, it's possible for the application to spend lots of time +// in WaitNextEvent, yielding to other applications. Since NSPR threads are +// cooperative here, this means that NSPR threads will also get very little +// time to run. To kick ourselves out of a WaitNextEvent call when we have +// determined that it's time to schedule another thread, the Timer Task +// (which fires every 8ms, even when other apps have the CPU) calls WakeUpProcess. +// We only want to do this on Mac OS X; the gTimeManagerTaskDoesWUP variable +// indicates when we're running on that OS. +// +// Note that the TimerCallback makes use of gApplicationProcess. We need to +// have set this up before the first possible run of the timer task; we do +// so in _MD_EarlyInit(). +static Boolean gTimeManagerTaskDoesWUP; + +static TMTask gTimeManagerTaskElem; extern void _MD_IOInterrupt(void); _PRInterruptTable _pr_interruptTable[] = { @@ -168,6 +184,8 @@ _PRInterruptTable _pr_interruptTable[] = { { 0 } }; +#define kMacTimerInMiliSecs 8L + pascal void TimerCallback(TMTaskPtr tmTaskPtr) { _PRCPU *cpu = _PR_MD_CURRENT_CPU(); @@ -184,8 +202,20 @@ pascal void TimerCallback(TMTaskPtr tmTaskPtr) // And tell nspr that a clock interrupt occured. _PR_ClockInterrupt(); - if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority))) + if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority))) { + if (gTimeManagerTaskDoesWUP) { + // We only want to call WakeUpProcess if we know that NSPR has managed to switch threads + // since the last call, otherwise we end up spewing out WakeUpProcess() calls while the + // application is blocking somewhere. This can interfere with events loops other than + // our own (see bug 158927). + if (UnsignedWideToUInt64(cpu->md.lastThreadSwitch) > UnsignedWideToUInt64(cpu->md.lastWakeUpProcess)) + { + WakeUpProcess(&gApplicationProcess); + cpu->md.lastWakeUpProcess = UpTime(); + } + } _PR_SET_RESCHED_FLAG(); + } _PR_FAST_INTSON(is); @@ -198,8 +228,10 @@ void _MD_StartInterrupts(void) { gPrimaryThread = _PR_MD_CURRENT_THREAD(); + gTimeManagerTaskDoesWUP = RunningOnOSX(); + if ( !gTimerCallbackUPP ) - gTimerCallbackUPP = NewTimerProc(TimerCallback); + gTimerCallbackUPP = NewTimerUPP(TimerCallback); // Fill in the Time Manager queue element @@ -222,26 +254,36 @@ void _MD_StopInterrupts(void) } } + +#define MAX_PAUSE_TIMEOUT_MS 500 + void _MD_PauseCPU(PRIntervalTime timeout) { if (timeout != PR_INTERVAL_NO_WAIT) { - EventRecord theEvent; - - /* - ** Calling WaitNextEvent() here is suboptimal. This routine should - ** pause the process until IO or the timeout occur, yielding time to - ** other processes on operating systems that require this (Mac OS classic). - ** WaitNextEvent() may incur too much latency, and has other problems, - ** such as the potential to drop suspend/resume events, and to handle - ** AppleEvents at a time at which we're not prepared to handle them. - */ - (void) WaitNextEvent(nullEvent, &theEvent, 1, NULL); - + // There is a race condition entering the critical section + // in AsyncIOCompletion (and probably elsewhere) that can + // causes deadlock for the duration of this timeout. To + // work around this, use a max 500ms timeout for now. + // See bug 99561 for details. + if (PR_IntervalToMilliseconds(timeout) > MAX_PAUSE_TIMEOUT_MS) + timeout = PR_MillisecondsToInterval(MAX_PAUSE_TIMEOUT_MS); + + WaitOnIdleSemaphore(timeout); (void) _MD_IOInterrupt(); } } +void _MD_InitRunningCPU(_PRCPU* cpu) +{ + cpu->md.trackScheduling = RunningOnOSX(); + if (cpu->md.trackScheduling) { + AbsoluteTime zeroTime = {0, 0}; + cpu->md.lastThreadSwitch = UpTime(); + cpu->md.lastWakeUpProcess = zeroTime; + } +} + //############################################################################## //############################################################################## @@ -528,19 +570,25 @@ void _MD_SetIntsOff(PRInt32 ints) #pragma mark - #pragma mark CRITICAL REGION SUPPORT + +static PRBool RunningOnOSX() +{ + long systemVersion; + OSErr err = Gestalt(gestaltSystemVersion, &systemVersion); + return (err == noErr) && (systemVersion >= 0x00001000); +} + + #if MAC_CRITICAL_REGIONS MDCriticalRegionID gCriticalRegion; void InitCriticalRegion() { - long systemVersion; OSStatus err; // we only need to do critical region stuff on Mac OS X - err = Gestalt(gestaltSystemVersion, &systemVersion); - gUseCriticalRegions = (err == noErr) && (systemVersion >= 0x00001000); - + gUseCriticalRegions = RunningOnOSX(); if (!gUseCriticalRegions) return; err = MD_CriticalRegionCreate(&gCriticalRegion); @@ -586,3 +634,85 @@ void LeaveCritialRegion() #endif // MAC_CRITICAL_REGIONS +//############################################################################## +//############################################################################## +#pragma mark - +#pragma mark IDLE SEMAPHORE SUPPORT + +/* + Since the WaitNextEvent() in _MD_PauseCPU() is causing all sorts of + headache under Mac OS X we're going to switch to MPWaitOnSemaphore() + which should do what we want +*/ + +#if TARGET_CARBON +PRBool gUseIdleSemaphore = PR_FALSE; +MPSemaphoreID gIdleSemaphore = NULL; +#endif + +void InitIdleSemaphore() +{ + // we only need to do idle semaphore stuff on Mac OS X +#if TARGET_CARBON + gUseIdleSemaphore = RunningOnOSX(); + if (gUseIdleSemaphore) + { + OSStatus err = MPCreateSemaphore(1 /* max value */, 0 /* initial value */, &gIdleSemaphore); + PR_ASSERT(err == noErr); + } +#endif +} + +void TermIdleSemaphore() +{ +#if TARGET_CARBON + if (gUseIdleSemaphore) + { + OSStatus err = MPDeleteSemaphore(gIdleSemaphore); + PR_ASSERT(err == noErr); + gUseIdleSemaphore = NULL; + } +#endif +} + + +void WaitOnIdleSemaphore(PRIntervalTime timeout) +{ +#if TARGET_CARBON + if (gUseIdleSemaphore) + { + OSStatus err = MPWaitOnSemaphore(gIdleSemaphore, kDurationMillisecond * PR_IntervalToMilliseconds(timeout)); + PR_ASSERT(err == noErr); + } + else +#endif + { + EventRecord theEvent; + /* + ** Calling WaitNextEvent() here is suboptimal. This routine should + ** pause the process until IO or the timeout occur, yielding time to + ** other processes on operating systems that require this (Mac OS classic). + ** WaitNextEvent() may incur too much latency, and has other problems, + ** such as the potential to drop suspend/resume events. + */ + (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL); + } +} + + +void SignalIdleSemaphore() +{ +#if TARGET_CARBON + if (gUseIdleSemaphore) + { + // often we won't be waiting on the semaphore here, so ignore any errors + (void)MPSignalSemaphore(gIdleSemaphore); + } + else +#endif + { + WakeUpProcess(&gApplicationProcess); + } +} + + diff --git a/pr/src/md/mac/mdcriticalregion.c b/pr/src/md/mac/mdcriticalregion.c index 927b9246..ff035d0d 100644 --- a/pr/src/md/mac/mdcriticalregion.c +++ b/pr/src/md/mac/mdcriticalregion.c @@ -35,6 +35,7 @@ */ #include "mdcriticalregion.h" +#include <MacErrors.h> /* This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion, diff --git a/pr/src/md/mac/mdmac.c b/pr/src/md/mac/mdmac.c index f7e9a4fa..6d65e578 100644 --- a/pr/src/md/mac/mdmac.c +++ b/pr/src/md/mac/mdmac.c @@ -70,6 +70,7 @@ unsigned char GarbageCollectorCacheFlusher(PRUint32 size); extern PRThread *gPrimaryThread; +extern ProcessSerialNumber gApplicationProcess; // in macthr.c //############################################################################## @@ -288,7 +289,10 @@ void _MD_EarlyInit() { Handle environmentVariables; + GetCurrentProcess(&gApplicationProcess); + INIT_CRITICAL_REGION(); + InitIdleSemaphore(); #if !defined(MAC_NSPR_STANDALONE) // MacintoshInitializeMemory(); Moved to mdmacmem.c: AllocateRawMemory(Size blockSize) @@ -376,6 +380,7 @@ void CleanupTermProc(void) _MD_StopInterrupts(); // deactive Time Manager task CLOSE_OPEN_TRANSPORT(); + TermIdleSemaphore(); TERM_CRITICAL_REGION(); __NSTerminate(); diff --git a/pr/src/md/os2/Makefile.in b/pr/src/md/os2/Makefile.in index 9898c88f..7f56eb23 100644 --- a/pr/src/md/os2/Makefile.in +++ b/pr/src/md/os2/Makefile.in @@ -62,6 +62,10 @@ ifeq ($(MOZ_OS2_TOOLS),VACPP) ASFILES = os2vacpp.asm endif +ifeq ($(MOZ_OS2_TOOLS),EMX) +ASFILES = os2emx.s os2vaclegacy.s +endif + TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private diff --git a/pr/src/md/os2/objs.mk b/pr/src/md/os2/objs.mk index 7c0bb943..05fe4658 100644 --- a/pr/src/md/os2/objs.mk +++ b/pr/src/md/os2/objs.mk @@ -52,6 +52,10 @@ ifeq ($(MOZ_OS2_TOOLS),VACPP) ASFILES = os2vacpp.asm endif +ifeq ($(MOZ_OS2_TOOLS),EMX) +ASFILES = os2emx.s os2vaclegacy.s +endif + OBJS += $(addprefix md/os2/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \ - $(addprefix md/os2/$(OBJDIR)/,$(ASFILES:.asm=.$(OBJ_SUFFIX))) + $(addprefix md/os2/$(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))) diff --git a/pr/src/md/os2/os2_errors.c b/pr/src/md/os2/os2_errors.c index f5be8391..7c270c4d 100644 --- a/pr/src/md/os2/os2_errors.c +++ b/pr/src/md/os2/os2_errors.c @@ -35,6 +35,44 @@ #include "prerror.h" #include "primpl.h" +void _MD_os2_map_default_error(PRInt32 err) +{ + switch (err) { + case EWOULDBLOCK: + PR_SetError(PR_WOULD_BLOCK_ERROR, err); + break; + case EBADF: + PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); + break; + case ENOTSOCK: + PR_SetError(PR_NOT_SOCKET_ERROR, err); + break; + case EMSGSIZE: + case EINVAL: + PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); + break; + case ENOBUFS: + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); + break; + case ECONNREFUSED: + PR_SetError(PR_CONNECT_REFUSED_ERROR, err); + break; + case EISCONN: + PR_SetError(PR_IS_CONNECTED_ERROR, err); + break; +#ifdef SOCEFAULT + case SOCEFAULT: + PR_SetError(PR_ACCESS_FAULT_ERROR, err); + break; +#endif + case ERROR_NETNAME_DELETED: + PR_SetError(PR_CONNECT_RESET_ERROR, err); + break; + default: + PR_SetError(PR_UNKNOWN_ERROR, err); + break; + } +} void _MD_os2_map_opendir_error(PRInt32 err) { switch (err) { @@ -92,7 +130,7 @@ void _MD_os2_map_closedir_error(PRInt32 err) } } -void _MD_unix_readdir_error(PRInt32 err) +void _MD_os2_readdir_error(PRInt32 err) { switch (err) { @@ -671,73 +709,17 @@ void _MD_os2_map_send_error(PRInt32 err) void _MD_os2_map_sendto_error(PRInt32 err) { - switch (err) { - case EWOULDBLOCK: - PR_SetError(PR_WOULD_BLOCK_ERROR, err); - break; - case EBADF: - PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); - break; - case ENOTSOCK: - PR_SetError(PR_NOT_SOCKET_ERROR, err); - break; - case EMSGSIZE: - case EINVAL: - PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); - break; - case ENOBUFS: - PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); - break; - case ECONNREFUSED: - PR_SetError(PR_CONNECT_REFUSED_ERROR, err); - break; - case EISCONN: - PR_SetError(PR_IS_CONNECTED_ERROR, err); - break; -#ifdef SOCEFAULT - case SOCEFAULT: - PR_SetError(PR_ACCESS_FAULT_ERROR, err); - break; -#endif - case ERROR_NETNAME_DELETED: - PR_SetError(PR_CONNECT_RESET_ERROR, err); - break; - default: - PR_SetError(PR_UNKNOWN_ERROR, err); - break; - } + _MD_os2_map_default_error(err); +} + +void _MD_os2_map_writev_error(int err) +{ + _MD_os2_map_default_error(err); } void _MD_os2_map_accept_error(PRInt32 err) { - switch (err) { - case EWOULDBLOCK: - PR_SetError(PR_WOULD_BLOCK_ERROR, err); - break; - case EBADF: - PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); - break; - case ENOTSOCK: - PR_SetError(PR_NOT_SOCKET_ERROR, err); - break; - case EOPNOTSUPP: - PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); - break; -#ifdef SOCEFAULT - case SOCEFAULT: - PR_SetError(PR_ACCESS_FAULT_ERROR, err); - break; -#endif - case EMFILE: - PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); - break; - case ENOBUFS: - PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); - break; - default: - PR_SetError(PR_UNKNOWN_ERROR, err); - break; - } + _MD_os2_map_default_error(err); } void _MD_os2_map_acceptex_error(PRInt32 err) @@ -759,6 +741,21 @@ void _MD_os2_map_acceptex_error(PRInt32 err) } } +/* + * An error code of 0 means that the nonblocking connect succeeded. + */ + +int _MD_os2_get_nonblocking_connect_error(int osfd) +{ + int err; + int len = sizeof(err); + if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == -1) { + return sock_errno(); + } else { + return err; + } +} + void _MD_os2_map_connect_error(PRInt32 err) { switch (err) { @@ -878,6 +875,30 @@ void _MD_os2_map_shutdown_error(PRInt32 err) } } +void _MD_os2_map_socketpair_error(PRInt32 err) +{ + switch (err) { + case ENOMEM: + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); + break; + case EAFNOSUPPORT: + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); + break; + case EPROTONOSUPPORT: + PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err); + break; + case EOPNOTSUPP: + PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); + break; + case EPROTOTYPE: + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); + break; + default: + _MD_os2_map_default_error(err); + return; + } +} + void _MD_os2_map_getsockname_error(PRInt32 err) { switch (err) { diff --git a/pr/src/md/os2/os2cv.c b/pr/src/md/os2/os2cv.c index 1a2d9399..44e1e68b 100644 --- a/pr/src/md/os2/os2cv.c +++ b/pr/src/md/os2/os2cv.c @@ -48,6 +48,42 @@ #include "primpl.h" +#ifdef USE_RAMSEM +ULONG _Far16 _Pascal Dos16GetInfoSeg(PSEL pselGlobal, PSEL pselLocal); + +#ifdef XP_OS2_EMX +typedef unsigned short BOOL16; +#endif + +typedef struct _LINFOSEG +{ + USHORT pidCurrent; + USHORT pidParent; + USHORT prtyCurrent; + USHORT tidCurrent; + USHORT sgCurrent; + UCHAR rfProcStatus; + UCHAR dummy1; + BOOL16 fForeground; + UCHAR typProcess; + UCHAR dummy2; + SEL selEnvironment; + USHORT offCmdLine; + USHORT cbDataSegment; + USHORT cbStack; + USHORT cbHeap; + USHORT hmod; + SEL selDS; + SEL selPack; + SEL selPackShr; + SEL selPackPck; + ULONG ulReserved; +} LINFOSEG; +typedef LINFOSEG FAR *PLINFOSEG; + +PLINFOSEG plisCurrent = NULL; +#endif + /* * AddThreadToCVWaitQueueInternal -- * @@ -82,7 +118,7 @@ AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv) * This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK, * the two places where a lock is unlocked. */ -static void +void md_UnlockAndPostNotifies( _MDLock *lock, PRThread *waitThred, @@ -163,7 +199,11 @@ md_UnlockAndPostNotifies( } /* Release the lock before notifying */ - DosReleaseMutexSem(lock->mutex); +#ifdef USE_RAMSEM + SemReleasex86(&lock->mutex, 0); +#else + DosReleaseMutexSem(lock->mutex); +#endif notified = &post; /* this is where we start */ do { @@ -270,7 +310,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout ) md_UnlockAndPostNotifies(lock, thred, cv); } else { AddThreadToCVWaitQueueInternal(thred, cv); +#ifdef USE_RAMSEM + SemReleasex86( &lock->mutex, 0 ); +#else DosReleaseMutexSem(lock->mutex); +#endif } /* Wait for notification or timeout; don't really care which */ @@ -279,7 +323,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout ) DosResetEventSem(thred->md.blocked_sema, &count); } +#ifdef USE_RAMSEM + SemRequest486(&(lock->mutex), -1); +#else DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT); +#endif PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT); @@ -336,28 +384,41 @@ _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock) PRStatus _PR_MD_NEW_LOCK(_MDLock *lock) { +#ifdef USE_RAMSEM + // It's better if this API traps when pCriticalSect is not a valid + // pointer, because we can't return an error code and if we just return + // the API caller will have nasty bugs that are hard to find. + + PRAMSEM pramsem = (PRAMSEM)(&(lock->mutex)); + /* First time, set up addresses of processor specific functions + */ + if (plisCurrent == NULL) + { + SEL selGlobal = 0, selLocal = 0; + + /* Convert 16 bit global information segment to 32 bit address + * by performing CRMA on the 16 bit address: "shift" operation + * to convert sel to flat, "and" operation to mask the address + * to 32-bit + */ + Dos16GetInfoSeg(&selGlobal, &selLocal); + plisCurrent = (PLINFOSEG)(((ULONG)selLocal << 13) & + (ULONG)0x1fff0000); + + } + + memset(pramsem, 0, sizeof(pramsem)); + DosCreateEventSem(0, &pramsem->hevSem, DC_SEM_SHARED, 0); + + lock->notified.length=0; + lock->notified.link=NULL; + return PR_SUCCESS; +#else DosCreateMutexSem(0, &(lock->mutex), 0, 0); (lock)->notified.length=0; (lock)->notified.link=NULL; return PR_SUCCESS; -} - -void -_PR_MD_FREE_LOCK(_MDLock *lock) -{ - DosCloseMutexSem(lock->mutex); -} - -void _PR_MD_LOCK(_MDLock *lock) -{ - DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT); -} - -PRIntn -_PR_MD_TEST_AND_LOCK(_MDLock *lock) -{ - DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT); - return 0; +#endif } void @@ -366,14 +427,3 @@ _PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock) md_PostNotifyToCvar(cv, lock, PR_TRUE); return; } - -void -_PR_MD_UNLOCK(_MDLock *lock) -{ - if (0 != lock->notified.length) { - md_UnlockAndPostNotifies(lock, NULL, NULL); - } else { - DosReleaseMutexSem(lock->mutex); - } - return; -} diff --git a/pr/src/md/os2/os2emx.s b/pr/src/md/os2/os2emx.s new file mode 100644 index 00000000..4dd81e39 --- /dev/null +++ b/pr/src/md/os2/os2emx.s @@ -0,0 +1,111 @@ +/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/ +/ The contents of this file are subject to the Mozilla Public +/ License Version 1.1 (the "License"); you may not use this file +/ except in compliance with the License. You may obtain a copy of +/ the License at http://www.mozilla.org/MPL/ +/ +/ Software distributed under the License is distributed on an "AS +/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +/ implied. See the License for the specific language governing +/ rights and limitations under the License. +/ +/ The Original Code is the Netscape Portable Runtime (NSPR). +/ +/ The Initial Developer of the Original Code is Netscape +/ Communications Corporation. Portions created by Netscape are +/ Copyright (C) 2000 Netscape Communications Corporation. All +/ Rights Reserved. +/ +/ Contributor(s): +/ +/ Alternatively, the contents of this file may be used under the +/ terms of the GNU General Public License Version 2 or later (the +/ "GPL"), in which case the provisions of the GPL are applicable +/ instead of those above. If you wish to allow use of your +/ version of this file only under the terms of the GPL and not to +/ allow others to use your version of this file under the MPL, +/ indicate your decision by deleting the provisions above and +/ replace them with the notice and other provisions required by +/ the GPL. If you do not delete the provisions above, a recipient +/ may use your version of this file under either the MPL or the +/ GPL. +/ + +/ PRInt32 __PR_MD_ATOMIC_INCREMENT(PRInt32 *val) +/ +/ Atomically increment the integer pointed to by 'val' and return +/ the result of the increment. +/ + .text + .globl __PR_MD_ATOMIC_INCREMENT + .align 4 +__PR_MD_ATOMIC_INCREMENT: + movl 4(%esp), %ecx + movl $1, %eax + lock + xaddl %eax, (%ecx) + incl %eax + ret + +/ PRInt32 __PR_MD_ATOMIC_DECREMENT(PRInt32 *val) +/ +/ Atomically decrement the integer pointed to by 'val' and return +/ the result of the decrement. +/ + .text + .globl __PR_MD_ATOMIC_DECREMENT + .align 4 +__PR_MD_ATOMIC_DECREMENT: + movl 4(%esp), %ecx + movl $-1, %eax + lock + xaddl %eax, (%ecx) + decl %eax + ret + +/ PRInt32 __PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) +/ +/ Atomically set the integer pointed to by 'val' to the new +/ value 'newval' and return the old value. +/ +/ An alternative implementation: +/ .text +/ .globl __PR_MD_ATOMIC_SET +/ .align 4 +/__PR_MD_ATOMIC_SET: +/ movl 4(%esp), %ecx +/ movl 8(%esp), %edx +/ movl (%ecx), %eax +/retry: +/ lock +/ cmpxchgl %edx, (%ecx) +/ jne retry +/ ret +/ + .text + .globl __PR_MD_ATOMIC_SET + .align 4 +__PR_MD_ATOMIC_SET: + movl 4(%esp), %ecx + movl 8(%esp), %eax + lock + xchgl %eax, (%ecx) + ret + +/ PRInt32 __PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) +/ +/ Atomically add 'val' to the integer pointed to by 'ptr' +/ and return the result of the addition. +/ + .text + .globl __PR_MD_ATOMIC_ADD + .align 4 +__PR_MD_ATOMIC_ADD: + movl 4(%esp), %ecx + movl 8(%esp), %eax + movl %eax, %edx + lock + xaddl %eax, (%ecx) + addl %edx, %eax + ret diff --git a/pr/src/md/os2/os2inrval.c b/pr/src/md/os2/os2inrval.c index 469da314..d4c90073 100644 --- a/pr/src/md/os2/os2inrval.c +++ b/pr/src/md/os2/os2inrval.c @@ -39,57 +39,62 @@ #include "primpl.h" -ULONG _os2_ticksPerSec = -1; +static PRBool useHighResTimer = PR_FALSE; +PRIntervalTime _os2_ticksPerSec = -1; PRIntn _os2_bitShift = 0; PRInt32 _os2_highMask = 0; - - void _PR_MD_INTERVAL_INIT() { - if (DosTmrQueryFreq(&_os2_ticksPerSec) == NO_ERROR) - { - while(_os2_ticksPerSec > PR_INTERVAL_MAX) { - _os2_ticksPerSec >>= 1; - _os2_bitShift++; - _os2_highMask = (_os2_highMask << 1)+1; - } - } - else - _os2_ticksPerSec = -1; + ULONG timerFreq = 0; /* OS/2 high-resolution timer frequency in Hz */ + APIRET rc = DosTmrQueryFreq(&timerFreq); + if (NO_ERROR == rc) { + useHighResTimer = PR_TRUE; + PR_ASSERT(timerFreq != 0); + while (timerFreq > PR_INTERVAL_MAX) { + timerFreq >>= 1; + _os2_bitShift++; + _os2_highMask = (_os2_highMask << 1)+1; + } - PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN && _os2_ticksPerSec < PR_INTERVAL_MAX); + _os2_ticksPerSec = timerFreq; + PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN); + } } PRIntervalTime _PR_MD_GET_INTERVAL() { - QWORD count; - - /* Sadly; nspr requires the interval to range from 1000 ticks per second - * to only 100000 ticks per second; Counter is too high - * resolution... - */ - if (DosTmrQueryTime(&count) == NO_ERROR) { - PRInt32 top = count.ulHi & _os2_highMask; + if (useHighResTimer) { + QWORD timestamp; + PRInt32 top; + APIRET rc = DosTmrQueryTime(×tamp); + if (NO_ERROR != rc) { + return -1; + } + /* Sadly, nspr requires the interval to range from 1000 ticks per + * second to only 100000 ticks per second. DosTmrQueryTime is too + * high resolution... + */ + top = timestamp.ulHi & _os2_highMask; top = top << (32 - _os2_bitShift); - count.ulLo = count.ulLo >> _os2_bitShift; - count.ulHi = count.ulLo + top; - return (PRUint32)count.ulLo; - } - else{ - ULONG msCount = PR_FAILURE; - DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount)); - return msCount; + timestamp.ulLo = timestamp.ulLo >> _os2_bitShift; + timestamp.ulLo = timestamp.ulLo + top; + return (PRUint32)timestamp.ulLo; + } else { + ULONG msCount = -1; + DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount)); + return msCount; } } PRIntervalTime _PR_MD_INTERVAL_PER_SEC() { - if(_os2_ticksPerSec != -1) - return _os2_ticksPerSec; - else - return 1000; + if (useHighResTimer) { + return _os2_ticksPerSec; + } else { + return 1000; + } } diff --git a/pr/src/md/os2/os2io.c b/pr/src/md/os2/os2io.c index 12e2f2a2..4897a31c 100644 --- a/pr/src/md/os2/os2io.c +++ b/pr/src/md/os2/os2io.c @@ -61,6 +61,7 @@ #include "primpl.h" #include "prio.h" #include <ctype.h> +#include <string.h> #ifdef XP_OS2_VACPP #include <direct.h> #else @@ -147,8 +148,6 @@ _PR_MD_OPEN(const char *name, PRIntn osflags, int mode) APIRET rc = 0; PRUword actionTaken; - ULONG CurMaxFH = 0; - LONG ReqCount = 1; ULONG fattr; if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH; @@ -253,6 +252,12 @@ _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) return -1; } + if (len != bytes) { + rv = ERROR_DISK_FULL; + _PR_MD_MAP_WRITE_ERROR(rv); + return -1; + } + return bytes; } /* --- end _PR_MD_WRITE() --- */ @@ -761,25 +766,43 @@ _PR_MD_UNLOCKFILE(PRInt32 f) PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) { - int rv = 0; + APIRET rc = 0; ULONG flags; + switch (fd->methods->file_type) + { + case PR_DESC_PIPE: + case PR_DESC_FILE: + rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags); + if (rc != NO_ERROR) { + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); + return PR_FAILURE; + } - rv = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags); - if (rv != 0) { - PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); - return PR_FAILURE; - } + if (inheritable) + flags &= ~OPEN_FLAGS_NOINHERIT; + else + flags |= OPEN_FLAGS_NOINHERIT; + + /* Mask off flags DosSetFHState don't want. */ + flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags); + if (rc != NO_ERROR) { + PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); + return PR_FAILURE; + } + break; - if (inheritable) - flags &= ~OPEN_FLAGS_NOINHERIT; - else - flags |= OPEN_FLAGS_NOINHERIT; + case PR_DESC_LAYERED: + /* what to do here? */ + PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/); + return PR_FAILURE; - rv = DosSetFHState((HFILE)fd->secret->md.osfd, flags); - if (rv != 0) { - PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); - return PR_FAILURE; + case PR_DESC_SOCKET_TCP: + case PR_DESC_SOCKET_UDP: + /* These are global on OS/2. */ + break; } + return PR_SUCCESS; } diff --git a/pr/src/md/os2/os2misc.c b/pr/src/md/os2/os2misc.c index be597fcd..4e9bb932 100644 --- a/pr/src/md/os2/os2misc.c +++ b/pr/src/md/os2/os2misc.c @@ -118,107 +118,28 @@ PR_Now(void) static int assembleCmdLine(char *const *argv, char **cmdLine) { char *const *arg; - char *p, *q; int cmdLineSize; - int numBackslashes; - int i; - int argNeedQuotes; /* * Find out how large the command line buffer should be. */ - cmdLineSize = 0; - for (arg = argv; *arg; arg++) { - /* - * \ and " need to be escaped by a \. In the worst case, - * every character is a \ or ", so the string of length - * may double. If we quote an argument, that needs two ". - * Finally, we need a space between arguments, a null between - * the EXE name and the arguments, and 2 nulls at the end - * of command line. - */ - cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */ - + 2 /* we quote every argument */ - + 4; /* space in between, or final nulls */ - } - p = *cmdLine = PR_MALLOC(cmdLineSize); - if (p == NULL) { + cmdLineSize = 1; /* final null */ + for (arg = argv+1; *arg; arg++) { + cmdLineSize += strlen(*arg) + 1; /* space in between */ + } + *cmdLine = PR_MALLOC(cmdLineSize); + if (*cmdLine == NULL) { return -1; } - for (arg = argv; *arg; arg++) { - /* Add a space to separates the arguments */ - if (arg > argv + 1) { - *p++ = ' '; - } - q = *arg; - numBackslashes = 0; - argNeedQuotes = 0; - - /* If the argument contains white space, it needs to be quoted. */ - if (strpbrk(*arg, " \f\n\r\t\v")) { - argNeedQuotes = 1; - } + (*cmdLine)[0] = '\0'; - if (argNeedQuotes) { - *p++ = '"'; + for (arg = argv+1; *arg; arg++) { + if (arg > argv +1) { + strcat(*cmdLine, " "); } - while (*q) { - if (*q == '\\') { - numBackslashes++; - q++; - } else if (*q == '"') { - if (numBackslashes) { - /* - * Double the backslashes since they are followed - * by a quote - */ - for (i = 0; i < 2 * numBackslashes; i++) { - *p++ = '\\'; - } - numBackslashes = 0; - } - /* To escape the quote */ - *p++ = '\\'; - *p++ = *q++; - } else { - if (numBackslashes) { - /* - * Backslashes are not followed by a quote, so - * don't need to double the backslashes. - */ - for (i = 0; i < numBackslashes; i++) { - *p++ = '\\'; - } - numBackslashes = 0; - } - *p++ = *q++; - } - } - - /* Now we are at the end of this argument */ - if (numBackslashes) { - /* - * Double the backslashes if we have a quote string - * delimiter at the end. - */ - if (argNeedQuotes) { - numBackslashes *= 2; - } - for (i = 0; i < numBackslashes; i++) { - *p++ = '\\'; - } - } - if (argNeedQuotes) { - *p++ = '"'; - } - if(arg == argv) - *p++ = '\0'; + strcat(*cmdLine, *arg); } - - /* Add 2 nulls at the end */ - *p++ = '\0'; - *p = '\0'; return 0; } @@ -308,138 +229,160 @@ static int compare(const void *arg1, const void *arg2) { return stricmp(* (char**)arg1, * (char**)arg2); } + PRProcess * _PR_CreateOS2Process( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { - char szFailed[CCHMAXPATH]; - RESULTCODES procInfo; - APIRET retVal; - char *cmdLine = NULL; - char *envBlock = NULL; - char **newEnvp; - PRProcess *proc = NULL; - HFILE hStdIn = 0, - hStdOut = 0, - hStdErr = 0; - HFILE hStdInSave = -1, - hStdOutSave = -1, - hStdErrSave = -1; - - proc = PR_NEW(PRProcess); - if (!proc) { - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - goto errorExit; - } - - if (assembleCmdLine(argv, &cmdLine) == -1) { - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - goto errorExit; - } - - if (envp == NULL) { - newEnvp = NULL; - } else { - int i; - int numEnv = 0; - while (envp[numEnv]) { - numEnv++; - } - newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *)); - for (i = 0; i <= numEnv; i++) { - newEnvp[i] = envp[i]; - } - qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare); - } - if (assembleEnvBlock(newEnvp, &envBlock) == -1) { - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - goto errorExit; - } - - if (attr) { - /* On OS/2, there is really no way to pass file handles for stdin, stdout, - * and stderr to a new process. Instead, we can make it a child process - * and make the given file handles a copy of our stdin, stdout, and stderr. - * The child process then inherits ours, and we set ours back. Twisted - * and gross I know. If you know a better way, please use it. - */ - if (attr->stdinFd) { - hStdIn = 0; - DosDupHandle(hStdIn, &hStdInSave); - DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn); - } - if (attr->stdoutFd) { - hStdOut = 1; - DosDupHandle(hStdOut, &hStdOutSave); - DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut); + PRProcess *proc = NULL; + char *cmdLine = NULL; + char **newEnvp = NULL; + char *envBlock = NULL; + + STARTDATA startData = {0}; + APIRET rc; + ULONG ulAppType = 0; + PID pid = 0; + char *pEnvWPS = NULL; + char *pszComSpec; + char pszEXEName[CCHMAXPATH] = ""; + char pszFormatString[CCHMAXPATH]; + char pszObjectBuffer[CCHMAXPATH]; + char *pszFormatResult = NULL; + + proc = PR_NEW(PRProcess); + if (!proc) { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + goto errorExit; + } + + if (assembleCmdLine(argv, &cmdLine) == -1) { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + goto errorExit; + } + + if (envp == NULL) { + newEnvp = NULL; + } else { + int i; + int numEnv = 0; + while (envp[numEnv]) { + numEnv++; } - if (attr->stderrFd) { - hStdErr = 2; - DosDupHandle(hStdErr, &hStdErrSave); - DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr); + newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *)); + for (i = 0; i <= numEnv; i++) { + newEnvp[i] = envp[i]; } - } - - retVal = DosExecPgm(szFailed, - CCHMAXPATH, - EXEC_ASYNCRESULT, - cmdLine, - envBlock, - &procInfo, - argv[0]); - - /* Restore our old values. Hope this works */ - if(hStdInSave != -1){ - DosDupHandle(hStdInSave, &hStdIn); - DosClose(hStdInSave); - } - if(hStdOutSave != -1){ - DosDupHandle(hStdOutSave, &hStdOut); - DosClose(hStdOutSave); - } - if(hStdErrSave != -1){ - DosDupHandle(hStdErrSave, &hStdErr); - DosClose(hStdErrSave); - } + qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare); + } + if (assembleEnvBlock(newEnvp, &envBlock) == -1) { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + goto errorExit; + } + + if (attr) { + PR_ASSERT(!"Not implemented"); + } - if (retVal != NO_ERROR) { - /* XXX what error code? */ - PR_SetError(PR_UNKNOWN_ERROR, retVal); + rc = DosQueryAppType(path, &ulAppType); + if (rc != NO_ERROR) { + char *pszDot = strrchr(path, '.'); + if (pszDot) { + /* If it is a CMD file, launch the users command processor */ + if (!stricmp(pszDot, ".cmd")) { + rc = DosScanEnv("COMSPEC", &pszComSpec); + if (!rc) { + strcpy(pszFormatString, "/C %s %s"); + strcpy(pszEXEName, pszComSpec); + ulAppType = FAPPTYP_WINDOWCOMPAT; + } + } + } + } + if (ulAppType == 0) { + PR_SetError(PR_UNKNOWN_ERROR, 0); goto errorExit; - } - - proc->md.pid = procInfo.codeTerminate; + } + + if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) { + startData.SessionType = SSF_TYPE_PM; + } + else if (ulAppType & FAPPTYP_WINDOWCOMPAT) { + startData.SessionType = SSF_TYPE_WINDOWABLEVIO; + } + else { + startData.SessionType = SSF_TYPE_DEFAULT; + } + + if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL)) + { + strcpy(pszEXEName, "WINOS2.COM"); + startData.SessionType = PROG_31_STDSEAMLESSVDM; + strcpy(pszFormatString, "/3 %s %s"); + } + + startData.InheritOpt = SSF_INHERTOPT_SHELL; + + if (pszEXEName[0]) { + pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine)); + sprintf(pszFormatResult, pszFormatString, path, cmdLine); + startData.PgmInputs = pszFormatResult; + } else { + strcpy(pszEXEName, path); + startData.PgmInputs = cmdLine; + } + startData.PgmName = pszEXEName; + + startData.Length = sizeof(startData); + startData.Related = SSF_RELATED_INDEPENDENT; + startData.ObjectBuffer = pszObjectBuffer; + startData.ObjectBuffLen = CCHMAXPATH; + startData.Environment = envBlock; + + rc = DosStartSession(&startData, &ulAppType, &pid); + + if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) { + PR_SetError(PR_UNKNOWN_ERROR, 0); + } + + proc->md.pid = pid; - PR_DELETE(cmdLine); - if (envBlock) { - PR_DELETE(envBlock); - } - return proc; + if (pszFormatResult) { + PR_DELETE(pszFormatResult); + } + + PR_DELETE(cmdLine); + if (newEnvp) { + PR_DELETE(newEnvp); + } + if (envBlock) { + PR_DELETE(envBlock); + } + return proc; errorExit: - if (cmdLine) { - PR_DELETE(cmdLine); - } - if (envBlock) { - PR_DELETE(envBlock); - } - if (proc) { - PR_DELETE(proc); - } - return NULL; - -} /* _PR_CreateWindowsProcess */ + if (cmdLine) { + PR_DELETE(cmdLine); + } + if (newEnvp) { + PR_DELETE(newEnvp); + } + if (envBlock) { + PR_DELETE(envBlock); + } + if (proc) { + PR_DELETE(proc); + } + return NULL; +} /* _PR_CreateOS2Process */ PRStatus _PR_DetachOS2Process(PRProcess *process) { - /* This is basically what they did on Windows (CloseHandle) - * but I don't think it will do much on OS/2. A process is - * either created as a child or not. You can't 'detach' it - * later on. + /* On OS/2, a process is either created as a child or not. + * You can't 'detach' it later on. */ - DosClose(process->md.pid); PR_DELETE(process); return PR_SUCCESS; } @@ -506,14 +449,12 @@ _PR_MD_WAKEUP_CPUS( void ) PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRInt32 _MD_GetMemMapAlignment(void) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } @@ -523,21 +464,18 @@ void * _MD_MemMap( PROffset64 offset, PRUint32 len) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRStatus _MD_CloseFileMap(PRFileMap *fmap) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } @@ -577,43 +515,3 @@ unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long fla return rc; } -#ifndef XP_OS2_VACPP - -PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *intp, PRInt32 val) -{ - PRInt32 result; - asm volatile ("lock ; xchg %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); - return result; -} - -PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); - return result + val; -} - -PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); - return result + 1; -} - -PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); - return result - 1; -} - -#endif - diff --git a/pr/src/md/os2/os2poll.c b/pr/src/md/os2/os2poll.c index 12f199f6..6accbfc8 100644 --- a/pr/src/md/os2/os2poll.c +++ b/pr/src/md/os2/os2poll.c @@ -37,54 +37,64 @@ */ #ifdef XP_OS2_EMX - #include <sys/time.h> /* For timeval. */ + #include <sys/time.h> /* For timeval. */ #endif #include "primpl.h" -PRInt32 _PR_MD_PR_POLL( - PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) +#ifndef BSD_SELECT +/* Utility functions called when using OS/2 select */ + +PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count ) +{ + int i; + PRBool isSet = PR_FALSE; + + for( i = start; i < start+count; i++ ) + { + if( socks[i] == osfd ) + isSet = PR_TRUE; + } + + return isSet; +} +#endif + +PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { - PRInt32 osfd; - int maxfd = -1; +#ifdef BSD_SELECT fd_set rd, wt, ex; +#else + int rd, wt, ex; + int* socks; + unsigned long msecs; + int i, j; +#endif PRFileDesc *bottom; PRPollDesc *pd, *epd; - PRInt32 ready, err; - PRThread *me = _PR_MD_CURRENT_THREAD(); - struct timeval tv, *tvp = NULL; + PRInt32 maxfd = -1, ready, err; + PRIntervalTime remaining, elapsed, start; - /* - * 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; +#ifdef BSD_SELECT + struct timeval tv, *tvp = NULL; - if (_PR_PENDING_INTERRUPT(me)) + FD_ZERO(&rd); + FD_ZERO(&wt); + FD_ZERO(&ex); +#else + rd = 0; + wt = 0; + ex = 0; + socks = (int) PR_MALLOC( npds * 3 * sizeof(int) ); + + if (!socks) { - me->flags &= ~_PR_INTERRUPT; - PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } +#endif - /* - ** Is it an empty set? If so, just sleep for the timeout and return - */ - if (0 == npds) - { - PR_Sleep(timeout); - return 0; - } - - remaining = timeout; - start = PR_IntervalNow(); - - FD_ZERO(&rd); - FD_ZERO(&wt); - FD_ZERO(&ex); - - ready = 0; + ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 in_flags_read = 0, in_flags_write = 0; @@ -95,19 +105,17 @@ PRInt32 _PR_MD_PR_POLL( 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); + 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, (PRInt16)(pd->in_flags & ~PR_POLL_READ), - &out_flags_write); + 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))) + if ((0 != (in_flags_read & out_flags_read)) || + (0 != (in_flags_write & out_flags_write))) { - /* this one's ready right now (buffered input) */ + /* this one's ready right now */ if (0 == ready) { /* @@ -128,37 +136,67 @@ PRInt32 _PR_MD_PR_POLL( 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 ((NULL != bottom) && + (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { - osfd = bottom->secret->md.osfd; - if (osfd > maxfd) maxfd = osfd; + 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; +#ifdef BSD_SELECT FD_SET(osfd, &rd); +#else + socks[rd] = osfd; + rd++; +#endif } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; +#ifdef BSD_SELECT FD_SET(osfd, &wt); +#else + socks[npds+wt] = osfd; + wt++; +#endif } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; +#ifdef BSD_SELECT FD_SET(osfd, &rd); +#else + socks[rd] = osfd; + rd++; +#endif } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; +#ifdef BSD_SELECT FD_SET(osfd, &wt); +#else + socks[npds+wt] = osfd; + wt++; +#endif + } + if (pd->in_flags & PR_POLL_EXCEPT) + { +#ifdef BSD_SELECT + FD_SET(osfd, &ex); +#else + socks[npds*2+ex] = osfd; + ex++; +#endif } - if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else @@ -176,36 +214,78 @@ PRInt32 _PR_MD_PR_POLL( } } } + else + { + pd->out_flags = 0; + } } - if (0 != ready) return ready; /* no need to block */ + if (0 != ready) + { +#ifndef BSD_SELECT + PR_Free(socks); +#endif + return ready; /* no need to block */ + } + + remaining = timeout; + start = PR_IntervalNow(); retry: +#ifdef BSD_SELECT 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; + tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); tvp = &tv; } - ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); + ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp); +#else + switch (timeout) + { + case PR_INTERVAL_NO_WAIT: + msecs = 0; + break; + case PR_INTERVAL_NO_TIMEOUT: + msecs = -1; + break; + default: + msecs = PR_IntervalToMilliseconds(remaining); + } + + /* compact array */ + for( i = rd, j = npds; j < npds+wt; i++,j++ ) + socks[i] = socks[j]; + for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ ) + socks[i] = socks[j]; + + ready = os2_select(socks, rd, wt, ex, msecs); +#endif + if (ready == -1 && errno == EINTR) { - if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; - else + if (timeout == PR_INTERVAL_NO_TIMEOUT) + goto retry; + else { - elapsed = (PRIntervalTime) (PR_IntervalNow() - start); - if (elapsed > timeout) ready = 0; /* timed out */ - else + elapsed = (PRIntervalTime) (PR_IntervalNow() - start); + if (elapsed > timeout) + ready = 0; /* timed out */ + else { - remaining = timeout - elapsed; - goto retry; + 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; @@ -214,26 +294,44 @@ retry: 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; +#ifdef BSD_SELECT if (FD_ISSET(osfd, &rd)) +#else + if( IsSocketSet(osfd, socks, 0, rd) ) +#endif { 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; - } + } + +#ifdef BSD_SELECT if (FD_ISSET(osfd, &wt)) +#else + if( IsSocketSet(osfd, socks, rd, wt) ) +#endif { 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; + } + +#ifdef BSD_SELECT + if (FD_ISSET(osfd, &ex)) +#else + if( IsSocketSet(osfd, socks, rd+wt, ex) ) +#endif + { + out_flags |= PR_POLL_EXCEPT; } - if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; } pd->out_flags = out_flags; if (out_flags) ready++; @@ -242,185 +340,40 @@ retry: } else if (ready < 0) { - err = _MD_ERRNO(); - if (err == EBADF) + err = _MD_ERRNO(); + if (err == EBADF) { - /* Find the bad fds */ - ready = 0; - for (pd = pds, epd = pd + npds; pd < epd; pd++) + /* Find the bad fds */ + int optval; + int optlen = sizeof(optval); + 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) + pd->out_flags = 0; + if ((NULL != pd->fd) && (0 != pd->in_flags)) { - PR_ASSERT(_MD_ERRNO() == ENOTSOCK); - if (_MD_ERRNO() == ENOTSOCK) + bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); + if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, + SO_TYPE, (char *) &optval, &optlen) == -1) { - pd->out_flags = PR_POLL_NVAL; - ready++; + PR_ASSERT(sock_errno() == ENOTSOCK); + if (sock_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); + } + PR_ASSERT(ready > 0); } - } - return ready; - } - -#ifdef XP_OS2_EMX -HMTX thread_select_mutex = 0; /* because EMX's select is not thread safe - duh! */ - -typedef struct _thread_select_st { - int nfds; - int isrdfds; - struct _fd_set *readfds; - int iswrfds; - struct _fd_set *writefds; - int isexfds; - struct _fd_set *exceptfds; - int istimeout; - struct timeval timeout; - volatile HEV event; - int result; - int select_errno; - volatile int done; -} *pthread_select_t; - -void _thread_select(void * arg) -{ - pthread_select_t self = arg; - int result, chkstdin; - struct _fd_set readfds; - struct _fd_set writefds; - struct _fd_set exceptfds; - HEV event = self->event; - - chkstdin = (self->isrdfds && FD_ISSET(0,self->readfds))?1:0; - - do { - struct timeval timeout = {0L,0L}; - - - if (self->isrdfds) readfds = *self->readfds; - if (self->iswrfds) writefds = *self->writefds; - if (self->isexfds) exceptfds = *self->exceptfds; - - if (chkstdin) FD_CLR(0,&readfds); - - if (!thread_select_mutex) - DosCreateMutexSem(NULL,&thread_select_mutex,0,1); - else - DosRequestMutexSem(thread_select_mutex,SEM_INDEFINITE_WAIT); - result = select( - self->nfds, - self->isrdfds?&readfds:NULL, - self->iswrfds?&writefds:NULL, - self->isexfds?&exceptfds:NULL, - &timeout); - DosReleaseMutexSem(thread_select_mutex); - - if (chkstdin) { - int charcount = 0, res; - res = ioctl(0,FIONREAD,&charcount); - if (res==0 && charcount>0) FD_SET(0,&readfds); - } - - if (result>0) { - self->done++; - if (self->isrdfds) *self->readfds = readfds; - if (self->iswrfds) *self->writefds = writefds; - if (self->isexfds) *self->exceptfds = exceptfds; - } else - if (result) self->done++; - else DosSleep(1); - - } while (self->event!=0 && self->done==0); - - if (self->event) { - self->select_errno = (result < 0)?errno:0; - self->result = result; - self->done = 3; - DosPostEventSem(event); - } else { - self->done = 3; - free(self); - } - -} - -PRInt32 -_MD_SELECT(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ - pthread_select_t sel; - HEV ev = 0; - HTIMER timer = 0; - int result = 0; - APIRET rc; - unsigned long msecs = SEM_INDEFINITE_WAIT; - - if (timeout) { - if (timeout->tv_sec != 0 || timeout->tv_usec != 0) - msecs = (timeout->tv_sec * 1000L) + (timeout->tv_usec / 1000L); - else - msecs = SEM_IMMEDIATE_RETURN; - }; - - if (!(sel = (pthread_select_t) malloc(sizeof(struct _thread_select_st)))) { - result = -1; - errno = ENOMEM; - } else { - sel->nfds = nfds; - sel->isrdfds = readfds?1:0; - if (sel->isrdfds) sel->readfds = readfds; - sel->iswrfds = writefds?1:0; - if (sel->iswrfds) sel->writefds = writefds; - sel->isexfds = exceptfds?1:0; - if (sel->isexfds) sel->exceptfds = exceptfds; - sel->istimeout = timeout?1:0; - if (sel->istimeout) sel->timeout = *timeout; - - rc = DosCreateEventSem(NULL,&ev,0,FALSE); - - sel->event = ev; - if (msecs == SEM_IMMEDIATE_RETURN) - sel->done = 1; - else - sel->done = 0; - - if (_beginthread(_thread_select,NULL,65536,(void *)sel) == -1) { - result = -1; sel->event = 0; - DosCloseEventSem(ev); - } else { - rc = DosWaitEventSem(ev,msecs); - if ((!sel->done) && (msecs != SEM_IMMEDIATE_RETURN)) { /* Interrupted by other thread or timeout */ - sel->event = 0; - result = 0; - errno = ETIMEDOUT; - - } else { - while (sel->done && sel->done != 3) { - DosSleep(1); - } - sel->event = 0; - result = sel->result; - if (sel->select_errno) errno = sel->select_errno; - free(sel); - } - rc = DosCloseEventSem(ev); - } - } + else + _PR_MD_MAP_SELECT_ERROR(err); + } - return (result); +#ifndef BSD_SELECT + PR_Free(socks); +#endif + return ready; } -#endif diff --git a/pr/src/md/os2/os2sock.c b/pr/src/md/os2/os2sock.c index 529e0e5a..8830a675 100644 --- a/pr/src/md/os2/os2sock.c +++ b/pr/src/md/os2/os2sock.c @@ -46,9 +46,13 @@ #include "primpl.h" #ifdef XP_OS2_EMX - #include <sys/time.h> /* For timeval. */ + #include <sys/time.h> /* For timeval. */ #endif +#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 +#define READ_FD 1 +#define WRITE_FD 2 + void _PR_MD_INIT_IO() { @@ -59,34 +63,19 @@ _PR_MD_INIT_IO() PRInt32 -_PR_MD_SOCKET(int af, int type, int flags) +_PR_MD_SOCKET(int domain, int type, int flags) { - int sock; - PRUint32 one = 1; - PRInt32 rv; - PRInt32 err; - - sock = socket(af, type, flags); + PRInt32 osfd, err; - if (sock == -1 ) - { - int rv = sock_errno(); - soclose(sock); - _PR_MD_MAP_SOCKET_ERROR(rv); - return (PRInt32) -1; - } + osfd = socket(domain, type, flags); - /* - ** Make the socket Non-Blocking - */ - rv = ioctl( sock, FIONBIO, (char *) &one, sizeof(one)); - if ( rv != 0 ) + if (osfd == -1) { err = sock_errno(); - return -1; + _PR_MD_MAP_SOCKET_ERROR(err); } - return (PRInt32)sock; + return(osfd); } /* @@ -96,12 +85,13 @@ _PR_MD_SOCKET(int af, int type, int flags) PRInt32 _MD_CloseSocket(PRInt32 osfd) { - PRInt32 rv = -1; - - rv = soclose((int) osfd ); - if (rv < 0) - _PR_MD_MAP_SOCKET_ERROR(sock_errno()); + PRInt32 rv, err; + rv = soclose(osfd); + if (rv == -1) { + err = sock_errno(); + _PR_MD_MAP_CLOSE_ERROR(err); + } return rv; } @@ -110,263 +100,283 @@ _MD_SocketAvailable(PRFileDesc *fd) { PRInt32 result; - if (ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) { + if (so_ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno()); return -1; } return result; } -PRInt32 -_MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, - PRIntervalTime timeout ) +static PRInt32 +socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout ) { - PRInt32 osfd = fd->secret->md.osfd; - PRInt32 rv, err; + PRInt32 rv = -1; + PRThread *me = _PR_MD_CURRENT_THREAD(); + PRIntervalTime epoch, now, elapsed, remaining; + PRBool wait_for_remaining; + PRInt32 syserror; #ifdef BSD_SELECT - fd_set rd; - struct timeval tv, *tvp; - - FD_ZERO(&rd); - FD_SET(osfd, &rd); + struct timeval tv; + fd_set rd_wr; #else int socks[1]; - socks[0] = osfd; + long lTimeout; #endif - if (timeout == PR_INTERVAL_NO_TIMEOUT) - { - while ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1) - { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { + + 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. + */ #ifdef BSD_SELECT - if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL,NULL)) == -1) { + 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 = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); + else + rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); #else - if ((rv = _MD_SELECT(socks, 1, 0, 0, -1)) == -1) { -#endif - _PR_MD_MAP_SELECT_ERROR(sock_errno()); + lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; + do { + socks[0] = osfd; + if (fd_type == READ_FD) + rv = os2_select(socks, 1, 0, 0, lTimeout); + else + rv = os2_select(socks, 0, 1, 0, lTimeout); +#endif + if (rv == -1 && (syserror = sock_errno()) != EINTR) { + _PR_MD_MAP_SELECT_ERROR(syserror); 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, (int *) rlen)) == -1) - { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - } - else - { - _PR_MD_MAP_ACCEPT_ERROR(err); - } - } - return(rv); - } - else - { -retry: - if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1) - { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { + } + 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; +#ifdef BSD_SELECT + FD_ZERO(&rd_wr); +#endif + do { + /* + * We block in select for at most + * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, + * so that there is an upper limit on the delay + * before the interrupt bit is checked. + */ #ifdef BSD_SELECT - tv.tv_sec = PR_IntervalToSeconds(timeout); - tv.tv_usec = PR_IntervalToMicroseconds(timeout - PR_SecondsToInterval(tv.tv_sec)); - tvp = &tv; - rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp); + wait_for_remaining = PR_TRUE; + tv.tv_sec = PR_IntervalToSeconds(remaining); + if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { + wait_for_remaining = PR_FALSE; + tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; + tv.tv_usec = 0; + } else { + tv.tv_usec = PR_IntervalToMicroseconds( + remaining - + PR_SecondsToInterval(tv.tv_sec)); + } + FD_SET(osfd, &rd_wr); + if (fd_type == READ_FD) + rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); + else + rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); #else - long lTimeout = PR_IntervalToMilliseconds(timeout); - rv = _MD_SELECT(socks, 1, 0, 0, lTimeout); + wait_for_remaining = PR_TRUE; + lTimeout = PR_IntervalToMilliseconds(remaining); + if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { + wait_for_remaining = PR_FALSE; + lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; + } + socks[0] = osfd; + if (fd_type == READ_FD) + rv = os2_select(socks, 1, 0, 0, lTimeout); + else + rv = os2_select(socks, 0, 1, 0, lTimeout); #endif - if (rv > 0) { - goto retry; - } - else if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); + /* + * we don't consider EINTR a real error + */ + if (rv == -1 && (syserror = sock_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; - } else { - _PR_MD_MAP_SELECT_ERROR(sock_errno()); + break; } - } else { - _PR_MD_MAP_ACCEPT_ERROR(err); - } + /* + * We loop again if 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 select timed out, we know how much time + * we spent in blocking, so we can avoid a + * PR_IntervalNow() call. + */ + if (rv == 0) { + if (wait_for_remaining) { + now += remaining; + } else { +#ifdef BSD_SELECT + now += PR_SecondsToInterval(tv.tv_sec) + + PR_MicrosecondsToInterval(tv.tv_usec); +#else + now += PR_MillisecondsToInterval(lTimeout); +#endif + } + } else { + now = PR_IntervalNow(); + } + elapsed = (PRIntervalTime) (now - epoch); + if (elapsed >= timeout) { + PR_SetError(PR_IO_TIMEOUT_ERROR, 0); + rv = -1; + break; + } else { + remaining = timeout - elapsed; + } + } + } while (rv == 0 || (rv == -1 && syserror == EINTR)); + break; } - } return(rv); -} /* end _MD_Accept() */ +} +PRInt32 +_MD_Accept(PRFileDesc *fd, PRNetAddr *addr, + 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, (int*)addrlen)) == -1) + { + err = sock_errno(); + if ((err == EWOULDBLOCK) || (err == ECONNABORTED)) + { + if (fd->secret->nonblocking) { + break; + } + 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: + return(rv); +} PRInt32 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { + PRInt32 rv, err; + PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 osfd = fd->secret->md.osfd; - PRInt32 rv; - int err, len; -#ifdef BSD_SELECT -#ifdef XP_OS2//_VACPP - fd_set wd; -#else - fd_set wd, ex; -#endif #vacpp - struct timeval tv, *tvp; -#else - int socks[1]; - long lTimeout = -1; -#endif - if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) + /* + * We initiate the connection setup by making a nonblocking connect() + * call. If the connect() call fails, there are two cases we handle + * specially: + * 1. The connect() call was interrupted by a signal. In this case + * we simply retry connect(). + * 2. The NSPR socket is nonblocking and connect() fails with + * EINPROGRESS. We first wait until the socket becomes writable. + * Then we try to find out whether the connection setup succeeded + * or failed. + */ + +retry: + if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) { err = sock_errno(); - if ((!fd->secret->nonblocking) && ((err == EINPROGRESS) || (err == EWOULDBLOCK))) - { -#ifdef BSD_SELECT - 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 (err == EINTR) { + if (_PR_PENDING_INTERRUPT(me)) { + me->flags &= ~_PR_INTERRUPT; + PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); + return -1; } + goto retry; + } - FD_ZERO(&wd); - FD_SET(osfd, &wd); -#ifdef XP_OS2//_VACPP - rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp); -#else - FD_ZERO(&ex); - FD_SET(osfd, &ex); - rv = _MD_SELECT(osfd + 1, NULL, &wd, &ex, tvp); -#endif #vacpp -#else #!bsd_select - if (timeout == PR_INTERVAL_NO_TIMEOUT) - lTimeout = -1; - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); + if (!fd->secret->nonblocking && (err == EINPROGRESS)) + { + /* + * socket_io_wait() may return -1 or 1. + */ + + rv = socket_io_wait(osfd, WRITE_FD, timeout); + if (rv == -1) { + return -1; } - - socks[0] = osfd; -#ifdef XP_OS2//_VACPP - rv = _MD_SELECT(socks, 0, 1, 0, lTimeout); -#else - rv = _MD_SELECT(socks, 0, 1, 1, lTimeout); -#endif #vacpp -#endif - if (rv > 0) - { -#ifdef BSD_SELECT -#ifdef XP_OS2//_VACPP - if (FD_ISSET(osfd, &wd)) - { - //DosSleep(0); - len = sizeof(err); - if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, - (char *) &err, &len) < 0) - { - _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno()); - return -1; - } - if (err != 0) - { - _PR_MD_MAP_CONNECT_ERROR(err); - return -1; - } - else - return 0; /* it's connected */ - } - else - return -1; -#else - if (FD_ISSET(osfd, &ex)) - { - DosSleep(0); - len = sizeof(err); - if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, - (char *) &err, &len) < 0) - { - _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno()); - return -1; - } - if (err != 0) - _PR_MD_MAP_CONNECT_ERROR(err); - else - PR_SetError(PR_UNKNOWN_ERROR, 0); - return -1; - } - if (FD_ISSET(osfd, &wd)) - { - /* it's connected */ - return 0; - } -#endif #vacpp -#else #!bsd_select - if (socks[0] == osfd) - { - len = sizeof(err); - if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, - (char *) &err, &len) < 0) - { - _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno()); - return -1; - } - - if (err != 0) - { - _PR_MD_MAP_CONNECT_ERROR(err); - return -1; - } - else - return 0; /* it's connected */ - } - else - return -1; -#endif + PR_ASSERT(rv == 1); + if (_PR_PENDING_INTERRUPT(me)) { + me->flags &= ~_PR_INTERRUPT; + PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); + return -1; } - else if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - return(-1); - } else if (rv < 0) - { - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - return(-1); + err = _MD_os2_get_nonblocking_connect_error(osfd); + if (err != 0) { + _PR_MD_MAP_CONNECT_ERROR(err); + return -1; } - } + return 0; + } + _PR_MD_MAP_CONNECT_ERROR(err); } - return rv; -} + return rv; +} /* _MD_connect */ PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { - PRInt32 rv; - - rv = bind(fd->secret->md.osfd, (struct sockaddr*) &(addr->inet), addrlen); + PRInt32 rv, err; + rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_BIND_ERROR(err); + } + return(rv); +} - if (rv == -1) { - _PR_MD_MAP_BIND_ERROR(sock_errno()); - return -1; - } - return 0; +PRInt32 +_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) +{ + PRInt32 rv, err; + rv = listen(fd->secret->md.osfd, backlog); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_DEFAULT_ERROR(err); + } + return(rv); } @@ -376,70 +386,27 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; -#ifdef BSD_SELECT - struct timeval tv, *tvp; - fd_set rd; -#else - int socks[1]; - long lTimeout = -1; -#endif - int osflags; + PRThread *me = _PR_MD_CURRENT_THREAD(); - if (0 == flags) { - osflags = 0; - } else { - PR_ASSERT(PR_MSG_PEEK == flags); - osflags = MSG_PEEK; - } - while ((rv = recv( osfd, buf, amount, osflags)) == -1) + while ((rv = recv(osfd,buf,amount,flags)) == -1) { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { -#ifdef BSD_SELECT - FD_ZERO(&rd); - FD_SET(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 = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1) -#else - socks[0] = osfd; - if (timeout == PR_INTERVAL_NO_TIMEOUT) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1) -#endif - { - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - return -1; - } - else if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - rv = -1; + err = sock_errno(); + if ((err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { break; } - } - else - { - _PR_MD_MAP_RECV_ERROR(err); + if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) + goto done; + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ + continue; + } else { break; } - } /* end while() */ + } + if (rv < 0) { + _PR_MD_MAP_RECV_ERROR(err); + } +done: return(rv); } @@ -449,108 +416,42 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; -#ifdef BSD_SELECT - struct timeval tv, *tvp; - fd_set wd; -#else - int socks[1]; - long lTimeout = -1; -#endif - PRInt32 bytesSent = 0; + PRThread *me = _PR_MD_CURRENT_THREAD(); - while(bytesSent < amount ) + while ((rv = send(osfd,buf,amount,flags)) == -1) { - while ((rv = send( osfd, (char *) buf, amount, 0 )) == -1) - { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { -#ifdef BSD_SELECT - 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(osfd, &wd); - if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL,tvp)) == -1) { -#else - if ( timeout == PR_INTERVAL_NO_TIMEOUT ) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - socks[0] = osfd; - if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) { -#endif - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - break; - } - if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - return -1; - } - } - else { - _PR_MD_MAP_SEND_ERROR(err); - return -1; + err = sock_errno(); + if ((err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; } - } - bytesSent += rv; - if (fd->secret->nonblocking) - { + 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) && (bytesSent < amount )) - { -#ifdef BSD_SELECT - 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(osfd, &wd); - if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL,tvp)) == -1) { -#else - if ( timeout == PR_INTERVAL_NO_TIMEOUT ) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - socks[0] = osfd; - if ((rv = _MD_SELECT(socks, 0, 1, 0,lTimeout)) == -1) { -#endif - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - break; - } - if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - return -1; - } + } + + /* + * 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 (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { + rv = -1; + goto done; } } - return bytesSent; + if (rv < 0) { + _PR_MD_MAP_SEND_ERROR(err); + } +done: + return(rv); } PRInt32 @@ -559,109 +460,29 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; - PRInt32 bytesSent = 0; -#ifdef BSD_SELECT - struct timeval tv, *tvp; - fd_set wd; -#else - int socks[1]; - long lTimeout = -1; -#endif - - while(bytesSent < amount) + PRThread *me = _PR_MD_CURRENT_THREAD(); + while ((rv = sendto(osfd, buf, amount, flags, + (struct sockaddr *) addr, addrlen)) == -1) { - while ((rv = sendto( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr, - addrlen)) == -1) - { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { -#ifdef BSD_SELECT - 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(osfd, &wd); - if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp)) == -1) { -#else - if ( timeout == PR_INTERVAL_NO_TIMEOUT ) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - socks[0] = osfd; - if ((rv = _MD_SELECT(socks, 0, 1, 0, lTimeout)) == -1) { -#endif - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - break; - } - if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - return -1; - } - } - else { - _PR_MD_MAP_SENDTO_ERROR(err); - return -1; - } - } - bytesSent += rv; - if (fd->secret->nonblocking) - { - break; - } - if ((rv >= 0) && (bytesSent < amount )) + err = sock_errno(); + if ((err == EWOULDBLOCK)) { -#ifdef BSD_SELECT - 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(osfd, &wd); - if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL, tvp)) == -1) { -#else - if ( timeout == PR_INTERVAL_NO_TIMEOUT ) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - socks[0] = osfd; - if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) { -#endif - _PR_MD_MAP_SELECT_ERROR(sock_errno()); + if (fd->secret->nonblocking) { break; } - if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - return -1; - } + if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) + goto done; + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ + continue; + } else { + break; } } - return bytesSent; + if (rv < 0) { + _PR_MD_MAP_SENDTO_ERROR(err); + } +done: + return(rv); } PRInt32 @@ -670,103 +491,86 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; - PRUint32 addrlen_temp = *addrlen; -#ifdef BSD_SELECT - struct timeval tv, *tvp; - fd_set rd; -#else - int socks[1]; - long lTimeout = -1; -#endif + PRThread *me = _PR_MD_CURRENT_THREAD(); - while ((rv = recvfrom( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr, - (int *) addrlen)) == -1) + while( (*addrlen = PR_NETADDR_SIZE(addr)), + ((rv = recvfrom(osfd, buf, amount, flags, + (struct sockaddr *) addr, (int *)addrlen)) == -1)) { - if (((err = sock_errno()) == EWOULDBLOCK) - && (!fd->secret->nonblocking)) - { -#ifdef BSD_SELECT - 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(&rd); - FD_SET(osfd, &rd); - if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1) -#else - if (timeout == PR_INTERVAL_NO_TIMEOUT) - { - lTimeout = -1; - } - else - { - lTimeout = PR_IntervalToMilliseconds(timeout); - } - socks[0] = osfd; - if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1) -#endif - { - _PR_MD_MAP_SELECT_ERROR(sock_errno()); - return -1; - } else if (rv == 0) - { - PR_SetError(PR_IO_TIMEOUT_ERROR, 0); - rv = -1; + err = sock_errno(); + if ((err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { break; } - - /* recvfrom blows this value away if it fails first time */ - *addrlen = addrlen_temp; - } - else - { - _PR_MD_MAP_RECVFROM_ERROR(err); + 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: return(rv); } PRInt32 -_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) +_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, + PRIntervalTime timeout) { - int index; - int sent = 0; - int rv; + PRInt32 rv, err; + PRThread *me = _PR_MD_CURRENT_THREAD(); + PRInt32 index, amount = 0; + PRInt32 osfd = fd->secret->md.osfd; - for (index=0; index < iov_size; index++) - { - rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout); - if (rv > 0) - sent += rv; - if ( rv != iov[index].iov_len ) - { - if (rv < 0) - { - if (fd->secret->nonblocking - && (PR_GetError() == PR_WOULD_BLOCK_ERROR) - && (sent > 0)) - { - return sent; - } - else - { - return -1; - } + /* + * 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 = so_writev(osfd, (const struct iovec*)iov, iov_size)) == -1) { + err = sock_errno(); + if ((err == EWOULDBLOCK)) { + if (fd->secret->nonblocking) { + break; } - /* Only a nonblocking socket can have partial sends */ - PR_ASSERT(fd->secret->nonblocking); - return sent; + if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) + goto done; + } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ + continue; + } else { + break; } } - return sent; + + /* + * 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 (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { + rv = -1; + goto done; + } + } + if (rv < 0) { + _PR_MD_MAP_WRITEV_ERROR(err); + } +done: + return(rv); } PRInt32 @@ -780,64 +584,92 @@ _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) return rv; } +PRInt32 +_PR_MD_SOCKETPAIR(int af, int type, int flags, 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; +} + + PRStatus -_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) +_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { - PRInt32 rv; + PRInt32 rv, err; - rv = getsockname((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len); - if (rv==0) - return PR_SUCCESS; - else { - _PR_MD_MAP_GETSOCKNAME_ERROR(sock_errno()); - return PR_FAILURE; + rv = getsockname(fd->secret->md.osfd, + (struct sockaddr *) addr, (int *)addrlen); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_GETSOCKNAME_ERROR(err); } + return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus -_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) +_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { - PRInt32 rv; + PRInt32 rv, err; - rv = getpeername((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len); - if (rv==0) - return PR_SUCCESS; - else { - _PR_MD_MAP_GETPEERNAME_ERROR(sock_errno()); - return PR_FAILURE; + rv = getpeername(fd->secret->md.osfd, + (struct sockaddr *) addr, (int *)addrlen); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_GETPEERNAME_ERROR(err); } + return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus -_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) +_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, + char* optval, PRInt32* optlen) { - PRInt32 rv; + PRInt32 rv, err; - rv = getsockopt((int)fd->secret->md.osfd, level, optname, optval, optlen); - if (rv==0) - return PR_SUCCESS; - else { - _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno()); - return PR_FAILURE; + rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_GETSOCKOPT_ERROR(err); } + return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus -_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) +_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, + const char* optval, PRInt32 optlen) { - PRInt32 rv; + PRInt32 rv, err; - rv = setsockopt((int)fd->secret->md.osfd, level, optname, (char *) optval, optlen); - if (rv==0) - return PR_SUCCESS; - else { - _PR_MD_MAP_SETSOCKOPT_ERROR(sock_errno()); - return PR_FAILURE; + rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); + if (rv < 0) { + err = sock_errno(); + _PR_MD_MAP_SETSOCKOPT_ERROR(err); } + return rv==0?PR_SUCCESS:PR_FAILURE; } void -_MD_MakeNonblock(PRFileDesc *f) +_MD_MakeNonblock(PRFileDesc *fd) { - return; /* do nothing! */ + PRInt32 osfd = fd->secret->md.osfd; + PRInt32 err; + PRUint32 one = 1; + + if (osfd <= 2) { + /* Don't mess around with stdin, stdout or stderr */ + return; + } + + err = so_ioctl( osfd, FIONBIO, (char *) &one, sizeof(one)); + if ( err != 0 ) + { + err = sock_errno(); + _PR_MD_MAP_SOCKET_ERROR(err); + } } diff --git a/pr/src/md/os2/os2thred.c b/pr/src/md/os2/os2thred.c index d64ae0b9..45613573 100644 --- a/pr/src/md/os2/os2thred.c +++ b/pr/src/md/os2/os2thred.c @@ -43,6 +43,8 @@ #include <signal.h> #endif +#include <float.h> + /* --- globals ------------------------------------------------ */ _NSPR_TLS* pThreadLocalStorage = 0; _PRInterruptTable _pr_interruptTable[] = { { 0 } }; @@ -88,19 +90,92 @@ _pr_SetThreadMDHandle(PRThread *thread) thread->md.handle = ptib->tib_ptib2->tib2_ultid; } +/* On OS/2, some system function calls seem to change the FPU control word, + * such that we crash with a floating underflow exception. The FIX_FPU() call + * in jsnum.c does not always work, as sometimes FIX_FPU() is called BEFORE the + * OS/2 system call that horks the FPU control word. So, we set an exception + * handler that covers any floating point exceptions and resets the FPU CW to + * the required value. + */ +static ULONG +_System OS2_FloatExcpHandler(PEXCEPTIONREPORTRECORD p1, + PEXCEPTIONREGISTRATIONRECORD p2, + PCONTEXTRECORD p3, + PVOID pv) +{ +#ifdef DEBUG_pedemonte + printf("Entering exception handler; ExceptionNum = %x\n", p1->ExceptionNum); + switch(p1->ExceptionNum) { + case XCPT_FLOAT_DENORMAL_OPERAND: + printf("got XCPT_FLOAT_DENORMAL_OPERAND\n"); + break; + case XCPT_FLOAT_DIVIDE_BY_ZERO: + printf("got XCPT_FLOAT_DIVIDE_BY_ZERO\n"); + break; + case XCPT_FLOAT_INEXACT_RESULT: + printf("got XCPT_FLOAT_INEXACT_RESULT\n"); + break; + case XCPT_FLOAT_INVALID_OPERATION: + printf("got XCPT_FLOAT_INVALID_OPERATION\n"); + break; + case XCPT_FLOAT_OVERFLOW: + printf("got XCPT_FLOAT_OVERFLOW\n"); + break; + case XCPT_FLOAT_STACK_CHECK: + printf("got XCPT_FLOAT_STACK_CHECK\n"); + break; + case XCPT_FLOAT_UNDERFLOW: + printf("got XCPT_FLOAT_UNDERFLOW\n"); + break; + } +#endif + + switch(p1->ExceptionNum) { + case XCPT_FLOAT_DENORMAL_OPERAND: + case XCPT_FLOAT_DIVIDE_BY_ZERO: + case XCPT_FLOAT_INEXACT_RESULT: + case XCPT_FLOAT_INVALID_OPERATION: + case XCPT_FLOAT_OVERFLOW: + case XCPT_FLOAT_STACK_CHECK: + case XCPT_FLOAT_UNDERFLOW: + { + unsigned cw = p3->ctx_env[0]; + if ((cw & MCW_EM) != MCW_EM) { + /* Mask out all floating point exceptions */ + p3->ctx_env[0] |= MCW_EM; + /* Following two lines set precision to 53 bit mantissa. See jsnum.c */ + p3->ctx_env[0] &= ~MCW_PC; + p3->ctx_env[0] |= PC_53; + return XCPT_CONTINUE_EXECUTION; + } + } + } + return XCPT_CONTINUE_SEARCH; +} + +PR_IMPLEMENT(void) +PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg) +{ + /* setup the exception handler for the thread */ + APIRET rv; + excpreg->ExceptionHandler = OS2_FloatExcpHandler; + excpreg->prev_structure = NULL; + rv = DosSetExceptionHandler(excpreg); + PR_ASSERT(rv == NO_ERROR); +} + +PR_IMPLEMENT(void) +PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg) +{ + /* unset exception handler */ + APIRET rv = DosUnsetExceptionHandler(excpreg); + PR_ASSERT(rv == NO_ERROR); +} PRStatus _PR_MD_INIT_THREAD(PRThread *thread) { APIRET rv; -#ifdef XP_OS2_EMX - /* disable SIGPIPE */ - struct sigaction sa; - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; - sigemptyset( &sa.sa_mask); - sigaction( SIGPIPE, &sa, NULL); -#endif if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { _pr_SetThreadMDHandle(thread); @@ -111,6 +186,29 @@ _PR_MD_INIT_THREAD(PRThread *thread) return (rv == NO_ERROR) ? PR_SUCCESS : PR_FAILURE; } +typedef struct param_store +{ + void (*start)(void *); + PRThread* thread; +} PARAMSTORE; + +/* This is a small intermediate function that sets/unsets the exception + handler before calling the initial thread function */ +static void +ExcpStartFunc(void* arg) +{ + EXCEPTIONREGISTRATIONRECORD excpreg; + PARAMSTORE params, *pParams = arg; + + PR_OS2_SetFloatExcpHandler(&excpreg); + + params = *pParams; + PR_Free(pParams); + params.start(params.thread); + + PR_OS2_UnsetFloatExcpHandler(&excpreg); +} + PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), @@ -119,15 +217,25 @@ _PR_MD_CREATE_THREAD(PRThread *thread, PRThreadState state, PRUint32 stackSize) { - thread->md.handle = thread->id = (TID) _beginthread( - (void(* _Optlink)(void*))start, - NULL, - thread->stack->stackSize, - thread); + PARAMSTORE* params = PR_Malloc(sizeof(PARAMSTORE)); + params->start = start; + params->thread = thread; + thread->md.handle = thread->id = (TID) _beginthread(ExcpStartFunc, + NULL, + thread->stack->stackSize, + params); if(thread->md.handle == -1) { return PR_FAILURE; } - _PR_MD_SET_PRIORITY(&(thread->md), priority); + + /* + * On OS/2, a thread is created with a thread priority of + * THREAD_PRIORITY_NORMAL + */ + + if (priority != PR_PRIORITY_NORMAL) { + _PR_MD_SET_PRIORITY(&(thread->md), priority); + } return PR_SUCCESS; } @@ -270,3 +378,19 @@ _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/os2/os2vaclegacy.s b/pr/src/md/os2/os2vaclegacy.s new file mode 100644 index 00000000..106df3de --- /dev/null +++ b/pr/src/md/os2/os2vaclegacy.s @@ -0,0 +1,74 @@ +/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/ +/ The contents of this file are subject to the Mozilla Public +/ License Version 1.1 (the "License"); you may not use this file +/ except in compliance with the License. You may obtain a copy of +/ the License at http://www.mozilla.org/MPL/ +/ +/ Software distributed under the License is distributed on an "AS +/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +/ implied. See the License for the specific language governing +/ rights and limitations under the License. +/ +/ The Original Code is the Netscape Portable Runtime (NSPR). +/ +/ The Initial Developer of the Original Code is InnoTek +/ Systemberatung GmbH. +/ Portions created by the Initial Developer are Copyright (C) 2003 +/ the Initial Developer. All Rights Reserved. +/ +/ Contributor(s): +/ InnoTek Systemberatung GmbH / Knut St. Osmundsen +/ +/ Alternatively, the contents of this file may be used under the +/ terms of the GNU General Public License Version 2 or later (the +/ "GPL"), in which case the provisions of the GPL are applicable +/ instead of those above. If you wish to allow use of your +/ version of this file only under the terms of the GPL and not to +/ allow others to use your version of this file under the MPL, +/ indicate your decision by deleting the provisions above and +/ replace them with the notice and other provisions required by +/ the GPL. If you do not delete the provisions above, a recipient +/ may use your version of this file under either the MPL or the +/ GPL. +/ + + .text + .align 4 + .globl PR_NewMonitor +PR_NewMonitor: + jmp _PR_NewMonitor + + .align 4 + .globl PR_EnterMonitor +PR_EnterMonitor: + mov %eax, 4(%esp) + jmp _PR_EnterMonitor + + .align 4 + .globl PR_ExitMonitor +PR_ExitMonitor: + mov %eax, 4(%esp) + jmp _PR_ExitMonitor + + + + .align 4 + .globl PR_AttachThread +PR_AttachThread: + mov %eax, 4(%esp) + mov %edx, 8(%esp) + mov %ecx, 12(%esp) + jmp _PR_AttachThread + + .align 4 + .globl PR_DetachThread +PR_DetachThread: + jmp _PR_DetachThread + + .align 4 + .globl PR_GetCurrentThread +PR_GetCurrentThread: + jmp _PR_GetCurrentThread + + diff --git a/pr/src/md/os2/os2vacpp.asm b/pr/src/md/os2/os2vacpp.asm index 2581323b..6b49e407 100644 --- a/pr/src/md/os2/os2vacpp.asm +++ b/pr/src/md/os2/os2vacpp.asm @@ -30,59 +30,230 @@ COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*- GPL. Windows uses inline assembly for their atomic functions, so we have - created an assembly file for VACPP on OS/2 + created an assembly file for VACPP on OS/2. + + This assembly file also contains an implementation of RAM semaphores. + + Notes: + The ulTIDPID element of the RAMSEM structure is overloaded in the 386 + implementation to hold the TID:PID in the lower 31 bits and the lock + bit in the high bit | + page ,132 .486P - .MODEL FLAT, OPTLINK - .STACK + ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT + + EXTRN Dos32PostEventSem:PROC + EXTRN Dos32WaitEventSem:PROC + EXTRN Dos32ResetEventSem:PROC + +ramsem STRUC + ramsem_ulTIDPID DD ? + ramsem_hevSem DD ? + ramsem_cLocks DD ? + ramsem_cWaiting DW ? + ramsem_cPosts DW ? +ramsem ENDS + +ERROR_SEM_TIMEOUT equ 121 +ERROR_NOT_OWNER equ 288 +SEM_RELEASE_UNOWNED equ 1 +SEM_RELEASE_ALL equ 2 +TS_LOCKBIT equ 31 + + +DATA SEGMENT DWORD USE32 PUBLIC 'DATA' + + EXTRN plisCurrent:DWORD + +DATA ENDS + +CODE32 SEGMENT USE32 PUBLIC 'CODE' + + PUBLIC SemRequest486 + PUBLIC SemReleasex86 + + PUBLIC _PR_MD_ATOMIC_SET + PUBLIC _PR_MD_ATOMIC_ADD + PUBLIC _PR_MD_ATOMIC_INCREMENT + PUBLIC _PR_MD_ATOMIC_DECREMENT + +;;;--------------------------------------------------------------------------- +;;; APIRET _Optlink SemRequest(PRAMSEM pramsem, ULONG ulTimeout); +;;; +;;; Registers: +;;; EAX - packed TID:PID word +;;; ECX - address of RAMSEM structure +;;; EDX - length of timeout in milli-seconds +;;;--------------------------------------------------------------------------- + + ALIGN 10H +SemRequest486 PROC + push ebx ; Save ebx (volatile) + mov ecx, eax ; PRAMSEM must be in ecx, + ; not eax, for cmpxchg + + mov ebx, dword ptr [plisCurrent] + mov eax, dword ptr [ebx+4] ; Place thread id in high + ; word, process id in low + mov ax, word ptr [ebx] ; word + mov ebx,eax + +req486_test: + xor eax,eax + cmp (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx ; If we own the sem, just + jz short req486_inc_exit ; increment the use count + + lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag + +; lock ; Uncomment for SMP + DB 0F0h +; cmpxchg (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx +; (byte 3 is the offset of ulProcessThread into the RAMSEM structure) + DB 00Fh + DB 0B1h + DB 019h + jnz short req486_sleep + +req486_inc_exit: + lock inc (ramsem PTR [ecx]).ramsem_cLocks + +req486_exit: + pop ebx ; Restore ebx + ret + +req486_sleep: + push ecx ; Save ecx (volatile) + push edx ; Save edx (volatile) + push edx ; timeout + push (ramsem PTR [ecx]).ramsem_hevSem + call Dos32WaitEventSem + add esp, 8 + pop edx ; restore edx + pop ecx ; restore ecx + or eax, eax + jne req486_exit ; Exit, if error - .CODE + push ecx ; Save ecx (volatile) + push edx ; Save edx (volatile) + sub esp, 4 ; Use stack space for + push esp ; dummy pulPostCt + push (ramsem PTR [ecx]).ramsem_hevSem + call Dos32ResetEventSem + add esp, 12 + pop edx ; restore edx + pop ecx ; restore ecx + jmp req486_test ; Retry the semaphore + +SemRequest486 ENDP + +;;;--------------------------------------------------------------------- +;;; APIRET _Optlink SemReleasex86(PRAMSEM pramsem, ULONG flFlags); +;;; +;;; Registers: +;;; EAX - address of RAMSEM structure +;;; ECX - temporary variable +;;; EDX - flags +;;;--------------------------------------------------------------------- + + ALIGN 10H +SemReleasex86 PROC + test edx, SEM_RELEASE_UNOWNED ; If set, don't bother + jnz short rel_ownerok ; getting/checking PID/TID + + push ebx ; Save ebx (volatile) + mov ebx, dword ptr [plisCurrent] + mov ecx, dword ptr [ebx+4] ; Place thread id in high + ; word, process id in low + mov cx, word ptr [ebx] ; word + pop ebx ; Restore ebx + + sub ecx, (ramsem PTR [eax]).ramsem_ulTIDPID ; This thread the owner? + shl ecx,1 ; Don't compare top bit + jnz short rel_notowner + +rel_ownerok: + test edx, SEM_RELEASE_ALL + jnz short rel_clear + + lock dec (ramsem PTR [eax]).ramsem_cLocks + jnz short rel_exit + +rel_disown: + mov (ramsem PTR [eax]).ramsem_ulTIDPID, 0 + + lock inc (ramsem PTR [eax]).ramsem_cPosts + mov cx, (ramsem PTR [eax]).ramsem_cWaiting + cmp (ramsem PTR [eax]).ramsem_cPosts, cx + jne short rel_post + +rel_exit: + xor eax, eax + ret + +rel_clear: + lock mov (ramsem PTR [eax]).ramsem_cLocks,0 + jmp rel_disown + +rel_notowner: + mov eax, ERROR_NOT_OWNER + ret + +rel_post: + mov (ramsem PTR [eax]).ramsem_cPosts, cx + push (ramsem PTR [eax]).ramsem_hevSem + call Dos32PostEventSem + add esp,4 + xor eax,eax + ret +SemReleasex86 ENDP ;;;--------------------------------------------------------------------- ;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval) ;;;--------------------------------------------------------------------- -_PR_MD_ATOMIC_SET PROC OPTLINK EXPORT - lock xchg dword ptr [eax],edx + ALIGN 10H +_PR_MD_ATOMIC_SET proc + lock xchg dword ptr [eax],edx mov eax, edx; - ret _PR_MD_ATOMIC_SET endp ;;;--------------------------------------------------------------------- ;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val) ;;;--------------------------------------------------------------------- -_PR_MD_ATOMIC_ADD PROC OPTLINK EXPORT + ALIGN 10H +_PR_MD_ATOMIC_ADD proc mov ecx, edx lock xadd dword ptr [eax], edx mov eax, edx add eax, ecx - ret _PR_MD_ATOMIC_ADD endp ;;;--------------------------------------------------------------------- ;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val) ;;;--------------------------------------------------------------------- -_PR_MD_ATOMIC_INCREMENT PROC OPTLINK EXPORT + ALIGN 10H +_PR_MD_ATOMIC_INCREMENT proc mov edx, 1 lock xadd dword ptr [eax], edx mov eax, edx inc eax - ret _PR_MD_ATOMIC_INCREMENT endp ;;;--------------------------------------------------------------------- ;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val) ;;;--------------------------------------------------------------------- -_PR_MD_ATOMIC_DECREMENT PROC OPTLINK EXPORT + ALIGN 10H +_PR_MD_ATOMIC_DECREMENT proc mov edx, 0ffffffffh lock xadd dword ptr [eax], edx mov eax, edx dec eax - ret _PR_MD_ATOMIC_DECREMENT endp - END +CODE32 ENDS +END diff --git a/pr/src/md/unix/Makefile.in b/pr/src/md/unix/Makefile.in index aa78f21b..8c5dfe80 100644 --- a/pr/src/md/unix/Makefile.in +++ b/pr/src/md/unix/Makefile.in @@ -76,6 +76,8 @@ ifeq ($(OS_ARCH),SunOS) ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX))) TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY) RELEASE_LIBS = $(SHARED_LIBRARY) + RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)/cpu/sparcv8plus + lib_subdir = cpu/sparcv8plus endif endif endif @@ -98,8 +100,24 @@ $(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES) /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v9 $< else $(SHARED_LIBRARY): $(ULTRASPARC_ASOBJS) - $(LD) -G -z text -o $@ $(ULTRASPARC_ASOBJS) - $(INSTALL) -m 444 $@ $(dist_libdir) + $(LD) -G -z text -z endfiltee -o $@ $(ULTRASPARC_ASOBJS) + $(INSTALL) -m 444 $@ $(dist_libdir)/cpu/sparcv8plus + $(INSTALL) -m 444 $@ $(dist_bindir)/cpu/sparcv8plus +# +# The -f $(ORIGIN)/... linker flag uses the real file, after symbolic links +# are resolved, as the origin. If NSDISTMODE is not "copy", libnspr4.so +# will be installed as a symbolic link in $(dist_libdir), pointing to the +# real libnspr4.so file in pr/src. Therefore we need to install an +# additional copy of libnspr_flt4.so in pr/src/cpu/sparcv8plus. +# +ifneq ($(NSDISTMODE),copy) + $(INSTALL) -m 444 $@ ../../cpu/sparcv8plus +endif + +ifneq ($(NSDISTMODE),copy) +clobber realclean clobber_all distclean:: + rm -rf ../../cpu +endif $(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES) /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v8plus $< diff --git a/pr/src/md/unix/darwin.c b/pr/src/md/unix/darwin.c index 43988b8d..82208c61 100644 --- a/pr/src/md/unix/darwin.c +++ b/pr/src/md/unix/darwin.c @@ -82,11 +82,11 @@ _MD_WAKEUP_WAITER(PRThread *thread) return PR_SUCCESS; } -/* These functions should not be called for Rhapsody */ +/* These functions should not be called for Darwin */ void _MD_YIELD(void) { - PR_NOT_REACHED("_MD_YIELD should not be called for Rhapsody."); + PR_NOT_REACHED("_MD_YIELD should not be called for Darwin."); } PRStatus @@ -98,37 +98,10 @@ _MD_CREATE_THREAD( PRThreadState state, PRUint32 stackSize) { - PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Rhapsody."); + PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Darwin."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ -#if defined(_PR_PTHREADS) - -/* -** Stubs for unimplemented functions -*/ - -int pthread_condattr_init(pthread_condattr_t *attr) -{ - return 0; -} - -int pthread_kill(pthread_t thread, int sig) -{ - return ENOSYS; -} - -typedef struct siginfo_t siginfo_t; - -int sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec *timeout) -{ - errno = ENOSYS; - return -1; -} - -#endif /* _PR_PTHREADS */ - /* darwin.c */ diff --git a/pr/src/md/unix/irix.c b/pr/src/md/unix/irix.c index 7ba079f8..f3d52f01 100644 --- a/pr/src/md/unix/irix.c +++ b/pr/src/md/unix/irix.c @@ -1451,7 +1451,7 @@ void _MD_EarlyInit(void) _MD_IrixIntervalInit(); } /* _MD_EarlyInit */ -void _MD_IrixInit() +void _MD_IrixInit(void) { #if !defined(_PR_PTHREADS) struct sigaction sigact; @@ -1567,7 +1567,7 @@ static PRUint32 pr_ticks_per_second = 0; extern PRIntervalTime _PR_UNIX_GetInterval(void); extern PRIntervalTime _PR_UNIX_TicksPerSecond(void); -static void _MD_IrixIntervalInit() +static void _MD_IrixIntervalInit(void) { /* * As much as I would like, the service available through this @@ -1634,12 +1634,12 @@ static void _MD_IrixIntervalInit() } } /* _MD_IrixIntervalInit */ -PRIntervalTime _MD_IrixIntervalPerSec() +PRIntervalTime _MD_IrixIntervalPerSec(void) { return pr_ticks_per_second; } -PRIntervalTime _MD_IrixGetInterval() +PRIntervalTime _MD_IrixGetInterval(void) { if (mmem_fd != -1) { diff --git a/pr/src/md/unix/openvms.c b/pr/src/md/unix/openvms.c index 72c20432..73d52314 100644 --- a/pr/src/md/unix/openvms.c +++ b/pr/src/md/unix/openvms.c @@ -204,4 +204,80 @@ int thread_resume(PRThread *thr_id) { return 0; } +/* +** Stubs for nspr_symvec.opt +** +** PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended +** (defined in ptthread.c) used to be exported by mistake +** (because they look like public functions). They have been +** converted into static functions. +** +** There is an existing third-party binary that uses NSPR: the +** Java plugin for Mozilla. Because it is part of the Java +** SDK, we have no control over its releases. So we need these +** stub functions to occupy the slots that used to be occupied +** by PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended +** in the symbol vector so that LIBNSPR4 is backward compatible. +** +** The Java plugin was also using PR_CreateThread which we didn't +** realise and hadn't "nailed down". So we now need to nail it down +** to its Mozilla 1.1 position and have to insert 51 additional stubs +** in order to achive this (stubs 4-54). +** +** Over time some of these stubs will get reused by new symbols. +** - Stub54 is replaced by LL_MaxUint +*/ +void PR_VMS_Stub1(void) { } +void PR_VMS_Stub2(void) { } +void PR_VMS_Stub3(void) { } +void PR_VMS_Stub4(void) { } +void PR_VMS_Stub5(void) { } +void PR_VMS_Stub6(void) { } +void PR_VMS_Stub7(void) { } +void PR_VMS_Stub8(void) { } +void PR_VMS_Stub9(void) { } +void PR_VMS_Stub10(void) { } +void PR_VMS_Stub11(void) { } +void PR_VMS_Stub12(void) { } +void PR_VMS_Stub13(void) { } +void PR_VMS_Stub14(void) { } +void PR_VMS_Stub15(void) { } +void PR_VMS_Stub16(void) { } +void PR_VMS_Stub17(void) { } +void PR_VMS_Stub18(void) { } +void PR_VMS_Stub19(void) { } +void PR_VMS_Stub20(void) { } +void PR_VMS_Stub21(void) { } +void PR_VMS_Stub22(void) { } +void PR_VMS_Stub23(void) { } +void PR_VMS_Stub24(void) { } +void PR_VMS_Stub25(void) { } +void PR_VMS_Stub26(void) { } +void PR_VMS_Stub27(void) { } +void PR_VMS_Stub28(void) { } +void PR_VMS_Stub29(void) { } +void PR_VMS_Stub30(void) { } +void PR_VMS_Stub31(void) { } +void PR_VMS_Stub32(void) { } +void PR_VMS_Stub33(void) { } +void PR_VMS_Stub34(void) { } +void PR_VMS_Stub35(void) { } +void PR_VMS_Stub36(void) { } +void PR_VMS_Stub37(void) { } +void PR_VMS_Stub38(void) { } +void PR_VMS_Stub39(void) { } +void PR_VMS_Stub40(void) { } +void PR_VMS_Stub41(void) { } +void PR_VMS_Stub42(void) { } +void PR_VMS_Stub43(void) { } +void PR_VMS_Stub44(void) { } +void PR_VMS_Stub45(void) { } +void PR_VMS_Stub46(void) { } +void PR_VMS_Stub47(void) { } +void PR_VMS_Stub48(void) { } +void PR_VMS_Stub49(void) { } +void PR_VMS_Stub50(void) { } +void PR_VMS_Stub51(void) { } +void PR_VMS_Stub52(void) { } +void PR_VMS_Stub53(void) { } diff --git a/pr/src/md/unix/os_Darwin_ppc.s b/pr/src/md/unix/os_Darwin_ppc.s new file mode 100644 index 00000000..f38ac644 --- /dev/null +++ b/pr/src/md/unix/os_Darwin_ppc.s @@ -0,0 +1,92 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Portable Runtime (NSPR). +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 2003 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# Based on the programming examples in The PowerPC Architecture: +# A Specification for A New Family of RISC Processors, 2nd Ed., +# Book I, Section E.1, "Synchronization," pp. 249-256, May 1994. +# + +.text + +# +# PRInt32 __PR_DarwinPPC_AtomicIncrement(PRInt32 *val); +# + .align 2 + .globl __PR_DarwinPPC_AtomicIncrement +__PR_DarwinPPC_AtomicIncrement: + lwarx r4,0,r3 + addi r0,r4,1 + stwcx. r0,0,r3 + bne- __PR_DarwinPPC_AtomicIncrement + mr r3,r0 + blr + +# +# PRInt32 __PR_DarwinPPC_AtomicDecrement(PRInt32 *val); +# + .align 2 + .globl __PR_DarwinPPC_AtomicDecrement +__PR_DarwinPPC_AtomicDecrement: + lwarx r4,0,r3 + addi r0,r4,-1 + stwcx. r0,0,r3 + bne- __PR_DarwinPPC_AtomicDecrement + mr r3,r0 + blr + +# +# PRInt32 __PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval); +# + .align 2 + .globl __PR_DarwinPPC_AtomicSet +__PR_DarwinPPC_AtomicSet: + lwarx r5,0,r3 + stwcx. r4,0,r3 + bne- __PR_DarwinPPC_AtomicSet + mr r3,r5 + blr + +# +# PRInt32 __PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val); +# + .align 2 + .globl __PR_DarwinPPC_AtomicAdd +__PR_DarwinPPC_AtomicAdd: + lwarx r5,0,r3 + add r0,r4,r5 + stwcx. r0,0,r3 + bne- __PR_DarwinPPC_AtomicAdd + mr r3,r0 + blr diff --git a/pr/src/md/unix/os_Linux_x86.s b/pr/src/md/unix/os_Linux_x86.s index 4eacdc40..d691badd 100644 --- a/pr/src/md/unix/os_Linux_x86.s +++ b/pr/src/md/unix/os_Linux_x86.s @@ -109,3 +109,6 @@ _PR_x86_AtomicAdd: xaddl %eax, (%ecx) addl %edx, %eax ret + +/ Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/pr/src/md/unix/os_Linux_x86_64.s b/pr/src/md/unix/os_Linux_x86_64.s new file mode 100644 index 00000000..567ae12d --- /dev/null +++ b/pr/src/md/unix/os_Linux_x86_64.s @@ -0,0 +1,95 @@ +/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/ +/ The contents of this file are subject to the Mozilla Public +/ License Version 1.1 (the "License"); you may not use this file +/ except in compliance with the License. You may obtain a copy of +/ the License at http://www.mozilla.org/MPL/ +/ +/ Software distributed under the License is distributed on an "AS +/ IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +/ implied. See the License for the specific language governing +/ rights and limitations under the License. +/ +/ The Original Code is the Netscape Portable Runtime (NSPR). +/ +/ The Initial Developer of the Original Code is Netscape +/ Communications Corporation. Portions created by Netscape are +/ Copyright (C) 2004 Netscape Communications Corporation. All +/ Rights Reserved. +/ +/ Contributor(s): +/ +/ Alternatively, the contents of this file may be used under the +/ terms of the GNU General Public License Version 2 or later (the +/ "GPL"), in which case the provisions of the GPL are applicable +/ instead of those above. If you wish to allow use of your +/ version of this file only under the terms of the GPL and not to +/ allow others to use your version of this file under the MPL, +/ indicate your decision by deleting the provisions above and +/ replace them with the notice and other provisions required by +/ the GPL. If you do not delete the provisions above, a recipient +/ may use your version of this file under either the MPL or the +/ GPL. +/ + +/ PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val) +/ +/ Atomically increment the integer pointed to by 'val' and return +/ the result of the increment. +/ + .text + .globl _PR_x86_64_AtomicIncrement + .align 4 +_PR_x86_64_AtomicIncrement: + movl $1, %eax + lock + xaddl %eax, (%rdi) + incl %eax + ret + +/ PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val) +/ +/ Atomically decrement the integer pointed to by 'val' and return +/ the result of the decrement. +/ + .text + .globl _PR_x86_64_AtomicDecrement + .align 4 +_PR_x86_64_AtomicDecrement: + movl $-1, %eax + lock + xaddl %eax, (%rdi) + decl %eax + ret + +/ PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval) +/ +/ Atomically set the integer pointed to by 'val' to the new +/ value 'newval' and return the old value. +/ + .text + .globl _PR_x86_64_AtomicSet + .align 4 +_PR_x86_64_AtomicSet: + movl %esi, %eax + lock + xchgl %eax, (%rdi) + ret + +/ PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val) +/ +/ Atomically add 'val' to the integer pointed to by 'ptr' +/ and return the result of the addition. +/ + .text + .globl _PR_x86_64_AtomicAdd + .align 4 +_PR_x86_64_AtomicAdd: + movl %esi, %eax + lock + xaddl %eax, (%rdi) + addl %esi, %eax + ret + +/ Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits ; .previous diff --git a/pr/src/md/unix/solaris.c b/pr/src/md/unix/solaris.c index 4dd1c06e..0437903a 100644 --- a/pr/src/md/unix/solaris.c +++ b/pr/src/md/unix/solaris.c @@ -183,9 +183,28 @@ THREAD_KEY_T cpuid_key; THREAD_KEY_T last_thread_key; static sigset_t set, oldset; +static void +threadid_key_destructor(void *value) +{ + PRThread *me = (PRThread *)value; + PR_ASSERT(me != NULL); + /* the thread could be PRIMORDIAL (thus not ATTACHED) */ + if (me->flags & _PR_ATTACHED) { + /* + * The Solaris thread library sets the thread specific + * data (the current thread) to NULL before invoking + * the destructor. We need to restore it to prevent the + * _PR_MD_CURRENT_THREAD() call in _PRI_DetachThread() + * from attaching the thread again. + */ + _PR_MD_SET_CURRENT_THREAD(me); + _PRI_DetachThread(); + } +} + void _MD_EarlyInit(void) { - THR_KEYCREATE(&threadid_key, NULL); + THR_KEYCREATE(&threadid_key, threadid_key_destructor); THR_KEYCREATE(&cpuid_key, NULL); THR_KEYCREATE(&last_thread_key, NULL); sigemptyset(&set); @@ -337,7 +356,7 @@ void _MD_lock(struct _MDLock *md_lock) mutex_lock(&md_lock->lock); } -PRThread *_pr_current_thread_tls() +PRThread *_pr_attached_thread_tls() { PRThread *ret; @@ -345,6 +364,21 @@ PRThread *_pr_current_thread_tls() return ret; } +PRThread *_pr_current_thread_tls() +{ + 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; +} + PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks) { diff --git a/pr/src/md/unix/unix.c b/pr/src/md/unix/unix.c index 69153f27..c69a233a 100644 --- a/pr/src/md/unix/unix.c +++ b/pr/src/md/unix/unix.c @@ -64,7 +64,8 @@ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */ -#if defined(HAVE_SOCKLEN_T) +#if defined(HAVE_SOCKLEN_T) \ + || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2) #define _PRSockLen_t socklen_t #elif defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \ || defined(AIX4_1) || defined(LINUX) || defined(SONY) \ @@ -514,6 +515,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; + PRBool wait_for_remaining; PRInt32 syserror; fd_set rd_wr; @@ -558,8 +560,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ + wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { + wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { @@ -596,8 +600,12 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, * PR_IntervalNow() call. */ if (rv == 0) { - now += PR_SecondsToInterval(tv.tv_sec) - + PR_MicrosecondsToInterval(tv.tv_usec); + if (wait_for_remaining) { + now += remaining; + } else { + now += PR_SecondsToInterval(tv.tv_sec) + + PR_MicrosecondsToInterval(tv.tv_usec); + } } else { now = PR_IntervalNow(); } @@ -625,6 +633,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, int msecs; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; + PRBool wait_for_remaining; PRInt32 syserror; struct pollfd pfd; @@ -682,8 +691,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ + wait_for_remaining = PR_TRUE; msecs = PR_IntervalToMilliseconds(remaining); if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { + wait_for_remaining = PR_FALSE; msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; } rv = _MD_POLL(&pfd, 1, msecs); @@ -719,7 +730,11 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, * PR_IntervalNow() call. */ if (rv == 0) { - now += PR_MillisecondsToInterval(msecs); + if (wait_for_remaining) { + now += remaining; + } else { + now += PR_MillisecondsToInterval(msecs); + } } else { now = PR_IntervalNow(); } @@ -2713,6 +2728,28 @@ static void* _MD_Unix_mmap64( } /* _MD_Unix_mmap64 */ #endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */ +#if defined(OSF1) && defined(__GNUC__) + +/* + * On OSF1 V5.0A, <sys/stat.h> defines stat and fstat as + * macros when compiled under gcc, so it is rather tricky to + * take the addresses of the real functions the macros expend + * to. A simple solution is to define forwarder functions + * and take the addresses of the forwarder functions instead. + */ + +static int stat_forwarder(const char *path, struct stat *buffer) +{ + return stat(path, buffer); +} + +static int fstat_forwarder(int filedes, struct stat *buffer) +{ + return fstat(filedes, buffer); +} + +#endif + static void _PR_InitIOV(void) { #if defined(SOLARIS2_5) @@ -2757,8 +2794,13 @@ static void _PR_InitIOV(void) #elif defined(_PR_HAVE_LARGE_OFF_T) _md_iovector._open64 = open; _md_iovector._mmap64 = mmap; +#if defined(OSF1) && defined(__GNUC__) + _md_iovector._fstat64 = fstat_forwarder; + _md_iovector._stat64 = stat_forwarder; +#else _md_iovector._fstat64 = fstat; _md_iovector._stat64 = stat; +#endif _md_iovector._lseek64 = lseek; #else #error "I don't know yet" @@ -3221,9 +3263,6 @@ int _MD_unix_get_nonblocking_connect_error(int osfd) int err; _PRSockLen_t optlen = sizeof(err); - printf("_MD_unix_get_nonblocking_connect_error: " - "Assuming Large TCP/IP Stack -REVISIT- Never Tested!\n"); - if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) { return errno; diff --git a/pr/src/md/unix/unix_errors.c b/pr/src/md/unix/unix_errors.c index 1ce52e68..055961ee 100644 --- a/pr/src/md/unix/unix_errors.c +++ b/pr/src/md/unix/unix_errors.c @@ -108,6 +108,9 @@ void _MD_unix_map_default_error(int err) case EFBIG: prError = PR_FILE_TOO_BIG_ERROR; break; + case EHOSTUNREACH: + prError = PR_HOST_UNREACHABLE_ERROR; + break; case EINPROGRESS: prError = PR_IN_PROGRESS_ERROR; break; @@ -847,3 +850,10 @@ void _MD_solaris_map_sendfile_error(int err) _MD_unix_map_default_error(err) ; } #endif /* SOLARIS */ + +#ifdef LINUX +void _MD_linux_map_sendfile_error(int err) +{ + _MD_unix_map_default_error(err) ; +} +#endif /* LINUX */ diff --git a/pr/src/md/unix/uxpoll.c b/pr/src/md/unix/uxpoll.c index 56a0d3dc..c3275acf 100644 --- a/pr/src/md/unix/uxpoll.c +++ b/pr/src/md/unix/uxpoll.c @@ -173,6 +173,8 @@ static PRInt32 NativeThreadPoll( { /* make poll() ignore this entry */ syspoll[index].fd = -1; + syspoll[index].events = 0; + pds[index].out_flags = 0; } } @@ -384,6 +386,10 @@ static PRInt32 NativeThreadSelect( } } } + else + { + pd->out_flags = 0; + } } if (0 != ready) return ready; /* no need to block */ @@ -396,8 +402,7 @@ retry: { 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; + tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); tvp = &tv; } diff --git a/pr/src/md/unix/uxproces.c b/pr/src/md/unix/uxproces.c index 58b5ab8a..d469f1c4 100644 --- a/pr/src/md/unix/uxproces.c +++ b/pr/src/md/unix/uxproces.c @@ -802,7 +802,7 @@ static void pr_InstallSigchldHandler() #endif /* !defined(_PR_NATIVE_THREADS) */ -static PRStatus _MD_InitProcesses() +static PRStatus _MD_InitProcesses(void) { #if !defined(_PR_NATIVE_THREADS) int rv; diff --git a/pr/src/md/unix/uxrng.c b/pr/src/md/unix/uxrng.c index 64358289..6add3bf1 100644 --- a/pr/src/md/unix/uxrng.c +++ b/pr/src/md/unix/uxrng.c @@ -64,6 +64,18 @@ GetHighResClock(void *buf, size_t maxbytes) #elif defined(HPUX) +#ifdef __ia64 +#include <ia64/sys/inline.h> + +static size_t +GetHighResClock(void *buf, size_t maxbytes) +{ + PRUint64 t; + + t = _Asm_mov_from_ar(_AREG44); + return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t)); +} +#else static size_t GetHighResClock(void *buf, size_t maxbytes) { @@ -73,6 +85,7 @@ GetHighResClock(void *buf, size_t maxbytes) cr16val = ret_cr16(); return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val))); } +#endif #elif defined(OSF1) @@ -88,7 +101,11 @@ GetHighResClock(void *buf, size_t maxbytes) { unsigned long t; +#ifdef __GNUC__ + __asm__("rpcc %0" : "=r" (t)); +#else t = asm("rpcc %v0"); +#endif return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t)); } @@ -210,7 +227,7 @@ static size_t GetHighResClock(void *buf, size_t maxbuf) } iotimer_addr = (unsigned *) mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr); - if (iotimer_addr == (void*)-1) { + if (iotimer_addr == (unsigned*)-1) { close(mfd); iotimer_addr = NULL; return 0; diff --git a/pr/src/md/unix/uxshm.c b/pr/src/md/unix/uxshm.c index 888cbe04..1dc98386 100644 --- a/pr/src/md/unix/uxshm.c +++ b/pr/src/md/unix/uxshm.c @@ -94,7 +94,7 @@ extern PRSharedMemory * _MD_OpenSharedMemory( return( NULL ); } - shm->ipcname = PR_MALLOC( strlen( ipcname ) + 1 ); + shm->ipcname = (char*)PR_MALLOC( strlen( ipcname ) + 1 ); if ( NULL == shm->ipcname ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); @@ -118,7 +118,7 @@ extern PRSharedMemory * _MD_OpenSharedMemory( PR_DELETE( shm ); return( NULL ); } - if ( close(osfd == -1 )) { + if ( close(osfd) == -1 ) { _PR_MD_MAP_CLOSE_ERROR( errno ); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); @@ -243,7 +243,7 @@ extern PRStatus _MD_DeleteSharedMemory( const char *name ) _PR_MD_MAP_OPEN_ERROR( errno ); return( PR_FAILURE ); } - if ( close(osfd == -1 )) { + if ( close(osfd) == -1 ) { _PR_MD_MAP_CLOSE_ERROR( errno ); return( PR_FAILURE ); } @@ -311,7 +311,6 @@ extern PRSharedMemory * _MD_OpenSharedMemory( ) { PRStatus rc = PR_SUCCESS; - PRIntn id; PRInt32 end; PRSharedMemory *shm; char ipcname[PR_IPC_NAME_SIZE]; diff --git a/pr/src/md/windows/Makefile.in b/pr/src/md/windows/Makefile.in index 283fa4a4..dd5a613b 100644 --- a/pr/src/md/windows/Makefile.in +++ b/pr/src/md/windows/Makefile.in @@ -105,3 +105,13 @@ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) +# Bug 122433 workaround: disable global optimization (-Og-) on ntio.c. +ifdef BUILD_OPT +ifeq ($(OS_TARGET), WINNT) +ifndef NS_USE_GCC +$(OBJDIR)/ntio.$(OBJ_SUFFIX): ntio.c + @$(MAKE_OBJDIR) + $(CC) -Fo$@ -c $(CFLAGS) -Og- $< +endif +endif +endif diff --git a/pr/src/md/windows/ntinrval.c b/pr/src/md/windows/ntinrval.c index d6a3fe6f..857ada6a 100644 --- a/pr/src/md/windows/ntinrval.c +++ b/pr/src/md/windows/ntinrval.c @@ -45,9 +45,8 @@ #define QueryPerformanceCounter(x) FALSE #endif -PRIntn _nt_bitShift = 0; -PRInt32 _nt_highMask = 0; -PRInt32 _nt_ticksPerSec = -1; +static PRIntn _nt_bitShift = 0; +static PRInt32 _nt_ticksPerSec = -1; void _PR_MD_INTERVAL_INIT() @@ -55,16 +54,33 @@ _PR_MD_INTERVAL_INIT() LARGE_INTEGER count; if (QueryPerformanceFrequency(&count)) { + /* + * HighPart is signed (LONG). Assert that its sign bit is 0 + * because we will be right shifting it. LowPart is unsigned + * (DWORD). + */ + PR_ASSERT(count.HighPart >= 0); + while(count.HighPart) { + count.LowPart = (count.HighPart << 31) + (count.LowPart >> 1); + count.HighPart >>= 1; + _nt_bitShift++; + } while(count.LowPart > PR_INTERVAL_MAX) { count.LowPart >>= 1; _nt_bitShift++; - _nt_highMask = (_nt_highMask << 1)+1; } - _nt_ticksPerSec = count.LowPart; - PR_ASSERT(_nt_ticksPerSec > PR_INTERVAL_MIN); - } else - _nt_ticksPerSec = -1; + /* + * We can't use the performance counter if after + * normalization we are left with fewer than 32 bits. + */ + if (_nt_bitShift <= 32) { + _nt_ticksPerSec = count.LowPart; + PR_ASSERT(_nt_ticksPerSec > PR_INTERVAL_MIN); + return; + } + } + _nt_ticksPerSec = -1; } PRIntervalTime @@ -76,12 +92,15 @@ _PR_MD_GET_INTERVAL() * to only 100000 ticks per second; QueryPerformanceCounter is too high * resolution... */ - if (QueryPerformanceCounter(&count)) { - PRInt32 top = count.HighPart & _nt_highMask; - top = top << (32 - _nt_bitShift); - count.LowPart = count.LowPart >> _nt_bitShift; - count.LowPart = count.LowPart + top; - return (PRUint32)count.LowPart; + if (_nt_ticksPerSec != -1) { + (void)QueryPerformanceCounter(&count); + PR_ASSERT(_nt_bitShift <= 32); + if (_nt_bitShift == 32) { + return (PRUint32)count.HighPart; + } else { + return (PRUint32)((count.HighPart << (32 - _nt_bitShift)) + + (count.LowPart >> _nt_bitShift)); + } } else #if defined(__MINGW32__) return time(); diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c index 299033cc..345e253a 100644 --- a/pr/src/md/windows/ntio.c +++ b/pr/src/md/windows/ntio.c @@ -99,7 +99,11 @@ static DWORD dirAccessTable[] = { * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). */ +#ifdef __GNUC__ +static const PRTime _pr_filetime_offset = 116444736000000000LL; +#else static const PRTime _pr_filetime_offset = 116444736000000000i64; +#endif #define _NEED_351_FILE_LOCKING_HACK #ifdef _NEED_351_FILE_LOCKING_HACK @@ -1328,6 +1332,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); + closesocket(accept_sock); return -1; } me->io_pending = PR_TRUE; @@ -1346,6 +1351,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) { /* Argh! The IO failed */ + closesocket(accept_sock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; @@ -1365,12 +1371,14 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); + closesocket(accept_sock); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { + closesocket(accept_sock); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); @@ -1381,6 +1389,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, } if (me->md.blocked_io_status == 0) { + closesocket(accept_sock); _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error); return -1; } @@ -1446,6 +1455,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); + closesocket(*newSock); return -1; } me->io_pending = PR_TRUE; @@ -1463,6 +1473,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) { + closesocket(*newSock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; @@ -1482,6 +1493,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); + closesocket(*newSock); return -1; } @@ -1511,8 +1523,10 @@ retry: callback(callbackArg); madeCallback = PR_TRUE; me->state = _PR_IO_WAIT; - if (_NT_ResumeIO(me, timeout) == PR_FAILURE) + if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { + closesocket(*newSock); return -1; + } goto retry; } @@ -1520,8 +1534,10 @@ retry: /* Socket is connected but time not elapsed, RESUME IO */ timeout -= elapsed; me->state = _PR_IO_WAIT; - if (_NT_ResumeIO(me, timeout) == PR_FAILURE) + if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { + closesocket(*newSock); return -1; + } goto retry; } } else { @@ -1548,6 +1564,7 @@ retry: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } me->state = _PR_RUNNING; + closesocket(*newSock); return -1; } @@ -2322,7 +2339,7 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) } PRInt32 -_PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) +_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) { PRInt32 f = fd->secret->md.osfd; PRInt32 bytes; @@ -2488,7 +2505,7 @@ _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) } PROffset32 -_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, int whence) +_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { DWORD moveMethod; PROffset32 rv; @@ -2521,7 +2538,7 @@ _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, int whence) } PROffset64 -_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, int whence) +_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { DWORD moveMethod; LARGE_INTEGER li; @@ -2815,12 +2832,16 @@ _PR_MD_DELETE(const char *name) } } -static void +void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); CopyMemory(prtm, filetime, sizeof(PRTime)); +#ifdef __GNUC__ + *prtm = (*prtm - _pr_filetime_offset) / 10LL; +#else *prtm = (*prtm - _pr_filetime_offset) / 10i64; +#endif #ifdef DEBUG /* Doublecheck our calculation. */ @@ -3168,7 +3189,7 @@ _PR_MD_RENAME(const char *from, const char *to) } PRInt32 -_PR_MD_ACCESS(const char *name, PRIntn how) +_PR_MD_ACCESS(const char *name, PRAccessHow how) { PRInt32 rv; diff --git a/pr/src/md/windows/ntmisc.c b/pr/src/md/windows/ntmisc.c index c4bb8511..32a199ce 100644 --- a/pr/src/md/windows/ntmisc.c +++ b/pr/src/md/windows/ntmisc.c @@ -84,18 +84,12 @@ PRIntn _PR_MD_PUT_ENV(const char *name) PR_IMPLEMENT(PRTime) PR_Now(void) { - PRInt64 s, ms, ms2us, s2us; - struct timeb b; - - ftime(&b); - LL_I2L(ms2us, PR_USEC_PER_MSEC); - LL_I2L(s2us, PR_USEC_PER_SEC); - LL_I2L(s, b.time); - LL_I2L(ms, b.millitm); - LL_MUL(ms, ms, ms2us); - LL_MUL(s, s, s2us); - LL_ADD(s, s, ms); - return s; + PRTime prt; + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + _PR_FileTimeToPRTime(&ft, &prt); + return prt; } /* @@ -792,7 +786,7 @@ PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) PRInt32 result; asm volatile ("lock ; xadd %0, %1" : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); + : "0"(-1), "m"(*val)); //asm volatile("lock ; xadd %0, %1" : "=m" (val), "=a" (result) : "-1" (1)); return result - 1; #else @@ -814,8 +808,8 @@ PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val) PRInt32 result; //asm volatile("lock ; xadd %1, %0" : "=m" (intp), "=a" (result) : "1" (val)); asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); + : "=r"(result), "=m"(*intp) + : "0"(val), "m"(*intp)); return result + val; #else __asm diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c index 9c3e2baf..0e7ef6e0 100644 --- a/pr/src/md/windows/ntthread.c +++ b/pr/src/md/windows/ntthread.c @@ -191,6 +191,14 @@ _PR_MD_INIT_THREAD(PRThread *thread) return PR_SUCCESS; } +static unsigned __stdcall +pr_root(void *arg) +{ + PRThread *thread = (PRThread *)arg; + thread->md.start(thread); + return 0; +} + PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), @@ -200,23 +208,14 @@ _PR_MD_CREATE_THREAD(PRThread *thread, PRUint32 stackSize) { -#if 0 - thread->md.handle = CreateThread( - NULL, /* security attrib */ - thread->stack->stackSize, /* stack size */ - (LPTHREAD_START_ROUTINE)start, /* startup routine */ - (void *)thread, /* thread param */ - CREATE_SUSPENDED, /* create flags */ - &(thread->id) ); /* thread id */ -#else + thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, - (unsigned (__stdcall *)(void *))start, + pr_root, (void *)thread, CREATE_SUSPENDED, &(thread->id)); -#endif if(!thread->md.handle) { PRErrorCode prerror; thread->md.fiber_last_error = GetLastError(); @@ -238,6 +237,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread, } thread->md.id = thread->id; + /* + * On windows, a thread is created with a thread priority of + * THREAD_PRIORITY_NORMAL. + */ + if (priority != PR_PRIORITY_NORMAL) { + _PR_MD_SET_PRIORITY(&(thread->md), priority); + } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) @@ -247,6 +253,21 @@ _PR_MD_CREATE_THREAD(PRThread *thread, return PR_FAILURE; } +void +_PR_MD_JOIN_THREAD(_MDThread *md) +{ + DWORD rv; + + rv = WaitForSingleObject(md->handle, INFINITE); + PR_ASSERT(WAIT_OBJECT_0 == rv); +} + +void +_PR_MD_END_THREAD(void) +{ + _endthreadex(0); +} + void _PR_MD_YIELD(void) { diff --git a/pr/src/md/windows/w32poll.c b/pr/src/md/windows/w32poll.c index 2747a040..403aa004 100644 --- a/pr/src/md/windows/w32poll.c +++ b/pr/src/md/windows/w32poll.c @@ -36,6 +36,9 @@ * This file implements _PR_MD_PR_POLL for Win32. */ +/* The default value of FD_SETSIZE is 64. */ +#define FD_SETSIZE 1024 + #include "primpl.h" #if !defined(_PR_GLOBAL_THREADS_ONLY) @@ -105,6 +108,8 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { int ready, err; fd_set rd, wt, ex; + fd_set *rdp, *wtp, *exp; + int nrd, nwt, nex; PRFileDesc *bottom; PRPollDesc *pd, *epd; PRThread *me = _PR_MD_CURRENT_THREAD(); @@ -127,6 +132,7 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) return 0; } + nrd = nwt = nex = 0; FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); @@ -189,23 +195,30 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { pd->out_flags |= _PR_POLL_READ_SYS_READ; FD_SET(osfd, &rd); + nrd++; } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; FD_SET(osfd, &wt); + nwt++; } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; FD_SET(osfd, &rd); + nrd++; } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; FD_SET(osfd, &wt); + nwt++; + } + if (pd->in_flags & PR_POLL_EXCEPT) { + FD_SET(osfd, &ex); + nex++; } - if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else @@ -223,23 +236,40 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) } } } + else + { + pd->out_flags = 0; + } } if (0 != ready) return ready; /* no need to block */ + if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + rdp = (0 == nrd) ? NULL : &rd; + wtp = (0 == nwt) ? NULL : &wt; + exp = (0 == nex) ? NULL : &ex; + + if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) { + PR_Sleep(timeout); + return 0; + } + 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; + tv.tv_usec = PR_IntervalToMicroseconds( timeout % ticksPerSecond ); tvp = &tv; } #if defined(_PR_GLOBAL_THREADS_ONLY) - ready = _MD_SELECT(0, &rd, &wt, &ex, tvp); + ready = _MD_SELECT(0, rdp, wtp, exp, tvp); #else - ready = _PR_NTFiberSafeSelect(0, &rd, &wt, &ex, tvp); + ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp); #endif /* diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 89669e6e..6ccdf410 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -41,6 +41,9 @@ #include "primpl.h" #include <direct.h> #include <mbstring.h> +#ifdef MOZ_UNICODE +#include <wchar.h> +#endif /* MOZ_UNICODE */ struct _MDLock _pr_ioq_lock; @@ -74,6 +77,10 @@ static const PRTime _pr_filetime_offset = 116444736000000000LL; static const PRTime _pr_filetime_offset = 116444736000000000i64; #endif +#ifdef MOZ_UNICODE +static void InitUnicodeSupport(void); +#endif + void _PR_MD_INIT_IO() { @@ -110,6 +117,10 @@ _PR_MD_INIT_IO() #endif /* DEBUG */ _PR_NT_InitSids(); + +#ifdef MOZ_UNICODE + InitUnicodeSupport(); +#endif } PRStatus @@ -568,7 +579,7 @@ _PR_MD_DELETE(const char *name) } } -static void +void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); @@ -1088,3 +1099,410 @@ _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } + +#ifdef MOZ_UNICODE + +typedef HANDLE (WINAPI *CreateFileWFn) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +static CreateFileWFn createFileW = NULL; +typedef HANDLE (WINAPI *FindFirstFileWFn) (LPCWSTR, LPWIN32_FIND_DATAW); +static FindFirstFileWFn findFirstFileW = NULL; +typedef BOOL (WINAPI *FindNextFileWFn) (HANDLE, LPWIN32_FIND_DATAW); +static FindNextFileWFn findNextFileW = NULL; +typedef DWORD (WINAPI *GetFullPathNameWFn) (LPCWSTR, DWORD, LPWSTR, LPWSTR *); +static GetFullPathNameWFn getFullPathNameW = NULL; +typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR); +static GetDriveTypeWFn getDriveTypeW = NULL; + +static void InitUnicodeSupport(void) +{ + HMODULE module; + + /* + * The W functions do not exist on Win9x. NSPR won't run on Win9x + * if we call the W functions directly. Use GetProcAddress() to + * look up their addresses at run time. + */ + + module = GetModuleHandle("Kernel32.dll"); + if (!module) { + return; + } + + createFileW = (CreateFileWFn)GetProcAddress(module, "CreateFileW"); + findFirstFileW = (FindFirstFileWFn)GetProcAddress(module, "FindFirstFileW"); + findNextFileW = (FindNextFileWFn)GetProcAddress(module, "FindNextFileW"); + getDriveTypeW = (GetDriveTypeWFn)GetProcAddress(module, "GetDriveTypeW"); + getFullPathNameW = (GetFullPathNameWFn)GetProcAddress(module, "GetFullPathNameW"); +} + +/* ================ UTF16 Interfaces ================================ */ +void FlipSlashesW(PRUnichar *cp, int len) +{ + while (--len >= 0) { + if (cp[0] == L'/') { + cp[0] = L'\\'; + } + cp++; + } +} /* end FlipSlashesW() */ + +PRInt32 +_PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode) +{ + HANDLE file; + PRInt32 access = 0; + PRInt32 flags = 0; + PRInt32 flag6 = 0; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + + if (!createFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } + + if (osflags & PR_CREATE_FILE) { + if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + } + + if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; + + if (osflags & PR_RDONLY || osflags & PR_RDWR) + access |= GENERIC_READ; + if (osflags & PR_WRONLY || osflags & PR_RDWR) + access |= GENERIC_WRITE; + + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) + flags = CREATE_NEW; + else if (osflags & PR_CREATE_FILE) { + if (osflags & PR_TRUNCATE) + flags = CREATE_ALWAYS; + else + flags = OPEN_ALWAYS; + } else { + if (osflags & PR_TRUNCATE) + flags = TRUNCATE_EXISTING; + else + flags = OPEN_EXISTING; + } + + file = createFileW(name, + access, + FILE_SHARE_READ|FILE_SHARE_WRITE, + lpSA, + flags, + flag6, + NULL); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (file == INVALID_HANDLE_VALUE) { + _PR_MD_MAP_OPEN_ERROR(GetLastError()); + return -1; + } + + return (PRInt32)file; +} + +PRStatus +_PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name) +{ + PRUnichar filename[ MAX_PATH ]; + int len; + + if (!findFirstFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; + } + + len = wcslen(name); + /* Need 5 bytes for \*.* and the trailing null byte. */ + if (len + 5 > MAX_PATH) { + PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); + return PR_FAILURE; + } + wcscpy(filename, name); + + /* + * If 'name' ends in a slash or backslash, do not append + * another backslash. + */ + if (filename[len - 1] == L'/' || filename[len - 1] == L'\\') { + len--; + } + wcscpy(&filename[len], L"\\*.*"); + FlipSlashesW( filename, wcslen(filename) ); + + d->d_hdl = findFirstFileW( filename, &(d->d_entry) ); + if ( d->d_hdl == INVALID_HANDLE_VALUE ) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return PR_FAILURE; + } + d->firstEntry = PR_TRUE; + d->magic = _MD_MAGIC_DIR; + return PR_SUCCESS; +} + +PRUnichar * +_PR_MD_READ_DIR_UTF16(_MDDirUTF16 *d, PRIntn flags) +{ + PRInt32 err; + BOOL rv; + PRUnichar *fileName; + + if (!findNextFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; + } + + if ( d ) { + while (1) { + if (d->firstEntry) { + d->firstEntry = PR_FALSE; + rv = 1; + } else { + rv = findNextFileW(d->d_hdl, &(d->d_entry)); + } + if (rv == 0) { + break; + } + fileName = GetFileFromDIR(d); + if ( (flags & PR_SKIP_DOT) && + (fileName[0] == L'.') && (fileName[1] == L'\0')) + continue; + if ( (flags & PR_SKIP_DOT_DOT) && + (fileName[0] == L'.') && (fileName[1] == L'.') && + (fileName[2] == L'\0')) + continue; + if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) + continue; + return fileName; + } + err = GetLastError(); + PR_ASSERT(NO_ERROR != err); + _PR_MD_MAP_READDIR_ERROR(err); + return NULL; + } + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return NULL; +} + +PRStatus +_PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *d) +{ + if ( d ) { + if (FindClose(d->d_hdl)) { + d->magic = (PRUint32)-1; + return PR_SUCCESS; + } else { + _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); + return PR_FAILURE; + } + } + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return PR_FAILURE; +} + +#define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\') + +/* + * IsRootDirectoryW -- + * + * Return PR_TRUE if the pathname 'fn' is a valid root directory, + * else return PR_FALSE. The PRUnichar buffer pointed to by 'fn' must + * be writable. During the execution of this function, the contents + * of the buffer pointed to by 'fn' may be modified, but on return + * the original contents will be restored. 'buflen' is the size of + * the buffer pointed to by 'fn', in PRUnichars. + * + * Root directories come in three formats: + * 1. / or \, meaning the root directory of the current drive. + * 2. C:/ or C:\, where C is a drive letter. + * 3. \\<server name>\<share point name>\ or + * \\<server name>\<share point name>, meaning the root directory + * of a UNC (Universal Naming Convention) name. + */ + +static PRBool +IsRootDirectoryW(PRUnichar *fn, size_t buflen) +{ + PRUnichar *p; + PRBool slashAdded = PR_FALSE; + PRBool rv = PR_FALSE; + + if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') { + return PR_TRUE; + } + + if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2]) + && fn[3] == L'\0') { + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + return rv; + } + + /* The UNC root directory */ + + if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) { + /* The 'server' part should have at least one character. */ + p = &fn[2]; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the next slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (*p == L'\0') { + return PR_FALSE; + } + + /* The 'share' part should have at least one character. */ + p++; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the final slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') { + return PR_FALSE; + } + if (*p == L'\0') { + /* + * GetDriveType() doesn't work correctly if the + * path is of the form \\server\share, so we add + * a final slash temporarily. + */ + if ((p + 1) < (fn + buflen)) { + *p++ = L'\\'; + *p = L'\0'; + slashAdded = PR_TRUE; + } else { + return PR_FALSE; /* name too long */ + } + } + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + /* restore the 'fn' buffer */ + if (slashAdded) { + *--p = L'\0'; + } + } + return rv; +} + +PRInt32 +_PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW findFileData; + PRUnichar pathbuf[MAX_PATH + 1]; + + if (!findFirstFileW || !getFullPathNameW || !getDriveTypeW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } + + if (NULL == fn || L'\0' == *fn) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + /* + * FindFirstFile() expands wildcard characters. So + * we make sure the pathname contains no wildcard. + */ + if (NULL != wcspbrk(fn, L"?*")) { + PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); + return -1; + } + + hFindFile = findFirstFileW(fn, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + DWORD len; + PRUnichar *filePart; + + /* + * FindFirstFile() does not work correctly on root directories. + * It also doesn't work correctly on a pathname that ends in a + * slash. So we first check to see if the pathname specifies a + * root directory. If not, and if the pathname ends in a slash, + * we remove the final slash and try again. + */ + + /* + * If the pathname does not contain ., \, and /, it cannot be + * a root directory or a pathname that ends in a slash. + */ + if (NULL == wcspbrk(fn, L".\\/")) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + len = getFullPathNameW(fn, sizeof(pathbuf)/sizeof(pathbuf[0]), pathbuf, + &filePart); + if (0 == len) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + if (len > sizeof(pathbuf)/sizeof(pathbuf[0])) { + PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); + return -1; + } + if (IsRootDirectoryW(pathbuf, sizeof(pathbuf)/sizeof(pathbuf[0]))) { + info->type = PR_FILE_DIRECTORY; + info->size = 0; + /* + * These timestamps don't make sense for root directories. + */ + info->modifyTime = 0; + info->creationTime = 0; + return 0; + } + if (!_PR_IS_W_SLASH(pathbuf[len - 1])) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } else { + pathbuf[len - 1] = L'\0'; + hFindFile = findFirstFileW(pathbuf, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + } + } + + FindClose(hFindFile); + + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + info->type = PR_FILE_DIRECTORY; + } else { + info->type = PR_FILE_FILE; + } + + info->size = findFileData.nFileSizeHigh; + info->size = (info->size << 32) + findFileData.nFileSizeLow; + + _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); + + if (0 == findFileData.ftCreationTime.dwLowDateTime && + 0 == findFileData.ftCreationTime.dwHighDateTime) { + info->creationTime = info->modifyTime; + } else { + _PR_FileTimeToPRTime(&findFileData.ftCreationTime, + &info->creationTime); + } + + return 0; +} +/* ================ end of UTF16 Interfaces ================================ */ +#endif /* MOZ_UNICODE */ diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c index d36ffdcd..58944703 100644 --- a/pr/src/md/windows/w95sock.c +++ b/pr/src/md/windows/w95sock.c @@ -168,7 +168,6 @@ PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv; - int one = 1; rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen); @@ -180,6 +179,20 @@ _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) return 0; } +PRInt32 +_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) +{ + PRInt32 rv; + + rv = listen(fd->secret->md.osfd, backlog); + + if (rv == SOCKET_ERROR) { + _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError()); + return -1; + } + + return 0; +} PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, @@ -461,6 +474,7 @@ static PRInt32 socket_io_wait( struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime elapsed, remaining; + PRBool wait_for_remaining; fd_set rd_wr, ex; int err, len; @@ -547,8 +561,10 @@ static PRInt32 socket_io_wait( * so that there is an upper limit on the delay * before the interrupt bit is checked. */ + wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { + wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { @@ -618,8 +634,12 @@ static PRInt32 socket_io_wait( */ if (rv == 0 ) { - elapsed = PR_SecondsToInterval(tv.tv_sec) - + PR_MicrosecondsToInterval(tv.tv_usec); + if (wait_for_remaining) { + elapsed = remaining; + } else { + elapsed = PR_SecondsToInterval(tv.tv_sec) + + PR_MicrosecondsToInterval(tv.tv_usec); + } if (elapsed >= remaining) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c index a70f1620..f2519f42 100644 --- a/pr/src/md/windows/w95thred.c +++ b/pr/src/md/windows/w95thred.c @@ -106,6 +106,14 @@ _PR_MD_INIT_THREAD(PRThread *thread) return PR_SUCCESS; } +static unsigned __stdcall +pr_root(void *arg) +{ + PRThread *thread = (PRThread *)arg; + thread->md.start(thread); + return 0; +} + PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), @@ -115,14 +123,11 @@ _PR_MD_CREATE_THREAD(PRThread *thread, PRUint32 stackSize) { + thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, -#if defined(__MINGW32__) - (void *)start, -#else - (unsigned (__stdcall *)(void *))start, -#endif + pr_root, (void *)thread, CREATE_SUSPENDED, &(thread->id)); @@ -131,7 +136,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread, } thread->md.id = thread->id; - _PR_MD_SET_PRIORITY(&(thread->md), priority); + /* + * On windows, a thread is created with a thread priority of + * THREAD_PRIORITY_NORMAL. + */ + if (priority != PR_PRIORITY_NORMAL) { + _PR_MD_SET_PRIORITY(&(thread->md), priority); + } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) diff --git a/pr/src/misc/Makefile.in b/pr/src/misc/Makefile.in index 114e110b..afc4b631 100644 --- a/pr/src/misc/Makefile.in +++ b/pr/src/misc/Makefile.in @@ -82,12 +82,14 @@ RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties include $(topsrcdir)/config/rules.mk -# An AIX Optimization bug causes PR_dtoa() to produce wrong result. -# This suppresses optimization for this single compilation unit. -ifeq ($(OS_ARCH), AIX) -$(OBJDIR)/prdtoa.o: prdtoa.c +# Prevent floating point errors caused by MSVC 6.0 Processor Pack +# optimizations (bug 207421). This disables optimizations that +# could change the precision of floating-point calculations for +# this single compilation unit. +ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) +$(OBJDIR)/prdtoa.$(OBJ_SUFFIX): prdtoa.c @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(filter-out -O, $(CFLAGS)) $< + $(CC) -Fo$@ -c $(CFLAGS) -Op $(call abspath,$<) endif # diff --git a/pr/src/misc/compile-et.pl b/pr/src/misc/compile-et.pl index c1c55dd7..8fafcb7b 100644 --- a/pr/src/misc/compile-et.pl +++ b/pr/src/misc/compile-et.pl @@ -129,7 +129,7 @@ print C "};\n\n"; printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n", $base, $table_base, $table_item_count; print C "\n"; -print C "void ", $table_name, "_InitializePRErrorTable", "() {\n"; +print C "void ", $table_name, "_InitializePRErrorTable", "(void) {\n"; print C " PR_ErrorInstallTable(&et);\n"; print C "}\n"; diff --git a/pr/src/misc/pralarm.c b/pr/src/misc/pralarm.c index 488ce5a4..81b251d9 100644 --- a/pr/src/misc/pralarm.c +++ b/pr/src/misc/pralarm.c @@ -116,7 +116,7 @@ static PRIntervalTime pr_PredictNextNotifyTime(PRAlarmID *id) id->lastNotify = id->nextNotify; /* just keeping track of things */ id->nextNotify = (PRIntervalTime)(offsetFromEpoch + 0.5); - delta = id->nextNotify - id->nextNotify; + delta = id->nextNotify - id->lastNotify; return delta; } /* pr_PredictNextNotifyTime */ @@ -180,7 +180,7 @@ static void PR_CALLBACK pr_alarmNotifier(void *arg) } /* pr_alarm_notifier */ -PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm() +PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm(void) { PRAlarm *alarm = PR_NEWZAP(PRAlarm); if (alarm != NULL) diff --git a/pr/src/misc/prcountr.c b/pr/src/misc/prcountr.c index 850f7bcd..b5f6ae23 100644 --- a/pr/src/misc/prcountr.c +++ b/pr/src/misc/prcountr.c @@ -68,7 +68,6 @@ ** */ -#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #include "prcountr.h" #include "prclist.h" #include "prlock.h" @@ -502,14 +501,3 @@ PR_IMPLEMENT(PRCounterHandle) return((PRCounterHandle)rnp); } /* end PR_FindNextCounterRname() */ - - -#else /* !(defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)) */ -/* -** NSPR Counters are not defined in this case -** -** -*/ -/* Some compilers don't like an empty compilation unit. */ -static int dummy = 0; -#endif /* defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) */ diff --git a/pr/src/misc/prdtoa.c b/pr/src/misc/prdtoa.c index e2e715fe..78b509e6 100644 --- a/pr/src/misc/prdtoa.c +++ b/pr/src/misc/prdtoa.c @@ -97,6 +97,9 @@ * significant byte has the lowest address. * #define IEEE_MC68k for IEEE-arithmetic machines where the most * significant byte has the lowest address. + * #define IEEE_ARM for IEEE-arithmetic machines where the two words + * in a double are stored in big endian order but the two shorts + * in a word are still stored in little endian order. * #define Long int on machines with 32-bit ints and 64-bit longs. * #define Sudden_Underflow for IEEE-format machines without gradual * underflow (i.e., that flush to zero on underflow). @@ -123,8 +126,16 @@ * if memory is available and otherwise does something you deem * appropriate. If MALLOC is undefined, malloc will be invoked * directly -- and assumed always to succeed. + * #define YES_ALIAS to permit aliasing certain double values with + * arrays of unsigned Longs. This leads to slightly better code with + * some compilers and was always used prior to 19990916, but it + * is not strictly legal and can cause trouble with aggressively + * optimizing compilers (e.g., gcc 2.95.1 under -O2). */ -#if defined(IS_LITTLE_ENDIAN) +#if defined(__arm) || defined(__arm__) || defined(__arm26__) \ + || defined(__arm32__) +#define IEEE_ARM +#elif defined(IS_LITTLE_ENDIAN) #define IEEE_8087 #else #define IEEE_MC68k @@ -164,6 +175,9 @@ extern void *MALLOC(size_t); #ifdef IEEE_8087 #define IEEE_ARITHMETIC #endif +#ifdef IEEE_ARM +#define IEEE_ARITHMETIC +#endif #ifdef IEEE_ARITHMETIC #define DBL_DIG 15 @@ -197,6 +211,16 @@ extern void *MALLOC(size_t); #endif #else #include "float.h" +/* + * MacOS 10.2 defines the macro FLT_ROUNDS to an internal function + * which does not exist on 10.1. We can safely #define it to 1 here + * to allow 10.2 builds to run on 10.1, since we can't use fesetround() + * (which does not exist on 10.1 either). + */ +#if defined(MACOS_DEPLOYMENT_TARGET) && (MACOS_DEPLOYMENT_TARGET < 100200) +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 +#endif #endif #ifndef __MATH_H__ #include "math.h" @@ -212,10 +236,14 @@ extern void *MALLOC(size_t); #define Sign_Extend(a,b) /*no-op*/ #endif -#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, IEEE_ARM, VAX, or IBM should be defined. #endif +typedef union { double d; unsigned Long L[2]; } U; + +#ifdef YES_ALIAS +#define dval(x) x #ifdef IEEE_8087 #define word0(x) ((unsigned Long *)&x)[1] #define word1(x) ((unsigned Long *)&x)[0] @@ -223,12 +251,22 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. #define word0(x) ((unsigned Long *)&x)[0] #define word1(x) ((unsigned Long *)&x)[1] #endif +#else +#ifdef IEEE_8087 +#define word0(x) ((U*)&x)->L[1] +#define word1(x) ((U*)&x)->L[0] +#else +#define word0(x) ((U*)&x)->L[0] +#define word1(x) ((U*)&x)->L[1] +#endif +#define dval(x) ((U*)&x)->d +#endif /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) */ -#if defined(IEEE_8087) + defined(VAX) +#if defined(IEEE_8087) + defined(IEEE_ARM) + defined(VAX) #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ ((unsigned short *)a)[0] = (unsigned short)c, a++) #else @@ -242,7 +280,7 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. /* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ /* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ -#if defined(IEEE_8087) + defined(IEEE_MC68k) +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) #define Exp_shift 20 #define Exp_shift1 20 #define Exp_msk1 0x100000 @@ -904,7 +942,7 @@ static double ulp(double x) } } #endif - return a; + return dval(a); } static double @@ -974,7 +1012,7 @@ ret_d: #undef d0 #undef d1 #endif - return d; + return dval(d); } static Bigint * @@ -1117,8 +1155,8 @@ ratio double da, db; PRInt32 k, ka, kb; - da = b2d(a, &ka); - db = b2d(b, &kb); + dval(da) = b2d(a, &ka); + dval(db) = b2d(b, &kb); #ifdef Pack_32 k = ka - kb + 32*(a->wds - b->wds); #else @@ -1128,13 +1166,13 @@ ratio if (k > 0) { word0(da) += (k >> 2)*Exp_msk1; if (k &= 3) - da *= 1 << k; + dval(da) *= 1 << k; } else { k = -k; word0(db) += (k >> 2)*Exp_msk1; if (k &= 3) - db *= 1 << k; + dval(db) *= 1 << k; } #else if (k > 0) @@ -1144,7 +1182,7 @@ ratio word0(db) += k*Exp_msk1; } #endif - return da / db; + return dval(da) / dval(db); } static CONST double @@ -1180,6 +1218,16 @@ void _PR_InitDtoa(void) p5s_lock = PR_NewLock(); } +void _PR_CleanupDtoa(void) +{ + PR_DestroyLock(freelist_lock); + freelist_lock = NULL; + PR_DestroyLock(p5s_lock); + p5s_lock = NULL; + + /* FIXME: deal with freelist and p5s. */ +} + #if defined(HAVE_WATCOM_BUG_1) PRFloat64 __pascal __loadds __export #else @@ -1199,7 +1247,7 @@ PR_strtod(CONST char *s00, char **se) if (!_pr_initialized) _PR_ImplicitInitialization(); sign = nz0 = nz = 0; - rv = 0.; + dval(rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': sign = 1; @@ -1321,9 +1369,9 @@ dig_done: if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; - rv = y; + dval(rv) = y; if (k > 9) - rv = tens[k - 9] * rv + z; + dval(rv) = tens[k - 9] * dval(rv) + z; bd0 = 0; if (nd <= DBL_DIG #ifndef RND_PRODQUOT @@ -1337,7 +1385,7 @@ dig_done: #ifdef VAX goto vax_ovfl_check; #else - /* rv = */ rounded_product(rv, tens[e]); + /* rv = */ rounded_product(dval(rv), tens[e]); goto ret; #endif } @@ -1347,27 +1395,27 @@ dig_done: * this for larger i values. */ e -= i; - rv *= tens[i]; + dval(rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: word0(rv) -= P*Exp_msk1; - /* rv = */ rounded_product(rv, tens[e]); + /* rv = */ rounded_product(dval(rv), tens[e]); if ((word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; word0(rv) += P*Exp_msk1; #else - /* rv = */ rounded_product(rv, tens[e]); + /* rv = */ rounded_product(dval(rv), tens[e]); #endif goto ret; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { - /* rv = */ rounded_quotient(rv, tens[-e]); + /* rv = */ rounded_quotient(dval(rv), tens[-e]); goto ret; } #endif @@ -1378,13 +1426,13 @@ dig_done: if (e1 > 0) { if ((i = e1 & 15) != 0) - rv *= tens[i]; + dval(rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: PR_SetError(PR_RANGE_ERROR, 0); #ifdef __STDC__ - rv = HUGE_VAL; + dval(rv) = HUGE_VAL; #else /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith @@ -1402,10 +1450,10 @@ dig_done: if (e1 >>= 4) { for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - rv *= bigtens[j]; + dval(rv) *= bigtens[j]; /* The last multiplication could overflow. */ word0(rv) -= P*Exp_msk1; - rv *= bigtens[j]; + dval(rv) *= bigtens[j]; if ((z = word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; @@ -1424,23 +1472,23 @@ dig_done: else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15) != 0) - rv /= tens[i]; + dval(rv) /= tens[i]; if (e1 &= ~15) { e1 >>= 4; if (e1 >= 1 << n_bigtens) goto undfl; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) - rv *= tinytens[j]; + dval(rv) *= tinytens[j]; /* The last multiplication could underflow. */ - rv0 = rv; - rv *= tinytens[j]; - if (!rv) { - rv = 2.*rv0; - rv *= tinytens[j]; - if (!rv) { + dval(rv0) = dval(rv); + dval(rv) *= tinytens[j]; + if (!dval(rv)) { + dval(rv) = 2.*dval(rv0); + dval(rv) *= tinytens[j]; + if (!dval(rv)) { undfl: - rv = 0.; + dval(rv) = 0.; PR_SetError(PR_RANGE_ERROR, 0); if (bd0) goto retfree; @@ -1464,7 +1512,7 @@ dig_done: for(;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); - bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { @@ -1576,12 +1624,12 @@ dig_done: break; #endif if (dsign) - rv += ulp(rv); + dval(rv) += ulp(dval(rv)); #ifndef ROUND_BIASED else { - rv -= ulp(rv); + dval(rv) -= ulp(dval(rv)); #ifndef Sudden_Underflow - if (!rv) + if (!dval(rv)) goto undfl; #endif } @@ -1632,10 +1680,10 @@ dig_done: /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - rv0 = rv; + dval(rv0) = dval(rv); word0(rv) -= P*Exp_msk1; - adj = aadj1 * ulp(rv); - rv += adj; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; if ((word0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(rv0) == Big0 && word1(rv0) == Big1) @@ -1650,10 +1698,10 @@ dig_done: else { #ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - rv0 = rv; + dval(rv0) = dval(rv); word0(rv) += P*Exp_msk1; - adj = aadj1 * ulp(rv); - rv += adj; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; #ifdef IBM if ((word0(rv) & Exp_mask) < P*Exp_msk1) #else @@ -1671,8 +1719,8 @@ dig_done: word0(rv) -= P*Exp_msk1; } else { - adj = aadj1 * ulp(rv); - rv += adj; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; } #else /* Compute adj so that the IEEE rounding rules will @@ -1687,8 +1735,8 @@ dig_done: if (!dsign) aadj1 = -aadj1; } - adj = aadj1 * ulp(rv); - rv += adj; + adj = aadj1 * ulp(dval(rv)); + dval(rv) += adj; #endif } z = word0(rv) & Exp_mask; @@ -1719,7 +1767,7 @@ retfree: ret: if (se) *se = (char *)s; - return sign ? -rv : rv; + return sign ? -dval(rv) : dval(rv); } static PRInt32 @@ -1952,9 +2000,9 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, } #endif #ifdef IBM - d += 0; /* normalize */ + dval(d) += 0; /* normalize */ #endif - if (!d) { + if (!dval(d)) { *decpt = 1; if (bufsize < 2) { PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); @@ -1968,18 +2016,18 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, return PR_SUCCESS; } - b = d2b(d, &be, &bbits); + b = d2b(dval(d), &be, &bbits); #ifdef Sudden_Underflow i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); #else if ((i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { #endif - d2 = d; + dval(d2) = dval(d); word0(d2) &= Frac_mask1; word0(d2) |= Exp_11; #ifdef IBM if (j = 11 - hi0bits(word0(d2) & Frac_mask)) - d2 /= 1 << j; + dval(d2) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 @@ -2018,19 +2066,19 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, i = bbits + be + (Bias + (P-1) - 1); x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) : word1(d) << (32 - i); - d2 = x; + dval(d2) = x; word0(d2) -= 31*Exp_msk1; /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } #endif - ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k = (PRInt32)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { - if (d < tens[k]) + if (dval(d) < tens[k]) k--; k_check = 0; } @@ -2097,7 +2145,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, /* Try to get by with floating-point arithmetic. */ i = 0; - d2 = d; + dval(d2) = dval(d); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ @@ -2107,7 +2155,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; - d /= bigtens[n_bigtens-1]; + dval(d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) @@ -2115,32 +2163,32 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, ieps++; ds *= bigtens[i]; } - d /= ds; + dval(d) /= ds; } else if ((j1 = -k) != 0) { - d *= tens[j1 & 0xf]; + dval(d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; - d *= bigtens[i]; + dval(d) *= bigtens[i]; } } - if (k_check && d < 1. && ilim > 0) { + if (k_check && dval(d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; - d *= 10.; + dval(d) *= 10.; ieps++; } - eps = ieps*d + 7.; + dval(eps) = ieps*dval(d) + 7.; word0(eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; - d -= 5.; - if (d > eps) + dval(d) -= 5.; + if (dval(d) > dval(eps)) goto one_digit; - if (d < -eps) + if (dval(d) < -dval(eps)) goto no_digits; goto fast_failed; } @@ -2149,33 +2197,33 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, /* Use Steele & White method of only * generating digits needed. */ - eps = 0.5/tens[ilim-1] - eps; + dval(eps) = 0.5/tens[ilim-1] - dval(eps); for(i = 0;;) { - L = (Long) d; - d -= L; + L = (Long) (dval(d)); + dval(d) -= L; *s++ = '0' + (PRInt32)L; - if (d < eps) + if (dval(d) < dval(eps)) goto ret1; - if (1. - d < eps) + if (1. - dval(d) < dval(eps)) goto bump_up; if (++i >= ilim) break; - eps *= 10.; - d *= 10.; + dval(eps) *= 10.; + dval(d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ - eps *= tens[ilim-1]; - for(i = 1;; i++, d *= 10.) { - L = (Long) d; - d -= L; + dval(eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(d) *= 10.) { + L = (Long) (dval(d)); + dval(d) -= L; *s++ = '0' + (PRInt32)L; if (i == ilim) { - if (d > 0.5 + eps) + if (dval(d) > 0.5 + dval(eps)) goto bump_up; - else if (d < 0.5 - eps) { + else if (dval(d) < 0.5 - dval(eps)) { while(*--s == '0'){} /* just count -- nothing to execute */ s++; goto ret1; @@ -2188,7 +2236,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, #endif fast_failed: s = s0; - d = d2; + dval(d) = dval(d2); k = k0; ilim = ilim0; } @@ -2200,24 +2248,24 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; - if (ilim < 0 || d <= 5*ds) + if (ilim < 0 || dval(d) <= 5*ds) goto no_digits; goto one_digit; } for(i = 1;; i++) { - L = (Long) (d / ds); - d -= L*ds; + L = (Long) (dval(d) / ds); + dval(d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (d < 0) { + if (dval(d) < 0) { L--; - d += ds; + dval(d) += ds; } #endif *s++ = '0' + (PRInt32)L; if (i == ilim) { - d += d; - if ((d > ds) || (d == ds && L & 1)) { + dval(d) += dval(d); + if ((dval(d) > ds) || (dval(d) == ds && L & 1)) { bump_up: while(*--s == '9') if (s == s0) { @@ -2229,7 +2277,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, } break; } - if (!(d *= 10.)) + if (!(dval(d) *= 10.)) break; } goto ret1; @@ -2514,7 +2562,7 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,double fval) return; } /* XXX Why use mode 1? */ - if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz) + if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz) == PR_FAILURE) { buf[0] = '\0'; goto done; diff --git a/pr/src/misc/prenv.c b/pr/src/misc/prenv.c index 75af10fb..fdcfb017 100644 --- a/pr/src/misc/prenv.c +++ b/pr/src/misc/prenv.c @@ -59,7 +59,7 @@ static PRLock *_pr_envLock = NULL; /************************************************************************/ -void _PR_InitEnv() +void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); } diff --git a/pr/src/misc/prerr.c b/pr/src/misc/prerr.c index 68bcc6ce..aaa1c38b 100644 --- a/pr/src/misc/prerr.c +++ b/pr/src/misc/prerr.c @@ -113,12 +113,13 @@ static const struct PRErrorMessage text[] = { {"PR_SOCKET_SHUTDOWN_ERROR", "Socket shutdown"}, {"PR_CONNECT_ABORTED_ERROR", "Connection aborted"}, {"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"}, + {"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"}, {"PR_MAX_ERROR", "Placeholder for the end of the list"}, {0, 0} }; -static const struct PRErrorTable et = { text, "prerr", -6000L, 75 }; +static const struct PRErrorTable et = { text, "prerr", -6000L, 76 }; -void nspr_InitializePRErrorTable() { +void nspr_InitializePRErrorTable(void) { PR_ErrorInstallTable(&et); } diff --git a/pr/src/misc/prerr.et b/pr/src/misc/prerr.et index e7e21305..9281ee6e 100644 --- a/pr/src/misc/prerr.et +++ b/pr/src/misc/prerr.et @@ -128,6 +128,7 @@ ec PR_NETWORK_DOWN_ERROR, "Network is down" ec PR_SOCKET_SHUTDOWN_ERROR, "Socket shutdown" ec PR_CONNECT_ABORTED_ERROR, "Connection aborted" ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable" +ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded" ec PR_MAX_ERROR, "Placeholder for the end of the list" diff --git a/pr/src/misc/prerr.properties b/pr/src/misc/prerr.properties index 652545e0..f6f0db26 100644 --- a/pr/src/misc/prerr.properties +++ b/pr/src/misc/prerr.properties @@ -32,7 +32,6 @@ # # -# # prerr.properties # This file is automatically generated; please do not edit it. PR_OUT_OF_MEMORY_ERROR=Memory allocation attempt failed @@ -109,4 +108,5 @@ PR_NETWORK_DOWN_ERROR=Network is down PR_SOCKET_SHUTDOWN_ERROR=Socket shutdown PR_CONNECT_ABORTED_ERROR=Connection aborted PR_HOST_UNREACHABLE_ERROR=Host is unreachable +PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded PR_MAX_ERROR=Placeholder for the end of the list diff --git a/pr/src/misc/prerror.c b/pr/src/misc/prerror.c index 8456d9d2..6e0d5f19 100644 --- a/pr/src/misc/prerror.c +++ b/pr/src/misc/prerror.c @@ -37,13 +37,13 @@ #include <string.h> #include <stdlib.h> -PR_IMPLEMENT(PRErrorCode) PR_GetError() +PR_IMPLEMENT(PRErrorCode) PR_GetError(void) { PRThread *thread = PR_GetCurrentThread(); return thread->errorCode; } -PR_IMPLEMENT(PRInt32) PR_GetOSError() +PR_IMPLEMENT(PRInt32) PR_GetOSError(void) { PRThread *thread = PR_GetCurrentThread(); return thread->osErrorCode; diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c index 6da27fa0..04c92226 100644 --- a/pr/src/misc/prinit.c +++ b/pr/src/misc/prinit.c @@ -161,7 +161,7 @@ static void _pr_SetNativeThreadsOnlyMode(void) #endif #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) -extern PRStatus _pr_init_ipv6(); +extern PRStatus _pr_init_ipv6(void); #endif static void _PR_InitStuff(void) @@ -169,6 +169,9 @@ static void _PR_InitStuff(void) if (_pr_initialized) return; _pr_initialized = PR_TRUE; +#ifdef _PR_ZONE_ALLOCATOR + _PR_InitZones(); +#endif #ifdef WINNT _pr_SetNativeThreadsOnlyMode(); #endif @@ -220,10 +223,6 @@ static void _PR_InitStuff(void) _PR_InitCPUs(); #endif -#ifdef _PR_ZONE_ALLOCATOR - _PR_InitZones(); -#endif - /* * XXX: call _PR_InitMem only on those platforms for which nspr implements * malloc, for now. @@ -251,7 +250,7 @@ static void _PR_InitStuff(void) _PR_MD_FINAL_INIT(); } -void _PR_ImplicitInitialization() +void _PR_ImplicitInitialization(void) { _PR_InitStuff(); @@ -417,9 +416,10 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup() PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0)); #endif -#if defined(WIN16) + _PR_CleanupMW(); + _PR_CleanupDtoa(); + _PR_CleanupCallOnce(); _PR_ShutdownLinker(); -#endif /* Release the primordial thread's private data, etc. */ _PR_CleanupThread(me); @@ -449,7 +449,11 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup() * Ideally, for each _PR_InitXXX(), there should be a corresponding * _PR_XXXCleanup() that we can call here. */ + _PR_CleanupNet(); _PR_CleanupIO(); +#ifdef WINNT + _PR_CleanupCPUs(); +#endif _PR_CleanupThreads(); PR_DestroyLock(_pr_sleeplock); _pr_sleeplock = NULL; @@ -561,7 +565,7 @@ PR_ProcessAttrSetCurrentDirectory( const char *dir) { PR_FREEIF(attr->currentDirectory); - attr->currentDirectory = PR_MALLOC(strlen(dir) + 1); + attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1); if (!attr->currentDirectory) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_FAILURE; @@ -776,13 +780,20 @@ static struct { PRCondVar *cv; } mod_init; -static void _PR_InitCallOnce() { +static void _PR_InitCallOnce(void) { mod_init.ml = PR_NewLock(); PR_ASSERT(NULL != mod_init.ml); mod_init.cv = PR_NewCondVar(mod_init.ml); PR_ASSERT(NULL != mod_init.cv); } +void _PR_CleanupCallOnce() +{ + PR_DestroyLock(mod_init.ml); + mod_init.ml = NULL; + PR_DestroyCondVar(mod_init.cv); + mod_init.cv = NULL; +} PR_IMPLEMENT(PRStatus) PR_CallOnce( PRCallOnceType *once, @@ -808,6 +819,31 @@ PR_IMPLEMENT(PRStatus) PR_CallOnce( return once->status; } +PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( + PRCallOnceType *once, + PRCallOnceWithArgFN func, + void *arg) +{ + if (!_pr_initialized) _PR_ImplicitInitialization(); + + if (!once->initialized) { + if (PR_AtomicSet(&once->inProgress, 1) == 0) { + once->status = (*func)(arg); + PR_Lock(mod_init.ml); + once->initialized = 1; + PR_NotifyAllCondVar(mod_init.cv); + PR_Unlock(mod_init.ml); + } else { + PR_Lock(mod_init.ml); + while (!once->initialized) { + PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); + } + PR_Unlock(mod_init.ml); + } + } + return once->status; +} + PRBool _PR_Obsolete(const char *obsolete, const char *preferred) { #if defined(DEBUG) diff --git a/pr/src/misc/prinrval.c b/pr/src/misc/prinrval.c index d0af3977..a319e8cb 100644 --- a/pr/src/misc/prinrval.c +++ b/pr/src/misc/prinrval.c @@ -68,13 +68,13 @@ void _PR_InitClock(void) * 2) The units here are milliseconds. That's not appropriate for our use. */ -PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow() +PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void) { if (!_pr_initialized) _PR_ImplicitInitialization(); return _PR_MD_GET_INTERVAL(); } /* PR_IntervalNow */ -PR_EXTERN(PRUint32) PR_TicksPerSecond() +PR_EXTERN(PRUint32) PR_TicksPerSecond(void) { if (!_pr_initialized) _PR_ImplicitInitialization(); return _PR_MD_INTERVAL_PER_SEC(); diff --git a/pr/src/misc/prlong.c b/pr/src/misc/prlong.c index df8d9e2e..31153293 100644 --- a/pr/src/misc/prlong.c +++ b/pr/src/misc/prlong.c @@ -37,6 +37,7 @@ static PRInt64 ll_zero = LL_INIT( 0x00000000,0x00000000 ); static PRInt64 ll_maxint = LL_INIT( 0x7fffffff, 0xffffffff ); static PRInt64 ll_minint = LL_INIT( 0x80000000, 0x00000000 ); +static PRUint64 ll_maxuint = LL_INIT( 0xffffffff, 0xffffffff ); #if defined(HAVE_WATCOM_BUG_2) PRInt64 __pascal __loadds __export @@ -45,10 +46,13 @@ PRInt64 __pascal __loadds __export LL_MaxInt(void) { return ll_maxint; } PRInt64 __pascal __loadds __export LL_MinInt(void) { return ll_minint; } +PRUint64 __pascal __loadds __export + LL_MaxUint(void) { return ll_maxuint; } #else PR_IMPLEMENT(PRInt64) LL_Zero(void) { return ll_zero; } PR_IMPLEMENT(PRInt64) LL_MaxInt(void) { return ll_maxint; } PR_IMPLEMENT(PRInt64) LL_MinInt(void) { return ll_minint; } +PR_IMPLEMENT(PRUint64) LL_MaxUint(void) { return ll_maxuint; } #endif #ifndef HAVE_LONG_LONG diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c index b40ca804..b26b7539 100644 --- a/pr/src/misc/prnetdb.c +++ b/pr/src/misc/prnetdb.c @@ -83,6 +83,12 @@ PRLock *_pr_dnsLock = NULL; * Some return a pointer to struct protoent, others return * an int. */ +#if defined(XP_BEOS) && defined(BONE_VERSION) +#include <arpa/inet.h> /* pick up define for inet_addr */ +#include <sys/socket.h> +#define _PR_HAVE_GETPROTO_R +#define _PR_HAVE_GETPROTO_R_POINTER +#endif #if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \ || (defined(LINUX) && defined(_REENTRANT) \ @@ -92,7 +98,7 @@ PRLock *_pr_dnsLock = NULL; #endif #if defined(OSF1) \ - || defined(AIX4_3) || (defined(AIX) && defined(_THREAD_SAFE)) \ + || defined(AIX4_3_PLUS) || (defined(AIX) && defined(_THREAD_SAFE)) \ || (defined(HPUX10_10) && defined(_REENTRANT)) \ || (defined(HPUX10_20) && defined(_REENTRANT)) #define _PR_HAVE_GETPROTO_R @@ -157,6 +163,250 @@ const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0, #define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3]) +#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) + +/* + * The _pr_QueryNetIfs() function finds out if the system has + * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if + * and _pr_have_inet6_if accordingly. + * + * We have an implementation using SIOCGIFCONF ioctl and a + * default implementation that simply sets _pr_have_inet_if + * and _pr_have_inet6_if to true. A better implementation + * would be to use the routing sockets (see Chapter 17 of + * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.) + */ + +static PRLock *_pr_query_ifs_lock = NULL; +static PRBool _pr_have_inet_if = PR_FALSE; +static PRBool _pr_have_inet6_if = PR_FALSE; + +#undef DEBUG_QUERY_IFS + +#if defined(AIX) \ + || (defined(DARWIN) && (!defined(HAVE_GETIFADDRS) \ + || (defined(MACOS_DEPLOYMENT_TARGET) \ + && MACOS_DEPLOYMENT_TARGET < 100200))) + +/* + * Use SIOCGIFCONF ioctl on platforms that don't have routing + * sockets. Warning: whether SIOCGIFCONF ioctl returns AF_INET6 + * network interfaces is not portable. + * + * The _pr_QueryNetIfs() function is derived from the code in + * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in + * Section 16.6 of W. Richard Stevens' Unix Network Programming, + * Vol. 1, 2nd. Ed. + */ + +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <net/if.h> + +#ifdef DEBUG_QUERY_IFS +static void +_pr_PrintIfreq(struct ifreq *ifr) +{ + PRNetAddr addr; + struct sockaddr *sa; + const char* family; + char addrstr[64]; + + sa = &ifr->ifr_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + family = "inet"; + memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr)); + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + family = "inet6"; + memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr)); + } else { + return; /* skip if not AF_INET or AF_INET6 */ + } + addr.raw.family = sa->sa_family; + PR_NetAddrToString(&addr, addrstr, sizeof(addrstr)); + printf("%s: %s %s\n", ifr->ifr_name, family, addrstr); +} +#endif + +static void +_pr_QueryNetIfs(void) +{ + int sock; + int rv; + struct ifconf ifc; + struct ifreq *ifr; + struct ifreq *lifr; + PRUint32 len, lastlen; + char *buf; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + return; + } + + /* Issue SIOCGIFCONF request in a loop. */ + lastlen = 0; + len = 100 * sizeof(struct ifreq); /* initial buffer size guess */ + for (;;) { + buf = (char *)PR_Malloc(len); + if (NULL == buf) { + close(sock); + return; + } + ifc.ifc_buf = buf; + ifc.ifc_len = len; + rv = ioctl(sock, SIOCGIFCONF, &ifc); + if (rv < 0) { + if (errno != EINVAL || lastlen != 0) { + close(sock); + PR_Free(buf); + return; + } + } else { + if (ifc.ifc_len == lastlen) + break; /* success, len has not changed */ + lastlen = ifc.ifc_len; + } + len += 10 * sizeof(struct ifreq); /* increment */ + PR_Free(buf); + } + close(sock); + + ifr = ifc.ifc_req; + lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; + + while (ifr < lifr) { + struct sockaddr *sa; + int sa_len; + +#ifdef DEBUG_QUERY_IFS + _pr_PrintIfreq(ifr); +#endif + sa = &ifr->ifr_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { + _pr_have_inet_if = PR_TRUE; + } + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + _pr_have_inet6_if = PR_TRUE; + } + } + +#ifdef _PR_HAVE_SOCKADDR_LEN + sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr)); +#else + switch (sa->sa_family) { +#ifdef AF_LINK + case AF_LINK: + sa_len = sizeof(struct sockaddr_dl); + break; +#endif + case AF_INET6: + sa_len = sizeof(struct sockaddr_in6); + break; + default: + sa_len = sizeof(struct sockaddr); + break; + } +#endif + ifr = (struct ifreq *)(((char *)sa) + sa_len); + } + PR_Free(buf); +} + +#elif (defined(DARWIN) && defined(HAVE_GETIFADDRS)) || defined(FREEBSD) \ + || defined(NETBSD) || defined(OPENBSD) + +/* + * Use the BSD getifaddrs function. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <ifaddrs.h> +#include <netinet/in.h> + +#ifdef DEBUG_QUERY_IFS +static void +_pr_PrintIfaddrs(struct ifaddrs *ifa) +{ + struct sockaddr *sa; + const char* family; + void *addrp; + char addrstr[64]; + + sa = ifa->ifa_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + family = "inet"; + addrp = &sin->sin_addr; + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + family = "inet6"; + addrp = &sin6->sin6_addr; + } else { + return; /* skip if not AF_INET or AF_INET6 */ + } + inet_ntop(sa->sa_family, addrp, addrstr, sizeof(addrstr)); + printf("%s: %s %s\n", ifa->ifa_name, family, addrstr); +} +#endif + +static void +_pr_QueryNetIfs(void) +{ + struct ifaddrs *ifp; + struct ifaddrs *ifa; + + if (getifaddrs(&ifp) == -1) { + return; + } + for (ifa = ifp; ifa; ifa = ifa->ifa_next) { + struct sockaddr *sa; + +#ifdef DEBUG_QUERY_IFS + _pr_PrintIfaddrs(ifa); +#endif + sa = ifa->ifa_addr; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { + _pr_have_inet_if = 1; + } + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + _pr_have_inet6_if = 1; + } + } + } + freeifaddrs(ifp); +} + +#else /* default */ + +/* + * Emulate the code in NSPR 4.2 or older. PR_GetIPNodeByName behaves + * as if the system had both IPv4 and IPv6 source addresses configured. + */ +static void +_pr_QueryNetIfs(void) +{ + _pr_have_inet_if = PR_TRUE; + _pr_have_inet6_if = PR_TRUE; +} + +#endif + +#endif /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */ + void _PR_InitNet(void) { #if defined(XP_UNIX) @@ -174,6 +424,31 @@ void _PR_InitNet(void) #if !defined(_PR_HAVE_GETPROTO_R) _getproto_lock = PR_NewLock(); #endif +#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) + _pr_query_ifs_lock = PR_NewLock(); +#endif +} + +void _PR_CleanupNet(void) +{ +#if !defined(_PR_NO_DNS_LOCK) + if (_pr_dnsLock) { + PR_DestroyLock(_pr_dnsLock); + _pr_dnsLock = NULL; + } +#endif +#if !defined(_PR_HAVE_GETPROTO_R) + if (_getproto_lock) { + PR_DestroyLock(_getproto_lock); + _getproto_lock = NULL; + } +#endif +#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) + if (_pr_query_ifs_lock) { + PR_DestroyLock(_pr_query_ifs_lock); + _pr_query_ifs_lock = NULL; + } +#endif } /* @@ -215,7 +490,6 @@ static void MakeIPv4MappedAddr(const char *v4, char *v6) memset(v6, 0, 10); memset(v6 + 10, 0xff, 2); memcpy(v6 + 12, v4, 4); - PR_ASSERT(_PR_IN6_IS_ADDR_V4MAPPED(((PRIPv6Addr *) v6))); } /* @@ -225,7 +499,6 @@ static void MakeIPv4CompatAddr(const char *v4, char *v6) { memset(v6, 0, 12); memcpy(v6 + 12, v4, 4); - PR_ASSERT(_PR_IN6_IS_ADDR_V4COMPAT(((PRIPv6Addr *) v6))); } /* @@ -406,7 +679,7 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { - tmpbuf = PR_Malloc(bufsize); + tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); @@ -442,15 +715,51 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( return rv; } -#if defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) +#if !defined(_PR_INET6) && \ + defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) typedef struct hostent * (*_pr_getipnodebyname_t)(const char *, int, int, int *); typedef struct hostent * (*_pr_getipnodebyaddr_t)(const void *, size_t, int, int *); typedef void (*_pr_freehostent_t)(struct hostent *); -extern void * _pr_getipnodebyname_fp; -extern void * _pr_getipnodebyaddr_fp; -extern void * _pr_freehostent_fp; +static void * _pr_getipnodebyname_fp; +static void * _pr_getipnodebyaddr_fp; +static void * _pr_freehostent_fp; + +/* + * Look up the addresses of getipnodebyname, getipnodebyaddr, + * and freehostent. + */ +PRStatus +_pr_find_getipnodebyname(void) +{ + PRLibrary *lib; + PRStatus rv; +#if defined(VMS) +#define GETIPNODEBYNAME getenv("GETIPNODEBYNAME") +#define GETIPNODEBYADDR getenv("GETIPNODEBYADDR") +#define FREEHOSTENT getenv("FREEHOSTENT") +#else +#define GETIPNODEBYNAME "getipnodebyname" +#define GETIPNODEBYADDR "getipnodebyaddr" +#define FREEHOSTENT "freehostent" +#endif + _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib); + if (NULL != _pr_getipnodebyname_fp) { + _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT); + if (NULL != _pr_freehostent_fp) { + _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR); + if (NULL != _pr_getipnodebyaddr_fp) + rv = PR_SUCCESS; + else + rv = PR_FAILURE; + } else + rv = PR_FAILURE; + (void)PR_UnloadLibrary(lib); + } else + rv = PR_FAILURE; + return rv; +} #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) @@ -521,6 +830,25 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( return PR_FAILURE; } +#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) + PR_Lock(_pr_query_ifs_lock); + /* + * Keep querying the presence of IPv4 and IPv6 interfaces until + * at least one is up. This allows us to detect the local + * machine going from offline to online. + */ + if (!_pr_have_inet_if && !_pr_have_inet6_if) { + _pr_QueryNetIfs(); +#ifdef DEBUG_QUERY_IFS + if (_pr_have_inet_if) + printf("Have IPv4 source address\n"); + if (_pr_have_inet6_if) + printf("Have IPv6 source address\n"); +#endif + } + PR_Unlock(_pr_query_ifs_lock); +#endif + #if defined(_PR_HAVE_GETIPNODEBYNAME) if (flags & PR_AI_V4MAPPED) tmp_flags |= AI_V4MAPPED; @@ -538,7 +866,7 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { - tmpbuf = PR_Malloc(bufsize); + tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); @@ -553,11 +881,15 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( LOCK_DNS(); if (af == PR_AF_INET6) { + if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet6_if) + { #ifdef _PR_INET6_PROBE - if (_pr_ipv6_is_present == PR_TRUE) + if (_pr_ipv6_is_present == PR_TRUE) #endif - h = GETHOSTBYNAME2(name, AF_INET6); - if ((NULL == h) && (flags & PR_AI_V4MAPPED)) + h = GETHOSTBYNAME2(name, AF_INET6); + } + if ((NULL == h) && (flags & PR_AI_V4MAPPED) + && ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if)) { did_af_inet = PR_TRUE; h = GETHOSTBYNAME2(name, AF_INET); @@ -565,8 +897,11 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( } else { - did_af_inet = PR_TRUE; - h = GETHOSTBYNAME2(name, af); + if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if) + { + did_af_inet = PR_TRUE; + h = GETHOSTBYNAME2(name, af); + } } #elif defined(_PR_HAVE_GETIPNODEBYNAME) h = getipnodebyname(name, md_af, tmp_flags, &error_num); @@ -575,7 +910,12 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( #endif /* _PR_HAVE_GETHOSTBYNAME2 */ #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) if (_pr_ipv6_is_present == PR_TRUE) + { +#ifdef PR_GETIPNODE_NOT_THREADSAFE + LOCK_DNS(); +#endif h = (*((_pr_getipnodebyname_t)_pr_getipnodebyname_fp))(name, md_af, tmp_flags, &error_num); + } else { LOCK_DNS(); @@ -619,7 +959,8 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED) - && (flags & (PR_AI_ALL|PR_AI_ADDRCONFIG)) + && ((flags & PR_AI_ALL) + || ((flags & PR_AI_ADDRCONFIG) && _pr_have_inet_if)) && !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)) != 0) { rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp); if (PR_SUCCESS != rv) @@ -634,8 +975,12 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( UNLOCK_DNS(); #endif /* _PR_HAVE_GETHOSTBYNAME2 */ #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) +#ifdef PR_GETIPNODE_NOT_THREADSAFE + UNLOCK_DNS(); +#else if (_pr_ipv6_is_present == PR_FALSE) UNLOCK_DNS(); +#endif #else /* _PR_INET6 */ UNLOCK_DNS(); #endif /* _PR_INET6 */ @@ -681,6 +1026,10 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( #else af = AF_INET; #endif +#if defined(_PR_GHBA_DISALLOW_V4MAPPED) + if (_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) + af = AF_INET; +#endif } else { @@ -717,7 +1066,7 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { - tmpbuf = PR_Malloc(bufsize); + tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); @@ -731,8 +1080,13 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( h = getipnodebyaddr(addr, addrlen, af, &error_num); #elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE) if (_pr_ipv6_is_present == PR_TRUE) + { +#ifdef PR_GETIPNODE_NOT_THREADSAFE + LOCK_DNS(); +#endif h = (*((_pr_getipnodebyaddr_t)_pr_getipnodebyaddr_fp))(addr, addrlen, af, &error_num); + } else { LOCK_DNS(); @@ -788,8 +1142,12 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( /* Must match the convoluted logic above for LOCK_DNS() */ #if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6) #elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE) +#ifdef PR_GETIPNODE_NOT_THREADSAFE + UNLOCK_DNS(); +#else if (_pr_ipv6_is_present == PR_FALSE) UNLOCK_DNS(); +#endif #else /* _PR_HAVE_GETIPNODEBYADDR */ UNLOCK_DNS(); #endif /* _PR_HAVE_GETIPNODEBYADDR */ @@ -1015,7 +1373,7 @@ PRUintn _PR_NetAddrSize(const PRNetAddr* addr) #else addrsize = sizeof(addr->ipv6); #endif -#if defined(XP_UNIX) +#if defined(XP_UNIX) || defined(XP_OS2) else if (AF_UNIX == addr->raw.family) addrsize = sizeof(addr->local); #endif @@ -1164,7 +1522,7 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) return PR_FALSE; } -#ifndef _PR_INET6 +#ifndef _PR_HAVE_INET_NTOP #define XX 127 static const unsigned char index_hex[256] = { XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, @@ -1404,14 +1762,14 @@ static const char *V6AddrToString( #undef STUFF } -#endif /* !_PR_INET6 */ +#endif /* !_PR_HAVE_INET_NTOP */ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) { PRStatus status = PR_SUCCESS; PRIntn rv; -#if defined(_PR_INET6) +#if defined(_PR_HAVE_INET_NTOP) rv = inet_pton(AF_INET6, string, &addr->ipv6.ip); if (1 == rv) { @@ -1434,7 +1792,7 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) status = PR_FAILURE; } } -#else /* _PR_INET6 */ +#else /* _PR_HAVE_INET_NTOP */ rv = StringToV6Addr(string, &addr->ipv6.ip); if (1 == rv) { addr->raw.family = PR_AF_INET6; @@ -1458,7 +1816,7 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); status = PR_FAILURE; } -#endif /* _PR_INET6 */ +#endif /* _PR_HAVE_INET_NTOP */ return status; } @@ -1468,7 +1826,7 @@ PR_IMPLEMENT(PRStatus) PR_NetAddrToString( { if (PR_AF_INET6 == addr->raw.family) { -#if defined(_PR_INET6) +#if defined(_PR_HAVE_INET_NTOP) if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size)) #else if (NULL == V6AddrToString(&addr->ipv6.ip, string, size)) @@ -1554,3 +1912,268 @@ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n) return n; #endif } /* htonll */ + + +/* + * Implementation of PR_GetAddrInfoByName and friends + * + * Compile-time options: + * + * _PR_HAVE_GETADDRINFO Define this macro if the target system provides + * getaddrinfo. With this defined, NSPR will require + * getaddrinfo at run time. If this if not defined, + * then NSPR will attempt to dynamically resolve + * getaddrinfo, falling back to PR_GetHostByName if + * getaddrinfo does not exist on the target system. + * + * Since getaddrinfo is a relatively new system call on many systems, + * we are forced to dynamically resolve it at run time in most cases. + * The exception includes any system (such as Mac OS X) that is known to + * provide getaddrinfo in all versions that NSPR cares to support. + */ + +#if defined(_PR_HAVE_GETADDRINFO) + +#if defined(_PR_INET6) + +typedef struct addrinfo PRADDRINFO; +#define GETADDRINFO getaddrinfo +#define FREEADDRINFO freeaddrinfo + +#elif defined(_PR_INET6_PROBE) + +typedef struct addrinfo PRADDRINFO; + +/* getaddrinfo/freeaddrinfo prototypes */ +#if defined(WIN32) +#define FUNC_MODIFIER __stdcall +#else +#define FUNC_MODIFIER +#endif +typedef int (FUNC_MODIFIER * FN_GETADDRINFO) + (const char *nodename, + const char *servname, + const PRADDRINFO *hints, + PRADDRINFO **res); +typedef int (FUNC_MODIFIER * FN_FREEADDRINFO) + (PRADDRINFO *ai); + +/* global state */ +static FN_GETADDRINFO _pr_getaddrinfo = NULL; +static FN_FREEADDRINFO _pr_freeaddrinfo = NULL; + +#if defined(VMS) +#define GETADDRINFO_SYMBOL getenv("GETADDRINFO") +#define FREEADDRINFO_SYMBOL getenv("FREEADDRINFO") +#else +#define GETADDRINFO_SYMBOL "getaddrinfo" +#define FREEADDRINFO_SYMBOL "freeaddrinfo" +#endif + +PRStatus +_pr_find_getaddrinfo(void) +{ + PRLibrary *lib; +#ifdef WIN32 + /* + * On windows, we need to search ws2_32.dll for getaddrinfo and + * freeaddrinfo. This library might not be loaded yet. + */ + lib = PR_LoadLibrary("ws2_32.dll"); + if (!lib) { + return PR_FAILURE; + } + _pr_getaddrinfo = (FN_GETADDRINFO) + PR_FindFunctionSymbol(lib, GETADDRINFO_SYMBOL); + _pr_freeaddrinfo = (FN_FREEADDRINFO) + PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL); + if (!_pr_getaddrinfo || !_pr_freeaddrinfo) { + PR_UnloadLibrary(lib); + return PR_FAILURE; + } + /* Keep ws2_32.dll loaded. */ + return PR_SUCCESS; +#else + /* + * Resolve getaddrinfo by searching all loaded libraries. Then + * search library containing getaddrinfo for freeaddrinfo. + */ + _pr_getaddrinfo = (FN_GETADDRINFO) + PR_FindFunctionSymbolAndLibrary(GETADDRINFO_SYMBOL, &lib); + if (!_pr_getaddrinfo) { + return PR_FAILURE; + } + _pr_freeaddrinfo = (FN_FREEADDRINFO) + PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL); + PR_UnloadLibrary(lib); + if (!_pr_freeaddrinfo) { + return PR_FAILURE; + } + return PR_SUCCESS; +#endif +} + +#define GETADDRINFO (*_pr_getaddrinfo) +#define FREEADDRINFO (*_pr_freeaddrinfo) + +#endif /* _PR_INET6 */ + +#endif /* _PR_HAVE_GETADDRINFO */ + +/* + * If getaddrinfo does not exist, then we will fall back on + * PR_GetHostByName, which requires that we allocate a buffer for the + * PRHostEnt data structure and its members. + */ +typedef struct PRAddrInfoFB { + char buf[PR_NETDB_BUF_SIZE]; + PRHostEnt hostent; +} PRAddrInfoFB; + +static PRAddrInfo * +pr_GetAddrInfoByNameFB(const char *hostname, + PRUint16 af, + PRIntn flags) +{ + PRStatus rv; + PRAddrInfoFB *ai; + /* fallback on PR_GetHostByName */ + ai = PR_NEW(PRAddrInfoFB); + if (!ai) { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent); + if (rv == PR_FAILURE) { + PR_Free(ai); + return NULL; + } + return (PRAddrInfo *) ai; +} + +PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname, + PRUint16 af, + PRIntn flags) +{ + /* restrict input to supported values */ + if ((af != PR_AF_INET && af != PR_AF_UNSPEC) || flags != PR_AI_ADDRCONFIG) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return NULL; + } + + if (!_pr_initialized) _PR_ImplicitInitialization(); + +#if !defined(_PR_HAVE_GETADDRINFO) + return pr_GetAddrInfoByNameFB(hostname, af, flags); +#else +#if defined(_PR_INET6_PROBE) + if (!_pr_ipv6_is_present) { + return pr_GetAddrInfoByNameFB(hostname, af, flags); + } +#endif + { + PRADDRINFO *res, hints; + PRStatus rv; + + /* + * we assume a RFC 2553 compliant getaddrinfo. this may at some + * point need to be customized as platforms begin to adopt the + * RFC 3493. + */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = (af == PR_AF_INET) ? AF_INET : AF_UNSPEC; + + /* + * it is important to select a socket type in the hints, otherwise we + * will get back repetitive entries: one for each socket type. since + * we do not expose ai_socktype through our API, it is okay to do this + * here. the application may still choose to create a socket of some + * other type. + */ + hints.ai_socktype = SOCK_STREAM; + + rv = GETADDRINFO(hostname, NULL, &hints, &res); + if (rv == 0) + return (PRAddrInfo *) res; + + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv); + } + return NULL; +#endif +} + +PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai) +{ +#if defined(_PR_HAVE_GETADDRINFO) +#if defined(_PR_INET6_PROBE) + if (!_pr_ipv6_is_present) + PR_Free((PRAddrInfoFB *) ai); + else +#endif + FREEADDRINFO((PRADDRINFO *) ai); +#else + PR_Free((PRAddrInfoFB *) ai); +#endif +} + +PR_IMPLEMENT(void *) PR_EnumerateAddrInfo(void *iterPtr, + const PRAddrInfo *base, + PRUint16 port, + PRNetAddr *result) +{ +#if defined(_PR_HAVE_GETADDRINFO) + PRADDRINFO *ai; +#if defined(_PR_INET6_PROBE) + if (!_pr_ipv6_is_present) { + /* using PRAddrInfoFB */ + PRIntn iter = (PRIntn) iterPtr; + iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result); + if (iter < 0) + iter = 0; + return (void *) iter; + } +#endif + + if (iterPtr) + ai = ((PRADDRINFO *) iterPtr)->ai_next; + else + ai = (PRADDRINFO *) base; + + if (ai) { + /* copy sockaddr to PRNetAddr */ + memcpy(result, ai->ai_addr, ai->ai_addrlen); + result->raw.family = ai->ai_addr->sa_family; + if (ai->ai_addrlen < sizeof(PRNetAddr)) + memset(((char*)result)+ai->ai_addrlen, 0, sizeof(PRNetAddr) - ai->ai_addrlen); + + if (result->raw.family == PR_AF_INET) + result->inet.port = htons(port); + else + result->ipv6.port = htons(port); + } + + return ai; +#else + /* using PRAddrInfoFB */ + PRIntn iter = (PRIntn) iterPtr; + iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result); + if (iter < 0) + iter = 0; + return (void *) iter; +#endif +} + +PR_IMPLEMENT(const char *) PR_GetCanonNameFromAddrInfo(const PRAddrInfo *ai) +{ +#if defined(_PR_HAVE_GETADDRINFO) +#if defined(_PR_INET6_PROBE) + if (!_pr_ipv6_is_present) + return ((const PRAddrInfoFB *) ai)->hostent.h_name; +#endif + return ((const PRADDRINFO *) ai)->ai_canonname; +#else + return ((const PRAddrInfoFB *) ai)->hostent.h_name; +#endif +} diff --git a/pr/src/misc/prolock.c b/pr/src/misc/prolock.c index a2a50ced..e8384879 100644 --- a/pr/src/misc/prolock.c +++ b/pr/src/misc/prolock.c @@ -38,7 +38,6 @@ ** Implement the API defined in prolock.h ** */ -#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #include "prolock.h" #include "prlog.h" #include "prerror.h" @@ -96,13 +95,3 @@ PR_IMPLEMENT(PRStatus) 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 -** -*/ - -/* Some compilers don't like an empty compilation unit. */ -static int dummy = 0; -#endif /* defined(FORCE_NSPR_ORDERED_LOCK */ diff --git a/pr/src/misc/prrng.c b/pr/src/misc/prrng.c index bc6c0cd8..480b347d 100644 --- a/pr/src/misc/prrng.c +++ b/pr/src/misc/prrng.c @@ -34,6 +34,16 @@ #include "primpl.h" +/* + * We were not including <string.h> in optimized builds. On AIX this + * caused libnspr4.so to export memcpy and some binaries linked with + * libnspr4.so resolved their memcpy references with libnspr4.so. To + * be backward compatible with old libnspr4.so binaries, we do not + * include <string.h> in optimized builds for AIX. (bug 200561) + */ +#if !(defined(AIX) && !defined(DEBUG)) +#include <string.h> +#endif PRSize _pr_CopyLowBits( void *dst, diff --git a/pr/src/misc/prsystem.c b/pr/src/misc/prsystem.c index bb786766..edf5dbd0 100644 --- a/pr/src/misc/prsystem.c +++ b/pr/src/misc/prsystem.c @@ -58,7 +58,7 @@ #endif #if defined(HPUX) -#include <sys/mp.h> +#include <sys/mpctl.h> #endif #if defined(XP_UNIX) @@ -66,7 +66,7 @@ #include <sys/utsname.h> #endif -PR_IMPLEMENT(char) PR_GetDirectorySeparator() +PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) { return PR_DIRECTORY_SEPARATOR; } /* PR_GetDirectorySeparator */ @@ -74,7 +74,7 @@ PR_IMPLEMENT(char) PR_GetDirectorySeparator() /* ** OBSOLETE -- the function name is misspelled. */ -PR_IMPLEMENT(char) PR_GetDirectorySepartor() +PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) { #if defined(DEBUG) static PRBool warn = PR_TRUE; @@ -86,6 +86,11 @@ PR_IMPLEMENT(char) PR_GetDirectorySepartor() return PR_GetDirectorySeparator(); } /* PR_GetDirectorySepartor */ +PR_IMPLEMENT(char) PR_GetPathSeparator(void) +{ + return PR_PATH_SEPARATOR; +} /* PR_GetPathSeparator */ + PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen) { PRUintn len = 0; @@ -97,6 +102,12 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle case PR_SI_HOSTNAME: if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) return PR_FAILURE; + /* + * On some platforms a system does not have a hostname and + * its IP address is returned instead. The following code + * should be skipped on those platforms. + */ +#ifndef _PR_GET_HOST_ADDR_AS_NAME /* Return the unqualified hostname */ while (buf[len] && (len < buflen)) { if (buf[len] == '.') { @@ -105,6 +116,7 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle } len += 1; } +#endif break; case PR_SI_SYSNAME: @@ -150,7 +162,6 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; - break; } return PR_SUCCESS; } diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c index 0aa6e46c..3eae35c7 100644 --- a/pr/src/misc/prtime.c +++ b/pr/src/misc/prtime.c @@ -637,6 +637,7 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) PRTime secs64; PRInt64 usecPerSec; PRInt64 maxInt32; + PRInt64 minInt32; PRInt32 dayOffset; PRInt32 offset2Jan1970; PRInt32 offsetNew; @@ -682,9 +683,10 @@ PR_LocalTimeParameters(const PRExplodedTime *gmt) secs64 = PR_ImplodeTime(gmt); /* This is still in microseconds */ LL_I2L(usecPerSec, PR_USEC_PER_SEC); LL_DIV(secs64, secs64, usecPerSec); /* Convert to seconds */ - LL_I2L(maxInt32, 0x7fffffff); - if (LL_CMP(secs64, >, maxInt32)) { - /* secs64 is too large for time_t (32-bit integer) */ + LL_I2L(maxInt32, PR_INT32_MAX); + LL_I2L(minInt32, PR_INT32_MIN); + if (LL_CMP(secs64, >, maxInt32) || LL_CMP(secs64, <, minInt32)) { + /* secs64 is too large or too small for time_t (32-bit integer) */ retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = 0; return retVal; @@ -774,7 +776,7 @@ PR_IMPLEMENT(PRTimeParameters) PR_USPacificTimeParameters(const PRExplodedTime *gmt) { PRTimeParameters retVal; - PRExplodedTime std; + PRExplodedTime st; /* * Based on geographic location and GMT, figure out offset of @@ -789,32 +791,32 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) * is ignored. */ - std.tm_usec = gmt->tm_usec; - std.tm_sec = gmt->tm_sec; - std.tm_min = gmt->tm_min; - std.tm_hour = gmt->tm_hour; - std.tm_mday = gmt->tm_mday; - std.tm_month = gmt->tm_month; - std.tm_year = gmt->tm_year; - std.tm_wday = gmt->tm_wday; - std.tm_yday = gmt->tm_yday; + st.tm_usec = gmt->tm_usec; + st.tm_sec = gmt->tm_sec; + st.tm_min = gmt->tm_min; + st.tm_hour = gmt->tm_hour; + st.tm_mday = gmt->tm_mday; + st.tm_month = gmt->tm_month; + st.tm_year = gmt->tm_year; + st.tm_wday = gmt->tm_wday; + st.tm_yday = gmt->tm_yday; /* Apply the offset to GMT to obtain the local standard time */ - ApplySecOffset(&std, retVal.tp_gmt_offset); + ApplySecOffset(&st, retVal.tp_gmt_offset); /* * Apply the rules on standard time or GMT to obtain daylight saving * time offset. In this implementation, we use the US DST rule. */ - if (std.tm_month < 3) { + if (st.tm_month < 3) { retVal.tp_dst_offset = 0L; - } else if (std.tm_month == 3) { - if (std.tm_wday == 0) { + } else if (st.tm_month == 3) { + if (st.tm_wday == 0) { /* A Sunday */ - if (std.tm_mday <= 7) { + if (st.tm_mday <= 7) { /* First Sunday */ /* 01:59:59 PST -> 03:00:00 PDT */ - if (std.tm_hour < 2) { + if (st.tm_hour < 2) { retVal.tp_dst_offset = 0L; } else { retVal.tp_dst_offset = 3600L; @@ -825,7 +827,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) } } else { /* Not a Sunday. See if before first Sunday or after */ - if (std.tm_wday + 1 <= std.tm_mday) { + if (st.tm_wday + 1 <= st.tm_mday) { /* After first Sunday */ retVal.tp_dst_offset = 3600L; } else { @@ -833,14 +835,14 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) retVal.tp_dst_offset = 0L; } } - } else if (std.tm_month < 9) { + } else if (st.tm_month < 9) { retVal.tp_dst_offset = 3600L; - } else if (std.tm_month == 9) { - if (std.tm_wday == 0) { - if (31 - std.tm_mday < 7) { + } else if (st.tm_month == 9) { + if (st.tm_wday == 0) { + if (31 - st.tm_mday < 7) { /* Last Sunday */ /* 01:59:59 PDT -> 01:00:00 PST */ - if (std.tm_hour < 1) { + if (st.tm_hour < 1) { retVal.tp_dst_offset = 3600L; } else { retVal.tp_dst_offset = 0L; @@ -851,7 +853,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt) } } else { /* See if before or after last Sunday */ - if (7 - std.tm_wday <= 31 - std.tm_mday) { + if (7 - st.tm_wday <= 31 - st.tm_mday) { /* before last Sunday */ retVal.tp_dst_offset = 3600L; } else { @@ -1662,15 +1664,14 @@ PR_FormatTime(char *buf, int buflen, const char *fmt, const PRExplodedTime *tm) /* * 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. + * fields: tm_zone and tm_gmtoff. */ -#if defined(SUNOS4) || (__GLIBC__ >= 2) || defined(XP_BEOS) - if (mktime(&a) == -1) { - PR_snprintf(buf, buflen, "can't get timezone"); - return 0; - } +#if defined(SUNOS4) || (__GLIBC__ >= 2) || defined(XP_BEOS) \ + || defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) \ + || defined(DARWIN) + a.tm_zone = NULL; + a.tm_gmtoff = tm->tm_params.tp_gmt_offset + tm->tm_params.tp_dst_offset; #endif return strftime(buf, buflen, fmt, &a); diff --git a/pr/src/misc/prtpool.c b/pr/src/misc/prtpool.c index 2f43c676..d0816b30 100644 --- a/pr/src/misc/prtpool.c +++ b/pr/src/misc/prtpool.c @@ -166,7 +166,7 @@ struct PRJob { PR_END_MACRO static void delete_job(PRJob *jobp); -static PRThreadPool * alloc_threadpool(); +static PRThreadPool * alloc_threadpool(void); static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp); static void notify_ioq(PRThreadPool *tp); static void notify_timerq(PRThreadPool *tp); @@ -599,11 +599,11 @@ delete_threadpool(PRThreadPool *tp) } static PRThreadPool * -alloc_threadpool() +alloc_threadpool(void) { PRThreadPool *tp; - tp = PR_CALLOC(sizeof(*tp)); + tp = (PRThreadPool *) PR_CALLOC(sizeof(*tp)); if (NULL == tp) goto failed; tp->jobq.lock = PR_NewLock(); diff --git a/pr/src/misc/prtrace.c b/pr/src/misc/prtrace.c index 72b9c52d..f861557c 100644 --- a/pr/src/misc/prtrace.c +++ b/pr/src/misc/prtrace.c @@ -41,7 +41,6 @@ ** */ -#if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #include <string.h> #include "prtrace.h" #include "prclist.h" @@ -917,14 +916,4 @@ PR_IMPLEMENT(PRIntn) return rc; } /* end PR_GetTraceEntries() */ -#else /* !defined(FORCE_NSPR_TRACE) */ -/* -** The trace facility is not defined when !DEBUG and !FORCE_NSPR_TRACE -** -*/ - -/* Some compilers don't like an empty compilation unit. */ -static int dummy = 0; -#endif /* defined(FORCE_NSPR_TRACE) */ - /* end prtrace.c */ diff --git a/pr/src/nspr.def b/pr/src/nspr.def new file mode 100644 index 00000000..144df2ca --- /dev/null +++ b/pr/src/nspr.def @@ -0,0 +1,457 @@ +;+# +;+# The contents of this file are subject to the Mozilla Public +;+# License Version 1.1 (the "License"); you may not use this file +;+# except in compliance with the License. You may obtain a copy of +;+# the License at http://www.mozilla.org/MPL/ +;+# +;+# Software distributed under the License is distributed on an "AS +;+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +;+# implied. See the License for the specific language governing +;+# rights and limitations under the License. +;+# +;+# The Original Code is the Netscape Portable Runtime (NSPR). +;+# +;+# The Initial Developer of the Original Code is Netscape +;+# Communications Corporation. Portions created by Netscape are +;+# Copyright (C) 2002-2003 Netscape Communications Corporation. All +;+# Rights Reserved. +;+# +;+# Contributor(s): +;+# +;+# Alternatively, the contents of this file may be used under the +;+# terms of the GNU General Public License Version 2 or later (the +;+# "GPL"), in which case the provisions of the GPL are applicable +;+# instead of those above. If you wish to allow use of your +;+# version of this file only under the terms of the GPL and not to +;+# allow others to use your version of this file under the MPL, +;+# indicate your decision by deleting the provisions above and +;+# replace them with the notice and other provisions required by +;+# the GPL. If you do not delete the provisions above, a recipient +;+# may use your version of this file under either the MPL or the +;+# GPL. +;+# +;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS +;+# 1. For all unix platforms, the string ";-" means "remove this line" +;+# 2. For all unix platforms, the string " DATA " will be removed from any +;+# line on which it occurs. +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. +;+# On AIX, lines containing ";+" will be removed. +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. +;+# 5. For all unix platforms, after the above processing has taken place, +;+# all characters after the first ";" on the line will be removed. +;+# And for AIX, the first ";" will also be removed. +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX +;+# directives are hidden behind ";", ";+", and ";-" +;+# +;+NSPR_4.0 { +;+ global: +LIBRARY nspr4 ;- +EXPORTS ;- + LL_MaxInt; + LL_MinInt; + LL_Zero; + PR_Abort; + PR_AddToCounter; + PR_Accept; + PR_AcceptRead; + PR_Access; + PR_AddWaitFileDesc; + PR_AllocFileDesc; + PR_Assert; + PR_AtomicAdd; + PR_AtomicDecrement; + PR_AtomicIncrement; + PR_AtomicSet; + PR_AttachSharedMemory; + PR_AttachThread; + PR_Available; + PR_Available64; + PR_Bind; + PR_BlockClockInterrupts; + PR_BlockInterrupt; + PR_CEnterMonitor; + PR_CExitMonitor; + PR_CNotify; + PR_CNotifyAll; + PR_CSetOnMonitorRecycle; + PR_CWait; + PR_CallOnce; + PR_Calloc; + PR_CancelJob; + PR_CancelWaitFileDesc; + PR_CancelWaitGroup; + PR_CeilingLog2; + PR_ChangeFileDescNativeHandle; + PR_Cleanup; + PR_ClearInterrupt; + PR_ClearThreadGCAble; + PR_Close; + PR_CloseDir; + PR_CloseFileMap; + PR_CloseSemaphore; + PR_CloseSharedMemory; + PR_Connect; + PR_CreateCounter; + PR_ConvertIPv4AddrToIPv6; + PR_CreateAlarm; + PR_CreateFileMap; + PR_CreateIOLayerStub; + PR_CreateOrderedLock; + PR_CreateMWaitEnumerator; + PR_CreatePipe; + PR_CreateProcess; + PR_CreateProcessDetached; + PR_CreateSocketPollFd; + PR_CreateStack; + PR_CreateThread; + PR_CreateThreadGCAble; + PR_CreateTrace; + PR_CreateThreadPool; + PR_DecrementCounter; + PR_CreateWaitGroup; + PR_Delete; + PR_DeleteSemaphore; + PR_DeleteSharedMemory; + PR_DestroyAlarm; + PR_DestroyCounter; + PR_DestroyCondVar; + PR_DestroyLock; + PR_DestroyMWaitEnumerator; + PR_DestroyOrderedLock; + PR_DestroyMonitor; + PR_DestroyPollableEvent; + PR_DestroyProcessAttr; + PR_DestroyRWLock; + PR_DestroySem; + PR_DestroySocketPollFd; + PR_DestroyTrace; + PR_DestroyStack; + PR_DestroyWaitGroup; + PR_DetachProcess; + PR_DetachSharedMemory; + PR_DetachThread; + PR_DisableClockInterrupts; + PR_EnableClockInterrupts; + PR_EnterMonitor; + PR_EnumerateHostEnt; + PR_EnumerateThreads; + PR_EnumerateWaitGroup; + PR_ErrorInstallCallback; + PR_ErrorInstallTable; + PR_ErrorLanguages; + PR_ErrorToName; + PR_ErrorToString; + PR_ExitMonitor; + PR_ExplodeTime; + PR_ExportFileMapAsString; + PR_FD_CLR; + PR_FD_ISSET; + PR_FD_NCLR; + PR_FD_NISSET; + PR_FD_NSET; + PR_FD_SET; + PR_FD_ZERO; + PR_FileDesc2NativeHandle; + PR_FindSymbol; + PR_FindSymbolAndLibrary; + PR_FloorLog2; + PR_FormatTime; + PR_FindNextCounterQname; + PR_FindNextCounterRname; + PR_FindNextTraceQname; + PR_FindNextTraceRname; + PR_FormatTimeUSEnglish; + PR_Free; + PR_FreeLibraryName; + PR_GMTParameters; + PR_GetConnectStatus; + PR_GetCurrentThread; + PR_GetDefaultIOMethods; + PR_GetDescType; + PR_GetDirectorySeparator; + PR_GetCounter; + PR_GetCounterHandleFromName; + PR_GetCounterNameFromHandle; + PR_GetDirectorySepartor; + PR_GetEnv; + PR_GetError; + PR_GetErrorText; + PR_GetErrorTextLength; + PR_GetFileInfo; + PR_GetFileInfo64; + PR_GetFileMethods; + PR_GetGCRegisters; + PR_GetHostByAddr; + PR_GetHostByName; + PR_GetIPNodeByName; + PR_GetIdentitiesLayer; + PR_GetInheritedFD; + PR_GetInheritedFileMap; + PR_GetLayersIdentity; + PR_GetLibraryName; + PR_GetLibraryPath; + PR_GetMonitorEntryCount; + PR_GetNameForIdentity; + PR_GetOSError; + PR_GetOpenFileInfo; + PR_GetOpenFileInfo64; + PR_GetPageShift; + PR_GetPageSize; + PR_GetPeerName; + PR_GetPipeMethods; + PR_GetProtoByName; + PR_GetProtoByNumber; + PR_GetRandomNoise; + PR_GetSP; + PR_GetSockName; + PR_GetSocketOption; + PR_GetSpecialFD; + PR_GetStackSpaceLeft; + PR_GetSysfdTableMax; + PR_GetSystemInfo; + PR_GetTCPMethods; + PR_GetThreadAffinityMask; + PR_GetThreadID; + PR_GetThreadPriority; + PR_GetThreadPrivate; + PR_GetThreadScope; + PR_GetThreadState; + PR_GetThreadType; + PR_GetUDPMethods; + PR_GetUniqueIdentity; + PR_ImplodeTime; + PR_ImportFile; + PR_ImportFileMapFromString; + PR_ImportTCPSocket; + PR_ImportUDPSocket; + PR_GetTraceEntries; + PR_GetTraceHandleFromName; + PR_GetTraceNameFromHandle; + PR_GetTraceOption; + PR_Init; + PR_Initialize; + PR_InitializeNetAddr; + PR_Initialized; + PR_Interrupt; + PR_IntervalNow; + PR_IntervalToMicroseconds; + PR_IntervalToMilliseconds; + PR_IncrementCounter; + PR_IntervalToSeconds; + PR_IsNetAddrType; + PR_JoinJob; + PR_JoinThread; + PR_JoinThreadPool; + PR_KillProcess; + PR_Listen; + PR_LoadLibrary; + PR_LoadLibraryWithFlags; + PR_LoadStaticLibrary; + PR_LocalTimeParameters; + PR_Lock; + PR_LockFile; + PR_LogFlush; + PR_LogPrint; + PR_MakeDir; + PR_Malloc; + PR_MemMap; + PR_MemUnmap; + PR_MicrosecondsToInterval; + PR_MillisecondsToInterval; + PR_LockOrderedLock; + PR_MkDir; + PR_NetAddrToString; + PR_NewCondVar; + PR_NewLock; + PR_NewLogModule; + PR_NewMonitor; + PR_NewNamedMonitor; + PR_NewPollableEvent; + PR_NewProcessAttr; + PR_NewRWLock; + PR_NewSem; + PR_NewTCPSocket; + PR_NewTCPSocketPair; + PR_NewThreadPrivateIndex; + PR_NewUDPSocket; + PR_NormalizeTime; + PR_Notify; + PR_NotifyAll; + PR_NotifyAllCondVar; + PR_NotifyCondVar; + PR_Now; + PR_Open; + PR_OpenAnonFileMap; + PR_OpenDir; + PR_OpenFile; + PR_OpenSemaphore; + PR_OpenSharedMemory; + PR_OpenTCPSocket; + PR_OpenUDPSocket; + PR_ParseTimeString; + PR_Poll; + PR_PopIOLayer; + PR_PostSem; + PR_PostSemaphore; + PR_ProcessAttrSetCurrentDirectory; + PR_ProcessAttrSetInheritableFD; + PR_ProcessAttrSetInheritableFileMap; + PR_ProcessAttrSetStdioRedirect; + PR_ProcessExit; + PR_PushIOLayer; + PR_QueueJob; + PR_QueueJob_Accept; + PR_QueueJob_Connect; + PR_QueueJob_Read; + PR_QueueJob_Timer; + PR_QueueJob_Write; + PR_RWLock_Rlock; + PR_RWLock_Unlock; + PR_RWLock_Wlock; + PR_Read; + PR_ReadDir; + PR_Realloc; + PR_Recv; + PR_RecvFrom; + PR_Rename; + PR_ResetAlarm; + PR_ResetProcessAttr; + PR_ResumeAll; + PR_RmDir; + PR_ScanStackPointers; + PR_RecordTraceEntries; + PR_SecondsToInterval; + PR_Seek; + PR_Seek64; + PR_Select; + PR_Send; + PR_SendFile; + PR_SendTo; + PR_SetAlarm; + PR_SetConcurrency; + PR_SetError; + PR_SetErrorText; + PR_SetFDCacheSize; + PR_SetFDInheritable; + PR_SetLibraryPath; + PR_SetLogBuffering; + PR_SetLogFile; + PR_SetNetAddr; + PR_SetPollableEvent; + PR_SetSocketOption; + PR_SetCounter; + PR_SetStdioRedirect; + PR_SetSysfdTableSize; + PR_SetThreadAffinityMask; + PR_SetThreadDumpProc; + PR_SetThreadGCAble; + PR_SetThreadPriority; + PR_SetThreadPrivate; + PR_SetThreadRecycleMode; + PR_Shutdown; + PR_ShutdownThreadPool; + PR_Sleep; + PR_Socket; + PR_StackPop; + PR_StackPush; + PR_Stat; + PR_StringToNetAddr; + PR_SuspendAll; + PR_Sync; + PR_TLockFile; + PR_ThreadScanStackPointers; + PR_SetTraceOption; + PR_TicksPerSecond; + PR_TransmitFile; + PR_USPacificTimeParameters; + PR_UnblockClockInterrupts; + PR_UnblockInterrupt; + PR_UnloadLibrary; + PR_SubtractFromCounter; + PR_Unlock; + PR_UnlockFile; + PR_VersionCheck; + PR_Wait; + PR_WaitCondVar; + PR_WaitForPollableEvent; + PR_Trace; + PR_WaitProcess; + PR_WaitRecvReady; + PR_WaitSem; + PR_WaitSemaphore; + PR_Write; + PR_Writev; + PR_Yield; + PR_UnlockOrderedLock; + PR_cnvtf; + PR_dtoa; + PR_fprintf; + PR_htonl; + PR_htonll; + PR_htons; + PR_ntohl; + PR_ntohll; + PR_ntohs; + PR_smprintf; + PR_smprintf_free; + PR_snprintf; + PR_sprintf_append; + PR_sscanf; + PR_strtod; + PR_sxprintf; + PR_vfprintf; + PR_vsmprintf; + PR_vsnprintf; + PR_vsprintf_append; + PR_vsxprintf; + PRP_DestroyNakedCondVar; + PRP_NakedBroadcast; + PRP_NakedNotify; + PRP_NakedWait; + PRP_NewNakedCondVar; + PRP_TryLock; + libVersionPoint; +;+ local: *; +;+}; +;+ +;+NSPRprivate { +;+ global: + GetExecutionEnvironment; + PT_FPrintStats; + SetExecutionEnvironment; +;+ local: *; +;+}; +;+ +;+NSPR_4.1 { +;+ global: + PR_ConnectContinue; + PR_CreateIOLayer; + PR_EmulateAcceptRead; + PR_EmulateSendFile; + PR_FindFunctionSymbol; + PR_FindFunctionSymbolAndLibrary; + PR_GetMemMapAlignment; + PR_GetNumberOfProcessors; + PR_ImportPipe; + PR_SetEnv; +;+} NSPR_4.0; +;+ +;+NSPR_4.3 { +;+ global: + LL_MaxUint; + PR_CallOnceWithArg; + PR_GetLibraryFilePathname; +;+} NSPR_4.1; +;+ +;+NSPR_4.4 { +;+ global: + PR_GetPathSeparator; +;+} NSPR_4.3; +;+ +;+NSPR_4.5 { +;+ global: + PR_EnumerateAddrInfo; + PR_FreeAddrInfo; + PR_GetAddrInfoByName; + PR_GetCanonNameFromAddrInfo; +;+} NSPR_4.4; diff --git a/pr/src/nspr_symvec.opt b/pr/src/nspr_symvec.opt new file mode 100644 index 00000000..b6441372 --- /dev/null +++ b/pr/src/nspr_symvec.opt @@ -0,0 +1,500 @@ +! Fixed section of symbol vector for LIBNSPR4 (non-debug) +! +GSMATCH=LEQUAL,2,7 +case_sensitive=YES +! +! -------------------------------------------------------------------------- +! Ident 2,1 introduced for Mozilla 0.9.4 +! Based on NSPR 4.1.2 +! -------------------------------------------------------------------------- +! Ident 2,2 introduced for Mozilla 1.2 +! Based on NSPR 4.2.2? +! PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended has been "removed". +! Only we can't remove the entry points because OJI is linked against NSPR so +! we have to make an upwardly compatible change: +! PR_ResumeSet is now PR_VMS_Stub1 +! PR_ResumeTest is now PR_VMS_Stub2 +! PR_SuspendAllSuspended is PR_VMS_Stub3 +! These are stub functions (defined in openvms.c) solely for the purpose of +! occupying the slots in our fixed section of the symbol table. +! -------------------------------------------------------------------------- +! Ident 2,3 introduced for Mozilla 1.3 +! Previously we were missing some symbols from NSPR 4.0 and 4.1, so now we +! include everything that's specified in nspr.def. +! -------------------------------------------------------------------------- +! Ident 2,4 introduced for Mozilla 1.3 final. +! 2,3 was still missing some symbols, in particular PR_CreateThread, which +! is used by OJI. So insert stubs to force the PR_CreateThread entry down +! to its Mozilla 1.1 (and Java 1.4-0) location so that everyone can play +! together and be happy. +! -------------------------------------------------------------------------- +! Ident 2,5 introduced for post Mozilla 1.3. +! LL_MaxUint introduced. Replaces Stub54. +! -------------------------------------------------------------------------- +! Ident 2,6 introduced for post Mozilla 1.4. +! PR_GetPathSeparator introduced in NSPR 4.4. +! This replaces stub 53 +! -------------------------------------------------------------------------- +! Ident 2,7 introduced for post Mozilla 1.4. +! PR_GetAddrInfoByName, PR_FreeAddrInfo, PR_EnumerateAddrInfo and +! PR_GetCanonNameFromAddrInfo introduced in NSPR 4.5. +! These replace stubs 49-52 +! -------------------------------------------------------------------------- +! +SYMBOL_VECTOR=(PR_Accept=PROCEDURE) +SYMBOL_VECTOR=(PR_AcceptRead=PROCEDURE) +SYMBOL_VECTOR=(PR_Access=PROCEDURE) +SYMBOL_VECTOR=(PR_AllocFileDesc=PROCEDURE) +SYMBOL_VECTOR=(PR_Assert=PROCEDURE) +SYMBOL_VECTOR=(PR_AtomicAdd=PROCEDURE) +SYMBOL_VECTOR=(PR_AtomicDecrement=PROCEDURE) +SYMBOL_VECTOR=(PR_AtomicSet=PROCEDURE) +SYMBOL_VECTOR=(PR_AttachSharedMemory=PROCEDURE) +SYMBOL_VECTOR=(PR_AttachThread=PROCEDURE) +SYMBOL_VECTOR=(PR_Available64=PROCEDURE) +SYMBOL_VECTOR=(PR_Available=PROCEDURE) +SYMBOL_VECTOR=(PR_Bind=PROCEDURE) +SYMBOL_VECTOR=(PR_BlockClockInterrupts=PROCEDURE) +SYMBOL_VECTOR=(PR_BlockInterrupt=PROCEDURE) +SYMBOL_VECTOR=(PR_CExitMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_CNotify=PROCEDURE) +SYMBOL_VECTOR=(PR_CNotifyAll=PROCEDURE) +SYMBOL_VECTOR=(PR_CSetOnMonitorRecycle=PROCEDURE) +SYMBOL_VECTOR=(PR_CWait=PROCEDURE) +SYMBOL_VECTOR=(PR_CallOnce=PROCEDURE) +SYMBOL_VECTOR=(PR_Calloc=PROCEDURE) +SYMBOL_VECTOR=(PR_CancelJob=PROCEDURE) +SYMBOL_VECTOR=(PR_CancelWaitFileDesc=PROCEDURE) +SYMBOL_VECTOR=(PR_CancelWaitGroup=PROCEDURE) +SYMBOL_VECTOR=(PR_ChangeFileDescNativeHandle=PROCEDURE) +SYMBOL_VECTOR=(PR_Cleanup=PROCEDURE) +SYMBOL_VECTOR=(PR_ClearInterrupt=PROCEDURE) +SYMBOL_VECTOR=(PR_ClearThreadGCAble=PROCEDURE) +SYMBOL_VECTOR=(PR_Close=PROCEDURE) +SYMBOL_VECTOR=(PR_CloseDir=PROCEDURE) +SYMBOL_VECTOR=(PR_CloseFileMap=PROCEDURE) +SYMBOL_VECTOR=(PR_CloseSemaphore=PROCEDURE) +SYMBOL_VECTOR=(PR_CloseSharedMemory=PROCEDURE) +SYMBOL_VECTOR=(PR_Connect=PROCEDURE) +SYMBOL_VECTOR=(PR_ConnectContinue=PROCEDURE) +SYMBOL_VECTOR=(PR_ConvertIPv4AddrToIPv6=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateIOLayer=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateIOLayerStub=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateMWaitEnumerator=PROCEDURE) +SYMBOL_VECTOR=(PR_CreatePipe=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateProcess=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateProcessDetached=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateSocketPollFd=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateStack=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateThreadGCAble=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateWaitGroup=PROCEDURE) +SYMBOL_VECTOR=(PR_Delete=PROCEDURE) +SYMBOL_VECTOR=(PR_DeleteSemaphore=PROCEDURE) +SYMBOL_VECTOR=(PR_DeleteSharedMemory=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyAlarm=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyCondVar=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyLock=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyMWaitEnumerator=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyPollableEvent=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyProcessAttr=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyRWLock=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroySem=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroySocketPollFd=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyStack=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyWaitGroup=PROCEDURE) +SYMBOL_VECTOR=(PR_DetachProcess=PROCEDURE) +SYMBOL_VECTOR=(PR_DetachSharedMemory=PROCEDURE) +SYMBOL_VECTOR=(PR_DetachThread=PROCEDURE) +SYMBOL_VECTOR=(PR_DisableClockInterrupts=PROCEDURE) +SYMBOL_VECTOR=(PR_EmulateAcceptRead=PROCEDURE) +SYMBOL_VECTOR=(PR_EmulateSendFile=PROCEDURE) +SYMBOL_VECTOR=(PR_EnableClockInterrupts=PROCEDURE) +SYMBOL_VECTOR=(PR_EnterMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_EnumerateHostEnt=PROCEDURE) +SYMBOL_VECTOR=(PR_EnumerateThreads=PROCEDURE) +SYMBOL_VECTOR=(PR_EnumerateWaitGroup=PROCEDURE) +SYMBOL_VECTOR=(PR_ErrorInstallCallback=PROCEDURE) +SYMBOL_VECTOR=(PR_ErrorInstallTable=PROCEDURE) +SYMBOL_VECTOR=(PR_ErrorLanguages=PROCEDURE) +SYMBOL_VECTOR=(PR_ErrorToName=PROCEDURE) +SYMBOL_VECTOR=(PR_ExitMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_ExportFileMapAsString=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_CLR=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_ISSET=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_NCLR=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_NISSET=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_NSET=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_SET=PROCEDURE) +SYMBOL_VECTOR=(PR_FD_ZERO=PROCEDURE) +SYMBOL_VECTOR=(PR_FileDesc2NativeHandle=PROCEDURE) +SYMBOL_VECTOR=(PR_FindFunctionSymbol=PROCEDURE) +SYMBOL_VECTOR=(PR_FindFunctionSymbolAndLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_FindLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_FindSymbol=PROCEDURE) +SYMBOL_VECTOR=(PR_FindSymbolAndLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_FloorLog2=PROCEDURE) +SYMBOL_VECTOR=(PR_FormatTime=PROCEDURE) +SYMBOL_VECTOR=(PR_FormatTimeUSEnglish=PROCEDURE) +SYMBOL_VECTOR=(PR_Free=PROCEDURE) +SYMBOL_VECTOR=(PR_FreeLibraryName=PROCEDURE) +SYMBOL_VECTOR=(PR_GMTParameters=PROCEDURE) +SYMBOL_VECTOR=(PR_GetConnectStatus=PROCEDURE) +SYMBOL_VECTOR=(PR_GetCurrentThread=PROCEDURE) +SYMBOL_VECTOR=(PR_GetDefaultIOMethods=PROCEDURE) +SYMBOL_VECTOR=(PR_GetDirectorySepartor=PROCEDURE) +SYMBOL_VECTOR=(PR_GetError=PROCEDURE) +SYMBOL_VECTOR=(PR_GetErrorText=PROCEDURE) +SYMBOL_VECTOR=(PR_GetErrorTextLength=PROCEDURE) +SYMBOL_VECTOR=(PR_GetFileInfo64=PROCEDURE) +SYMBOL_VECTOR=(PR_GetFileInfo=PROCEDURE) +SYMBOL_VECTOR=(PR_GetFileMethods=PROCEDURE) +SYMBOL_VECTOR=(PR_GetHostByAddr=PROCEDURE) +SYMBOL_VECTOR=(PR_GetHostByName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetIPNodeByName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetIdentitiesLayer=PROCEDURE) +SYMBOL_VECTOR=(PR_GetInheritedFD=PROCEDURE) +SYMBOL_VECTOR=(PR_GetInheritedFileMap=PROCEDURE) +SYMBOL_VECTOR=(PR_GetLayersIdentity=PROCEDURE) +SYMBOL_VECTOR=(PR_GetLibraryName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetLibraryPath=PROCEDURE) +SYMBOL_VECTOR=(PR_GetMemMapAlignment=PROCEDURE) +SYMBOL_VECTOR=(PR_GetMonitorEntryCount=PROCEDURE) +SYMBOL_VECTOR=(PR_GetNameForIdentity=PROCEDURE) +SYMBOL_VECTOR=(PR_GetNumberOfProcessors=PROCEDURE) +SYMBOL_VECTOR=(PR_GetOSError=PROCEDURE) +SYMBOL_VECTOR=(PR_GetOpenFileInfo64=PROCEDURE) +SYMBOL_VECTOR=(PR_GetOpenFileInfo=PROCEDURE) +SYMBOL_VECTOR=(PR_GetPageShift=PROCEDURE) +SYMBOL_VECTOR=(PR_GetPeerName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetPipeMethods=PROCEDURE) +SYMBOL_VECTOR=(PR_GetProtoByName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetProtoByNumber=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSP=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSockName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSocketOption=PROCEDURE) +SYMBOL_VECTOR=(PR_GetStackSpaceLeft=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSysfdTableMax=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSystemInfo=PROCEDURE) +SYMBOL_VECTOR=(PR_GetTCPMethods=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadAffinityMask=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadID=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadPriority=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadPrivate=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadScope=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadState=PROCEDURE) +SYMBOL_VECTOR=(PR_GetThreadType=PROCEDURE) +SYMBOL_VECTOR=(PR_GetUDPMethods=PROCEDURE) +SYMBOL_VECTOR=(PR_ImplodeTime=PROCEDURE) +SYMBOL_VECTOR=(PR_ImportFile=PROCEDURE) +SYMBOL_VECTOR=(PR_ImportFileMapFromString=PROCEDURE) +SYMBOL_VECTOR=(PR_ImportPipe=PROCEDURE) +SYMBOL_VECTOR=(PR_ImportTCPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_ImportUDPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_Init=PROCEDURE) +SYMBOL_VECTOR=(PR_Initialize=PROCEDURE) +SYMBOL_VECTOR=(PR_InitializeNetAddr=PROCEDURE) +SYMBOL_VECTOR=(PR_Initialized=PROCEDURE) +SYMBOL_VECTOR=(PR_Interrupt=PROCEDURE) +SYMBOL_VECTOR=(PR_IntervalToMicroseconds=PROCEDURE) +SYMBOL_VECTOR=(PR_IntervalToMilliseconds=PROCEDURE) +SYMBOL_VECTOR=(PR_IntervalToSeconds=PROCEDURE) +SYMBOL_VECTOR=(PR_IsNetAddrType=PROCEDURE) +SYMBOL_VECTOR=(PR_JoinJob=PROCEDURE) +SYMBOL_VECTOR=(PR_JoinThread=PROCEDURE) +SYMBOL_VECTOR=(PR_JoinThreadPool=PROCEDURE) +SYMBOL_VECTOR=(PR_KillProcess=PROCEDURE) +SYMBOL_VECTOR=(PR_Listen=PROCEDURE) +SYMBOL_VECTOR=(PR_LoadLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_LoadLibraryWithFlags=PROCEDURE) +SYMBOL_VECTOR=(PR_LoadStaticLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_LocalTimeParameters=PROCEDURE) +SYMBOL_VECTOR=(PR_Lock=PROCEDURE) +SYMBOL_VECTOR=(PR_LockFile=PROCEDURE) +SYMBOL_VECTOR=(PR_LogFlush=PROCEDURE) +SYMBOL_VECTOR=(PR_LogPrint=PROCEDURE) +SYMBOL_VECTOR=(PR_MakeDir=PROCEDURE) +SYMBOL_VECTOR=(PR_MemMap=PROCEDURE) +SYMBOL_VECTOR=(PR_MemUnmap=PROCEDURE) +SYMBOL_VECTOR=(PR_MicrosecondsToInterval=PROCEDURE) +SYMBOL_VECTOR=(PR_MillisecondsToInterval=PROCEDURE) +SYMBOL_VECTOR=(PR_MkDir=PROCEDURE) +SYMBOL_VECTOR=(PR_NetAddrToString=PROCEDURE) +SYMBOL_VECTOR=(PR_NewCondVar=PROCEDURE) +SYMBOL_VECTOR=(PR_NewLogModule=PROCEDURE) +SYMBOL_VECTOR=(PR_NewMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_NewNamedMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_NewProcessAttr=PROCEDURE) +SYMBOL_VECTOR=(PR_NewSem=PROCEDURE) +SYMBOL_VECTOR=(PR_NewTCPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_NewTCPSocketPair=PROCEDURE) +SYMBOL_VECTOR=(PR_NewUDPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_NormalizeTime=PROCEDURE) +SYMBOL_VECTOR=(PR_Notify=PROCEDURE) +SYMBOL_VECTOR=(PR_NotifyAll=PROCEDURE) +SYMBOL_VECTOR=(PR_NotifyAllCondVar=PROCEDURE) +SYMBOL_VECTOR=(PR_NotifyCondVar=PROCEDURE) +SYMBOL_VECTOR=(PR_Open=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenDir=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenFile=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenSemaphore=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenTCPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenUDPSocket=PROCEDURE) +SYMBOL_VECTOR=(PR_ParseTimeString=PROCEDURE) +SYMBOL_VECTOR=(PR_Poll=PROCEDURE) +SYMBOL_VECTOR=(PR_PopIOLayer=PROCEDURE) +SYMBOL_VECTOR=(PR_PostSem=PROCEDURE) +SYMBOL_VECTOR=(PR_PostSemaphore=PROCEDURE) +SYMBOL_VECTOR=(PR_ProcessAttrSetCurren1sb1r7b$=PROCEDURE) ! PR_ProcessAttrSetCurrentDirectory +SYMBOL_VECTOR=(PR_ProcessAttrSetInheri3dpg1d0$=PROCEDURE) ! PR_ProcessAttrSetInheritableFileMap +SYMBOL_VECTOR=(PR_ProcessAttrSetInheritableFD=PROCEDURE) +SYMBOL_VECTOR=(PR_ProcessAttrSetStdioRedirect=PROCEDURE) +SYMBOL_VECTOR=(PR_ProcessExit=PROCEDURE) +SYMBOL_VECTOR=(PR_PushIOLayer=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob_Accept=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob_Connect=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob_Read=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob_Timer=PROCEDURE) +SYMBOL_VECTOR=(PR_QueueJob_Write=PROCEDURE) +SYMBOL_VECTOR=(PR_RWLock_Rlock=PROCEDURE) +SYMBOL_VECTOR=(PR_RWLock_Unlock=PROCEDURE) +SYMBOL_VECTOR=(PR_RWLock_Wlock=PROCEDURE) +SYMBOL_VECTOR=(PR_Read=PROCEDURE) +SYMBOL_VECTOR=(PR_ReadDir=PROCEDURE) +SYMBOL_VECTOR=(PR_Realloc=PROCEDURE) +SYMBOL_VECTOR=(PR_Recv=PROCEDURE) +SYMBOL_VECTOR=(PR_RecvFrom=PROCEDURE) +SYMBOL_VECTOR=(PR_Rename=PROCEDURE) +SYMBOL_VECTOR=(PR_ResetAlarm=PROCEDURE) +SYMBOL_VECTOR=(PR_ResetProcessAttr=PROCEDURE) +SYMBOL_VECTOR=(PR_ResumeAll=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub1=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub2=PROCEDURE) +SYMBOL_VECTOR=(PR_RmDir=PROCEDURE) +SYMBOL_VECTOR=(PR_ScanStackPointers=PROCEDURE) +SYMBOL_VECTOR=(PR_SecondsToInterval=PROCEDURE) +SYMBOL_VECTOR=(PR_Seek64=PROCEDURE) +SYMBOL_VECTOR=(PR_Seek=PROCEDURE) +SYMBOL_VECTOR=(PR_Select=PROCEDURE) +SYMBOL_VECTOR=(PR_Send=PROCEDURE) +SYMBOL_VECTOR=(PR_SendFile=PROCEDURE) +SYMBOL_VECTOR=(PR_SendTo=PROCEDURE) +SYMBOL_VECTOR=(PR_SetAlarm=PROCEDURE) +SYMBOL_VECTOR=(PR_SetEnv=PROCEDURE) +SYMBOL_VECTOR=(PR_SetErrorText=PROCEDURE) +SYMBOL_VECTOR=(PR_SetFDInheritable=PROCEDURE) +SYMBOL_VECTOR=(PR_SetLogBuffering=PROCEDURE) +SYMBOL_VECTOR=(PR_SetLogFile=PROCEDURE) +SYMBOL_VECTOR=(PR_SetNetAddr=PROCEDURE) +SYMBOL_VECTOR=(PR_SetPollableEvent=PROCEDURE) +SYMBOL_VECTOR=(PR_SetSocketOption=PROCEDURE) +SYMBOL_VECTOR=(PR_SetStdioRedirect=PROCEDURE) +SYMBOL_VECTOR=(PR_SetSysfdTableSize=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadAffinityMask=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadDumpProc=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadGCAble=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadPriority=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadPrivate=PROCEDURE) +SYMBOL_VECTOR=(PR_SetThreadRecycleMode=PROCEDURE) +SYMBOL_VECTOR=(PR_Shutdown=PROCEDURE) +SYMBOL_VECTOR=(PR_ShutdownThreadPool=PROCEDURE) +SYMBOL_VECTOR=(PR_Sleep=PROCEDURE) +SYMBOL_VECTOR=(PR_Socket=PROCEDURE) +SYMBOL_VECTOR=(PR_StackPop=PROCEDURE) +SYMBOL_VECTOR=(PR_StackPush=PROCEDURE) +SYMBOL_VECTOR=(PR_Stat=PROCEDURE) +SYMBOL_VECTOR=(PR_SuspendAll=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub3=PROCEDURE) +SYMBOL_VECTOR=(PR_Sync=PROCEDURE) +SYMBOL_VECTOR=(PR_TLockFile=PROCEDURE) +SYMBOL_VECTOR=(PR_ThreadScanStackPointers=PROCEDURE) +SYMBOL_VECTOR=(PR_TicksPerSecond=PROCEDURE) +SYMBOL_VECTOR=(PR_TransmitFile=PROCEDURE) +SYMBOL_VECTOR=(PR_USPacificTimeParameters=PROCEDURE) +SYMBOL_VECTOR=(PR_UnblockClockInterrupts=PROCEDURE) +SYMBOL_VECTOR=(PR_UnblockInterrupt=PROCEDURE) +SYMBOL_VECTOR=(PR_UnloadLibrary=PROCEDURE) +SYMBOL_VECTOR=(PR_Unlock=PROCEDURE) +SYMBOL_VECTOR=(PR_UnlockFile=PROCEDURE) +SYMBOL_VECTOR=(PR_Wait=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitCondVar=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitForPollableEvent=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitProcess=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitRecvReady=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitSem=PROCEDURE) +SYMBOL_VECTOR=(PR_WaitSemaphore=PROCEDURE) +SYMBOL_VECTOR=(PR_Write=PROCEDURE) +SYMBOL_VECTOR=(PR_Writev=PROCEDURE) +SYMBOL_VECTOR=(PR_XIsLocked=PROCEDURE) +SYMBOL_VECTOR=(PR_XLock=PROCEDURE) +SYMBOL_VECTOR=(PR_XNotify=PROCEDURE) +SYMBOL_VECTOR=(PR_XNotifyAll=PROCEDURE) +SYMBOL_VECTOR=(PR_XUnlock=PROCEDURE) +SYMBOL_VECTOR=(PR_XWait=PROCEDURE) +SYMBOL_VECTOR=(PR_Yield=PROCEDURE) +SYMBOL_VECTOR=(PR_cnvtf=PROCEDURE) +SYMBOL_VECTOR=(PR_dtoa=PROCEDURE) +SYMBOL_VECTOR=(PR_htonl=PROCEDURE) +SYMBOL_VECTOR=(PR_htonll=PROCEDURE) +SYMBOL_VECTOR=(PR_htons=PROCEDURE) +SYMBOL_VECTOR=(PR_ntohl=PROCEDURE) +SYMBOL_VECTOR=(PR_ntohll=PROCEDURE) +SYMBOL_VECTOR=(PR_ntohs=PROCEDURE) +SYMBOL_VECTOR=(PR_smprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_smprintf_free=PROCEDURE) +SYMBOL_VECTOR=(PR_sprintf_append=PROCEDURE) +SYMBOL_VECTOR=(PR_sxprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_vfprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_vsmprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_vsnprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_vsprintf_append=PROCEDURE) +SYMBOL_VECTOR=(PR_vsxprintf=PROCEDURE) +! +! Start of 2,3 additions +! +SYMBOL_VECTOR=(LL_MaxInt=PROCEDURE) +SYMBOL_VECTOR=(LL_MinInt=PROCEDURE) +SYMBOL_VECTOR=(LL_Zero=PROCEDURE) +SYMBOL_VECTOR=(PR_Abort=PROCEDURE) +SYMBOL_VECTOR=(PR_AddToCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_AddWaitFileDesc=PROCEDURE) +SYMBOL_VECTOR=(PR_AtomicIncrement=PROCEDURE) +SYMBOL_VECTOR=(PR_CEnterMonitor=PROCEDURE) +SYMBOL_VECTOR=(PR_CeilingLog2=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateAlarm=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateFileMap=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateOrderedLock=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateTrace=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateThreadPool=PROCEDURE) +SYMBOL_VECTOR=(PR_DecrementCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyOrderedLock=PROCEDURE) +SYMBOL_VECTOR=(PR_DestroyTrace=PROCEDURE) +SYMBOL_VECTOR=(PR_ErrorToString=PROCEDURE) +SYMBOL_VECTOR=(PR_ExplodeTime=PROCEDURE) +SYMBOL_VECTOR=(PR_FindNextCounterQname=PROCEDURE) +SYMBOL_VECTOR=(PR_FindNextCounterRname=PROCEDURE) +SYMBOL_VECTOR=(PR_FindNextTraceQname=PROCEDURE) +SYMBOL_VECTOR=(PR_FindNextTraceRname=PROCEDURE) +SYMBOL_VECTOR=(PR_GetDescType=PROCEDURE) +SYMBOL_VECTOR=(PR_GetDirectorySeparator=PROCEDURE) +SYMBOL_VECTOR=(PR_GetCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_GetCounterHandleFromName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetCounterNameFromHandle=PROCEDURE) +SYMBOL_VECTOR=(PR_GetEnv=PROCEDURE) +SYMBOL_VECTOR=(PR_GetGCRegisters=PROCEDURE) +SYMBOL_VECTOR=(PR_GetPageSize=PROCEDURE) +SYMBOL_VECTOR=(PR_GetRandomNoise=PROCEDURE) +SYMBOL_VECTOR=(PR_GetSpecialFD=PROCEDURE) +SYMBOL_VECTOR=(PR_GetUniqueIdentity=PROCEDURE) +SYMBOL_VECTOR=(PR_GetTraceEntries=PROCEDURE) +SYMBOL_VECTOR=(PR_GetTraceHandleFromName=PROCEDURE) +SYMBOL_VECTOR=(PR_GetTraceNameFromHandle=PROCEDURE) +SYMBOL_VECTOR=(PR_GetTraceOption=PROCEDURE) +SYMBOL_VECTOR=(PR_IntervalNow=PROCEDURE) +SYMBOL_VECTOR=(PR_IncrementCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_Malloc=PROCEDURE) +SYMBOL_VECTOR=(PR_LockOrderedLock=PROCEDURE) +SYMBOL_VECTOR=(PR_NewLock=PROCEDURE) +SYMBOL_VECTOR=(PR_NewPollableEvent=PROCEDURE) +SYMBOL_VECTOR=(PR_NewRWLock=PROCEDURE) +SYMBOL_VECTOR=(PR_NewThreadPrivateIndex=PROCEDURE) +SYMBOL_VECTOR=(PR_Now=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenAnonFileMap=PROCEDURE) +SYMBOL_VECTOR=(PR_OpenSharedMemory=PROCEDURE) +SYMBOL_VECTOR=(PR_RecordTraceEntries=PROCEDURE) +SYMBOL_VECTOR=(PR_SetConcurrency=PROCEDURE) +SYMBOL_VECTOR=(PR_SetFDCacheSize=PROCEDURE) +SYMBOL_VECTOR=(PR_SetLibraryPath=PROCEDURE) +SYMBOL_VECTOR=(PR_SetCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_StringToNetAddr=PROCEDURE) +SYMBOL_VECTOR=(PR_SetTraceOption=PROCEDURE) +SYMBOL_VECTOR=(PR_SubtractFromCounter=PROCEDURE) +SYMBOL_VECTOR=(PR_VersionCheck=PROCEDURE) +SYMBOL_VECTOR=(PR_Trace=PROCEDURE) +SYMBOL_VECTOR=(PR_UnlockOrderedLock=PROCEDURE) +SYMBOL_VECTOR=(PR_fprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_snprintf=PROCEDURE) +SYMBOL_VECTOR=(PR_sscanf=PROCEDURE) +SYMBOL_VECTOR=(PR_strtod=PROCEDURE) +SYMBOL_VECTOR=(PRP_DestroyNakedCondVar=PROCEDURE) +SYMBOL_VECTOR=(PRP_NakedBroadcast=PROCEDURE) +SYMBOL_VECTOR=(PRP_NakedNotify=PROCEDURE) +SYMBOL_VECTOR=(PRP_NakedWait=PROCEDURE) +SYMBOL_VECTOR=(PRP_NewNakedCondVar=PROCEDURE) +SYMBOL_VECTOR=(PRP_TryLock=PROCEDURE) +SYMBOL_VECTOR=(libVersionPoint=PROCEDURE) +! +! NSPR private +! +SYMBOL_VECTOR=(GetExecutionEnvironment=PROCEDURE) +SYMBOL_VECTOR=(PT_FPrintStats=PROCEDURE) +SYMBOL_VECTOR=(SetExecutionEnvironment=PROCEDURE) +! +! Start of 2,4 additions +! 51 stubs (4 thru 54) so that PR_CreateThread ends up at 1B70. +! Over time some of these stubs will get replaced by new symbols. +! +SYMBOL_VECTOR=(PR_VMS_Stub4=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub5=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub6=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub7=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub8=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub9=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub10=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub11=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub12=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub13=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub14=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub15=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub16=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub17=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub18=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub19=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub20=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub21=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub22=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub23=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub24=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub25=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub26=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub27=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub28=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub29=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub30=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub31=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub32=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub33=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub34=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub35=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub36=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub37=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub38=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub39=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub40=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub41=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub42=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub43=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub44=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub45=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub46=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub47=PROCEDURE) +SYMBOL_VECTOR=(PR_VMS_Stub48=PROCEDURE) +SYMBOL_VECTOR=(PR_GetAddrInfoByName=PROCEDURE) ! was Stub49 +SYMBOL_VECTOR=(PR_FreeAddrInfo=PROCEDURE) ! was Stub50 +SYMBOL_VECTOR=(PR_EnumerateAddrInfo=PROCEDURE) ! was Stub51 +SYMBOL_VECTOR=(PR_GetCanonNameFromAddrInfo=PROCEDURE) ! was Stub52 +SYMBOL_VECTOR=(PR_GetPathSeparator=PROCEDURE) ! was Stub53 +SYMBOL_VECTOR=(LL_MaxUint=PROCEDURE) ! was Stub54 +! +SYMBOL_VECTOR=(PR_CallOnceWithArg=PROCEDURE) +SYMBOL_VECTOR=(PR_GetLibraryFilePathname=PROCEDURE) +SYMBOL_VECTOR=(PR_SetError=PROCEDURE) +SYMBOL_VECTOR=(PR_CreateThread=PROCEDURE) +! +! -------------------------------------------------------------------------- +! End of fixed section +! -------------------------------------------------------------------------- +! diff --git a/pr/src/os2extra.def b/pr/src/os2extra.def new file mode 100644 index 00000000..8dbb34da --- /dev/null +++ b/pr/src/os2extra.def @@ -0,0 +1,16 @@ + ; + ; Support plugins that were explicitly linked to the Visual Age + ; version of nspr4.dll. + ; + PR_NewMonitor + PR_EnterMonitor + PR_ExitMonitor + PR_GetCurrentThread + PR_AttachThread + PR_DetachThread + ; + ; Exception handler functions that are used by nsAppRunner.cpp + ; + _PR_OS2_SetFloatExcpHandler + _PR_OS2_UnsetFloatExcpHandler + diff --git a/pr/src/pthreads/Makefile.in b/pr/src/pthreads/Makefile.in index a43fd6ac..8eb237d4 100644 --- a/pr/src/pthreads/Makefile.in +++ b/pr/src/pthreads/Makefile.in @@ -63,6 +63,11 @@ INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/incl DEFINES += -D_NSPR_BUILD_ +ifeq ($(OS_ARCH),Linux) +# for pthread_mutexattr_settype +DEFINES += -D_XOPEN_SOURCE=500 +endif + include $(topsrcdir)/config/rules.mk export:: $(TARGETS) diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c index ce263217..6792d8e7 100644 --- a/pr/src/pthreads/ptio.c +++ b/pr/src/pthreads/ptio.c @@ -40,9 +40,11 @@ #if defined(_PR_PTHREADS) #if defined(_PR_POLL_WITH_SELECT) +#if !(defined(HPUX) && defined(_USE_BIG_FDS)) /* set fd limit for select(), before including system header files */ #define FD_SETSIZE (16 * 1024) #endif +#endif #include <pthread.h> #include <string.h> /* for memset() */ @@ -55,6 +57,9 @@ #include <sys/uio.h> #include <sys/file.h> #include <sys/ioctl.h> +#if defined(DARWIN) +#include <sys/utsname.h> /* for uname */ +#endif #if defined(SOLARIS) || defined(UNIXWARE) #include <sys/filio.h> /* to pick up FIONREAD */ #endif @@ -173,11 +178,26 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #endif /* HAVE_SEND_FILE */ #endif /* AIX */ +#ifdef LINUX +#include <sys/sendfile.h> +#endif + #include "primpl.h" -/* On Alpha Linux, these are already defined in sys/socket.h */ -#if !(defined(LINUX) && defined(__alpha)) #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */ +#ifdef LINUX +/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */ +#ifndef TCP_CORK +#define TCP_CORK 3 +#endif +#endif + +#ifdef DARWIN +static PRBool _pr_ipv6_v6only_on_by_default; +/* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */ +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 +#endif #endif #if defined(SOLARIS) @@ -185,7 +205,7 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \ || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS) \ || defined(NTO) || defined(OPENBSD) || defined(DARWIN) \ - || defined(UNIXWARE) + || defined(UNIXWARE) || defined(NETBSD) #define _PRSockOptVal_t void * #else #error "Cannot determine architecture" @@ -281,11 +301,9 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) * most current systems. */ #if defined(HAVE_SOCKLEN_T) \ - || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2 \ - && !defined(__alpha)) + || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2) typedef socklen_t pt_SockLen; #elif (defined(AIX) && !defined(AIX4_1)) \ - || (defined(LINUX) && defined(__alpha)) \ || defined(VMS) typedef PRSize pt_SockLen; #else @@ -338,6 +356,15 @@ struct pt_Continuation */ int nbytes_to_send; /* size of header and file */ #endif /* SOLARIS */ + +#ifdef LINUX + /* + * For sendfile() + */ + int in_fd; /* descriptor of file to send */ + off_t offset; + size_t count; +#endif /* LINUX */ PRIntervalTime timeout; /* client (relative) timeout */ @@ -358,15 +385,13 @@ struct pt_Continuation PTDebug pt_debug; /* this is shared between several modules */ -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; - PT_GetStats(&stats); /* a copy */ + stats = pt_debug; /* a copy */ PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod); (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod); @@ -391,6 +416,13 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) stats.cvars_notified, stats.delayed_cv_deletes); } /* PT_FPrintStats */ +#else + +PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) +{ + /* do nothing */ +} /* PT_FPrintStats */ + #endif /* DEBUG */ #if defined(_PR_POLL_WITH_SELECT) @@ -406,6 +438,7 @@ static void pt_poll_now_with_select(pt_Continuation *op) fd_set rd, wr, *rdp, *wrp; struct timeval tv; PRIntervalTime epoch, now, elapsed, remaining; + PRBool wait_for_remaining; PRThread *self = PR_GetCurrentThread(); PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); @@ -485,9 +518,12 @@ static void pt_poll_now_with_select(pt_Continuation *op) } else wrp = NULL; + wait_for_remaining = PR_TRUE; msecs = (PRInt32)PR_IntervalToMilliseconds(remaining); - if (msecs > PT_DEFAULT_POLL_MSEC) + if (msecs > PT_DEFAULT_POLL_MSEC) { + wait_for_remaining = PR_FALSE; msecs = PT_DEFAULT_POLL_MSEC; + } tv.tv_sec = msecs/PR_MSEC_PER_SEC; tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC; rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv); @@ -514,9 +550,12 @@ static void pt_poll_now_with_select(pt_Continuation *op) } else if ((rv == 0) || ((errno == EINTR) || (errno == EAGAIN))) { - if (rv == 0) /* select timed out */ - now += PR_MillisecondsToInterval(msecs); - else + if (rv == 0) { /* select timed out */ + if (wait_for_remaining) + now += remaining; + else + now += PR_MillisecondsToInterval(msecs); + } else now = PR_IntervalNow(); elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= op->timeout) { @@ -542,6 +581,7 @@ static void pt_poll_now(pt_Continuation *op) { PRInt32 msecs; PRIntervalTime epoch, now, elapsed, remaining; + PRBool wait_for_remaining; PRThread *self = PR_GetCurrentThread(); PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); @@ -618,9 +658,13 @@ static void pt_poll_now(pt_Continuation *op) tmp_pfd.fd = op->arg1.osfd; tmp_pfd.events = op->event; + wait_for_remaining = PR_TRUE; msecs = (PRInt32)PR_IntervalToMilliseconds(remaining); if (msecs > PT_DEFAULT_POLL_MSEC) + { + wait_for_remaining = PR_FALSE; msecs = PT_DEFAULT_POLL_MSEC; + } rv = poll(&tmp_pfd, 1, msecs); if (self->state & PT_THREAD_ABORTED) @@ -654,7 +698,12 @@ static void pt_poll_now(pt_Continuation *op) } else if ((rv == 0) || ((errno == EINTR) || (errno == EAGAIN))) { if (rv == 0) /* poll timed out */ - now += PR_MillisecondsToInterval(msecs); + { + if (wait_for_remaining) + now += remaining; + else + now += PR_MillisecondsToInterval(msecs); + } else now = PR_IntervalNow(); elapsed = (PRIntervalTime) (now - epoch); @@ -1024,17 +1073,18 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents) ssize_t count; count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred); - PR_ASSERT((count == -1) || (count == xferred)); - PR_ASSERT(xferred <= op->nbytes_to_send); op->syserrno = errno; + PR_ASSERT((count == -1) || (count == xferred)); if (count == -1) { - if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { + if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN + && op->syserrno != EINTR) { op->result.code = -1; return PR_TRUE; } count = xferred; } + PR_ASSERT(count <= op->nbytes_to_send); op->result.code += count; if (count < op->nbytes_to_send) { @@ -1059,7 +1109,34 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents) } #endif /* SOLARIS */ -void _PR_InitIO() +#ifdef LINUX +static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents) +{ + ssize_t rv; + off_t oldoffset; + + oldoffset = op->offset; + rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count); + op->syserrno = errno; + + if (rv == -1) { + if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { + op->result.code = -1; + return PR_TRUE; + } + rv = 0; + } + PR_ASSERT(rv == op->offset - oldoffset); + op->result.code += rv; + if (rv < op->count) { + op->count -= rv; + return PR_FALSE; + } + return PR_TRUE; +} +#endif /* LINUX */ + +void _PR_InitIO(void) { #if defined(DEBUG) memset(&pt_debug, 0, sizeof(PTDebug)); @@ -1080,6 +1157,26 @@ void _PR_InitIO() _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE); PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr); +#ifdef DARWIN + /* In Mac OS X v10.3 Panther Beta the IPV6_V6ONLY socket option + * is turned on by default, contrary to what RFC 3493, Section + * 5.3 says. So we have to turn it off. Find out whether we + * are running on such a system. + */ + { + int osfd; + osfd = socket(AF_INET6, SOCK_STREAM, 0); + if (osfd != -1) { + int on; + int optlen = sizeof(on); + if (getsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY, + &on, &optlen) == 0) { + _pr_ipv6_v6only_on_by_default = on; + } + close(osfd); + } + } +#endif } /* _PR_InitIO */ void _PR_CleanupIO(void) @@ -1569,6 +1666,18 @@ static PRFileDesc* pt_Accept( if (pt_TestAbort()) return newfd; +#ifdef _PR_STRICT_ADDR_LEN + if (addr) + { + /* + * Set addr->raw.family just so that we can use the + * PR_NETADDR_SIZE macro. + */ + addr->raw.family = fd->secret->af; + addr_len = PR_NETADDR_SIZE(addr); + } +#endif + osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len); syserrno = errno; @@ -1614,6 +1723,14 @@ static PRFileDesc* pt_Accept( { PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); +#ifdef LINUX + /* + * On Linux, experiments showed that the accepted sockets + * inherit the TCP_NODELAY socket option of the listening + * socket. + */ + newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay; +#endif } return newfd; @@ -2107,7 +2224,7 @@ static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd, } if (count == -1) { - _MD_aix_map_sendfile_error(syserrno); + pt_MapError(_MD_aix_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { @@ -2146,14 +2263,16 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRInt32 count; int syserrno; - /* Get file size */ - if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { - _PR_MD_MAP_FSTAT_ERROR(errno); - return -1; + if (sfd->file_nbytes == 0) { + /* Get file size */ + if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { + _PR_MD_MAP_FSTAT_ERROR(errno); + return -1; + } + file_nbytes_to_send = statbuf.st_size - sfd->file_offset; + } else { + file_nbytes_to_send = sfd->file_nbytes; } - file_nbytes_to_send = (sfd->file_nbytes == 0) ? - statbuf.st_size - sfd->file_offset : - sfd->file_nbytes; nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send; hdtrl[0].iov_base = (void *) sfd->header; /* cast away the 'const' */ @@ -2228,7 +2347,7 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, } if (count == -1) { - _MD_hpux_map_sendfile_error(syserrno); + pt_MapError(_MD_hpux_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { @@ -2358,7 +2477,7 @@ static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd, done: if (count == -1) { - _MD_solaris_map_sendfile_error(syserrno); + pt_MapError(_MD_solaris_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { @@ -2425,6 +2544,140 @@ static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd, #endif /* SOLARIS */ +#ifdef LINUX +/* + * pt_LinuxSendFile + * + * Send file sfd->fd across socket sd. If specified, header and trailer + * buffers are sent before and after the file, respectively. + * + * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file + * + * return number of bytes sent or -1 on error + * + * This implementation takes advantage of the sendfile() system + * call available in Linux kernel 2.2 or higher. + */ + +static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd, + PRTransmitFileFlags flags, PRIntervalTime timeout) +{ + struct stat statbuf; + size_t file_nbytes_to_send; + PRInt32 count = 0; + ssize_t rv; + int syserrno; + off_t offset; + PRBool tcp_cork_enabled = PR_FALSE; + int tcp_cork; + + if (sfd->file_nbytes == 0) { + /* Get file size */ + if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { + _PR_MD_MAP_FSTAT_ERROR(errno); + return -1; + } + file_nbytes_to_send = statbuf.st_size - sfd->file_offset; + } else { + file_nbytes_to_send = sfd->file_nbytes; + } + + if ((sfd->hlen != 0 || sfd->tlen != 0) + && sd->secret->md.tcp_nodelay == 0) { + tcp_cork = 1; + if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK, + &tcp_cork, sizeof tcp_cork) == 0) { + tcp_cork_enabled = PR_TRUE; + } else { + syserrno = errno; + if (syserrno != EINVAL) { + _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno); + return -1; + } + /* + * The most likely reason for the EINVAL error is that + * TCP_NODELAY is set (with a function other than + * PR_SetSocketOption). This is not fatal, so we keep + * on going. + */ + PR_LOG(_pr_io_lm, PR_LOG_WARNING, + ("pt_LinuxSendFile: " + "setsockopt(TCP_CORK) failed with EINVAL\n")); + } + } + + if (sfd->hlen != 0) { + count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout); + if (count == -1) { + goto failed; + } + } + + if (file_nbytes_to_send != 0) { + offset = sfd->file_offset; + do { + rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd, + &offset, file_nbytes_to_send); + } while (rv == -1 && (syserrno = errno) == EINTR); + if (rv == -1) { + if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) { + _MD_linux_map_sendfile_error(syserrno); + count = -1; + goto failed; + } + rv = 0; + } + PR_ASSERT(rv == offset - sfd->file_offset); + count += rv; + + if (rv < file_nbytes_to_send) { + pt_Continuation op; + + op.arg1.osfd = sd->secret->md.osfd; + op.in_fd = sfd->fd->secret->md.osfd; + op.offset = offset; + op.count = file_nbytes_to_send - rv; + op.result.code = count; + op.timeout = timeout; + op.function = pt_linux_sendfile_cont; + op.event = POLLOUT | POLLPRI; + count = pt_Continue(&op); + syserrno = op.syserrno; + if (count == -1) { + pt_MapError(_MD_linux_map_sendfile_error, syserrno); + goto failed; + } + } + } + + if (sfd->tlen != 0) { + rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout); + if (rv == -1) { + count = -1; + goto failed; + } + count += rv; + } + +failed: + if (tcp_cork_enabled) { + tcp_cork = 0; + if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK, + &tcp_cork, sizeof tcp_cork) == -1 && count != -1) { + _PR_MD_MAP_SETSOCKOPT_ERROR(errno); + count = -1; + } + } + if (count != -1) { + if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { + PR_Close(sd); + } + PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send); + } + return count; +} +#endif /* LINUX */ + #ifdef AIX extern int _pr_aix_send_file_use_disabled; #endif @@ -2465,6 +2718,8 @@ static PRInt32 pt_SendFile( #else return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout)); #endif /* HAVE_SENDFILEV */ +#elif defined(LINUX) + return(pt_LinuxSendFile(sd, sfd, flags, timeout)); #else return(PR_EmulateSendFile(sd, sfd, flags, timeout)); #endif @@ -2728,6 +2983,12 @@ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *dat rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&value, sizeof(PRIntn)); +#ifdef LINUX + /* for pt_LinuxSendFile */ + if (name == TCP_NODELAY && rv == 0) { + fd->secret->md.tcp_nodelay = value; + } +#endif break; } case PR_SockOpt_McastLoopback: @@ -3086,27 +3347,27 @@ static PRFileDesc *pt_SetMethods( return fd; } /* pt_SetMethods */ -PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods() +PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void) { return &_pr_file_methods; } /* PR_GetFileMethods */ -PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods() +PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void) { return &_pr_pipe_methods; } /* PR_GetPipeMethods */ -PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods() +PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void) { return &_pr_tcp_methods; } /* PR_GetTCPMethods */ -PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods() +PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods(void) { return &_pr_udp_methods; } /* PR_GetUDPMethods */ -static const PRIOMethods* PR_GetSocketPollFdMethods() +static const PRIOMethods* PR_GetSocketPollFdMethods(void) { return &_pr_socketpollfd_methods; } /* PR_GetSocketPollFdMethods */ @@ -3116,11 +3377,6 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc( { PRFileDesc *fd = _PR_Getfd(); - /* - * Assert that the file descriptor is small enough to fit in the - * fd_set passed to select - */ - PR_ASSERT(osfd < FD_SETSIZE); if (NULL == fd) goto failed; fd->methods = methods; @@ -3149,12 +3405,30 @@ PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() { PRInt32 osfd; - osfd = socket(AF_INET6, SOCK_STREAM, 0); - if (osfd != -1) { - close(osfd); - return PR_TRUE; - } - return PR_FALSE; +#if defined(DARWIN) + /* + * Disable IPv6 if Darwin version is less than 7.0.0 (OS X 10.3). IPv6 on + * lesser versions is not ready for general use (see bug 222031). + */ + { + struct utsname u; + if (uname(&u) != 0 || atoi(u.release) < 7) + return PR_FALSE; + } +#endif + + /* + * HP-UX only: HP-UX IPv6 Porting Guide (dated February 2001) + * suggests that we call open("/dev/ip6", O_RDWR) to determine + * whether IPv6 APIs and the IPv6 stack are on the system. + * Our portable test below seems to work fine, so I am using it. + */ + osfd = socket(AF_INET6, SOCK_STREAM, 0); + if (osfd != -1) { + close(osfd); + return PR_TRUE; + } + return PR_FALSE; } #endif /* _PR_INET6_PROBE */ #endif @@ -3203,9 +3477,20 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno); else { +#ifdef DARWIN + if ((domain == AF_INET6) && _pr_ipv6_v6only_on_by_default) + { + int on = 0; + (void)setsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY, + &on, sizeof(on)); + } +#endif fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE); if (fd == NULL) close(osfd); } +#ifdef _PR_STRICT_ADDR_LEN + if (fd != NULL) fd->secret->af = domain; +#endif #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6) if (fd != NULL) { /* @@ -3598,6 +3883,8 @@ static PRInt32 _pr_poll_with_poll( { /* make poll() ignore this entry */ syspoll[index].fd = -1; + syspoll[index].events = 0; + pds[index].out_flags = 0; } } if (0 == ready) @@ -3805,43 +4092,65 @@ static PRInt32 _pr_poll_with_select( { if (0 == ready) { + PRBool add_to_rd = PR_FALSE; + PRBool add_to_wr = PR_FALSE; + PRBool add_to_ex = PR_FALSE; + selectfd[index] = bottom->secret->md.osfd; if (in_flags_read & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_READ_SYS_READ; - FD_SET(bottom->secret->md.osfd, &rd); - rdp = &rd; + add_to_rd = PR_TRUE; } if (in_flags_read & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE; - FD_SET(bottom->secret->md.osfd, &wr); - wrp = ≀ + add_to_wr = PR_TRUE; } if (in_flags_write & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ; - FD_SET(bottom->secret->md.osfd, &rd); - rdp = &rd; + add_to_rd = PR_TRUE; } if (in_flags_write & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE; - FD_SET(bottom->secret->md.osfd, &wr); - wrp = ≀ + add_to_wr = PR_TRUE; + } + if (pds[index].in_flags & PR_POLL_EXCEPT) + { + add_to_ex = PR_TRUE; + } + if ((selectfd[index] > maxfd) && + (add_to_rd || add_to_wr || add_to_ex)) + { + maxfd = selectfd[index]; + /* + * If maxfd is too large to be used with + * select, fall back to calling poll. + */ + if (maxfd >= FD_SETSIZE) + break; + } + if (add_to_rd) + { + FD_SET(bottom->secret->md.osfd, &rd); + rdp = &rd; + } + if (add_to_wr) + { + FD_SET(bottom->secret->md.osfd, &wr); + wrp = ≀ + } + if (add_to_ex) + { + FD_SET(bottom->secret->md.osfd, &ex); + exp = &ex; } - if (pds[index].in_flags & PR_POLL_EXCEPT) { - FD_SET(bottom->secret->md.osfd, &ex); - exp = &ex; - } - if ((selectfd[index] > maxfd) && - (pds[index].out_flags || - (pds[index].in_flags & PR_POLL_EXCEPT))) - maxfd = selectfd[index]; } } else @@ -3859,10 +4168,14 @@ static PRInt32 _pr_poll_with_select( } } } + else + { + pds[index].out_flags = 0; + } } if (0 == ready) { - if ((maxfd + 1) > FD_SETSIZE) + if (maxfd >= FD_SETSIZE) { /* * maxfd too large to be used with select, fall back to @@ -4017,14 +4330,14 @@ PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags) return &dir->d; } /* PR_ReadDir */ -PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket() +PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void) { PRIntn domain = PF_INET; return PR_Socket(domain, SOCK_DGRAM, 0); } /* PR_NewUDPSocket */ -PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket() +PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket(void) { PRIntn domain = PF_INET; @@ -4122,7 +4435,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable( { return PR_FAILURE; } - fd->secret->inheritable = inheritable; + fd->secret->inheritable = (_PRTriStateBool) inheritable; } return PR_SUCCESS; } @@ -4158,6 +4471,9 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd) if (!_pr_initialized) _PR_ImplicitInitialization(); fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE); if (NULL == fd) close(osfd); +#ifdef _PR_STRICT_ADDR_LEN + if (NULL != fd) fd->secret->af = PF_INET; +#endif return fd; } /* PR_ImportTCPSocket */ @@ -4552,4 +4868,39 @@ retry: } #endif /* defined(_PR_PTHREADS) */ +#ifdef MOZ_UNICODE +/* ================ UTF16 Interfaces ================================ */ +PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16( + const PRUnichar *name, PRIntn flags, PRIntn mode) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; +} + +PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDir *dir) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; +} + +PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; +} + +PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; +} + +PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; +} +/* ================ UTF16 Interfaces ================================ */ +#endif /* MOZ_UNICODE */ + /* ptio.c */ diff --git a/pr/src/pthreads/ptsynch.c b/pr/src/pthreads/ptsynch.c index 4400e8df..c3e50d5a 100644 --- a/pr/src/pthreads/ptsynch.c +++ b/pr/src/pthreads/ptsynch.c @@ -71,6 +71,13 @@ void _PR_InitLocks(void) rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); PR_ASSERT(0 == rv); +#ifdef LINUX +#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) + rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP); + PR_ASSERT(0 == rv); +#endif +#endif + rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr); PR_ASSERT(0 == rv); } @@ -464,7 +471,8 @@ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void) PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); - mon->name = name; + if (mon) + mon->name = name; return mon; } @@ -706,7 +714,12 @@ PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( } else { +#ifdef HPUX + /* Pass 0 as the mode and value arguments to work around a bug. */ + sem->sem = sem_open(osname, 0, 0, 0); +#else sem->sem = sem_open(osname, 0); +#endif } if ((sem_t *) -1 == sem->sem) { @@ -1041,7 +1054,7 @@ PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock) return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE; } /* PRP_TryLock */ -PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar() +PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void) { PRCondVar *cv; diff --git a/pr/src/pthreads/ptthread.c b/pr/src/pthreads/ptthread.c index dc8cc127..7fc2ad4d 100644 --- a/pr/src/pthreads/ptthread.c +++ b/pr/src/pthreads/ptthread.c @@ -607,9 +607,9 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred) return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } /* PR_JoinThread */ -PR_IMPLEMENT(void) PR_DetachThread() { } /* PR_DetachThread */ +PR_IMPLEMENT(void) PR_DetachThread(void) { } /* PR_DetachThread */ -PR_IMPLEMENT(PRThread*) PR_GetCurrentThread() +PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void) { void *thred; @@ -724,25 +724,25 @@ PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred) return PR_SUCCESS; } /* PR_Interrupt */ -PR_IMPLEMENT(void) PR_ClearInterrupt() +PR_IMPLEMENT(void) PR_ClearInterrupt(void) { PRThread *me = PR_CurrentThread(); me->state &= ~PT_THREAD_ABORTED; } /* PR_ClearInterrupt */ -PR_IMPLEMENT(void) PR_BlockInterrupt() +PR_IMPLEMENT(void) PR_BlockInterrupt(void) { PRThread *me = PR_CurrentThread(); _PT_THREAD_BLOCK_INTERRUPT(me); } /* PR_BlockInterrupt */ -PR_IMPLEMENT(void) PR_UnblockInterrupt() +PR_IMPLEMENT(void) PR_UnblockInterrupt(void) { PRThread *me = PR_CurrentThread(); _PT_THREAD_UNBLOCK_INTERRUPT(me); } /* PR_UnblockInterrupt */ -PR_IMPLEMENT(PRStatus) PR_Yield() +PR_IMPLEMENT(PRStatus) PR_Yield(void) { static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( @@ -908,7 +908,7 @@ void _PR_InitThreads( PR_SetThreadPriority(thred, priority); } /* _PR_InitThreads */ -PR_IMPLEMENT(PRStatus) PR_Cleanup() +PR_IMPLEMENT(PRStatus) PR_Cleanup(void) { PRThread *me = PR_CurrentThread(); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); @@ -920,7 +920,12 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup() PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(pt_book.ml); + _PR_CleanupMW(); + _PR_CleanupDtoa(); + _PR_CleanupCallOnce(); + _PR_ShutdownLinker(); _PR_LogCleanup(); + _PR_CleanupNet(); /* Close all the fd's before calling _PR_CleanupIO */ _PR_CleanupIO(); @@ -1026,7 +1031,7 @@ static void null_signal_handler(PRIntn sig); * conflict with the use of these two signals in our GC support. * So we don't know how to support GC on Linux pthreads. */ -static void init_pthread_gc_support() +static void init_pthread_gc_support(void) { PRIntn rv; @@ -1066,14 +1071,14 @@ static void init_pthread_gc_support() #endif /* defined(_PR_DCETHREADS) */ } -PR_IMPLEMENT(void) PR_SetThreadGCAble() +PR_IMPLEMENT(void) PR_SetThreadGCAble(void) { PR_Lock(pt_book.ml); PR_CurrentThread()->state |= PT_THREAD_GCABLE; PR_Unlock(pt_book.ml); } -PR_IMPLEMENT(void) PR_ClearThreadGCAble() +PR_IMPLEMENT(void) PR_ClearThreadGCAble(void) { PR_Lock(pt_book.ml); PR_CurrentThread()->state &= (~PT_THREAD_GCABLE); @@ -1086,12 +1091,6 @@ static PRBool suspendAllOn = PR_FALSE; static PRBool suspendAllSuspended = PR_FALSE; -/* Are all GCAble threads (except gc'ing thread) suspended? */ -PR_IMPLEMENT(PRBool) PR_SuspendAllSuspended() -{ - return suspendAllSuspended; -} /* PR_SuspendAllSuspended */ - PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) { PRIntn count = 0; @@ -1215,7 +1214,7 @@ static void suspend_signal_handler(PRIntn sig) while (me->suspend & PT_THREAD_SUSPENDED) { #if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \ - && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) /*XXX*/ + && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) && !defined(DARWIN) /*XXX*/ PRIntn rv; sigwait(&sigwait_set, &rv); #endif @@ -1242,12 +1241,12 @@ static void suspend_signal_handler(PRIntn sig) ("End suspend_signal_handler thred = %X tid = %X\n", me, me->id)); } /* suspend_signal_handler */ -static void PR_SuspendSet(PRThread *thred) +static void pt_SuspendSet(PRThread *thred) { PRIntn rv; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("PR_SuspendSet thred %X thread id = %X\n", thred, thred->id)); + ("pt_SuspendSet thred %X thread id = %X\n", thred, thred->id)); /* @@ -1257,7 +1256,7 @@ static void PR_SuspendSet(PRThread *thred) PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("doing pthread_kill in PR_SuspendSet thred %X tid = %X\n", + ("doing pthread_kill in pt_SuspendSet thred %X tid = %X\n", thred, thred->id)); #if defined(VMS) rv = thread_suspend(thred); @@ -1267,10 +1266,10 @@ static void PR_SuspendSet(PRThread *thred) PR_ASSERT(0 == rv); } -static void PR_SuspendTest(PRThread *thred) +static void pt_SuspendTest(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("Begin PR_SuspendTest thred %X thread id = %X\n", thred, thred->id)); + ("Begin pt_SuspendTest thred %X thread id = %X\n", thred, thred->id)); /* @@ -1296,13 +1295,13 @@ static void PR_SuspendTest(PRThread *thred) #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("End PR_SuspendTest thred %X tid %X\n", thred, thred->id)); -} /* PR_SuspendTest */ + ("End pt_SuspendTest thred %X tid %X\n", thred, thred->id)); +} /* pt_SuspendTest */ -PR_IMPLEMENT(void) PR_ResumeSet(PRThread *thred) +static void pt_ResumeSet(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("PR_ResumeSet thred %X thread id = %X\n", thred, thred->id)); + ("pt_ResumeSet thred %X thread id = %X\n", thred, thred->id)); /* * Clear the global state and set the thread state so that it will @@ -1322,12 +1321,12 @@ PR_IMPLEMENT(void) PR_ResumeSet(PRThread *thred) #endif #endif -} /* PR_ResumeSet */ +} /* pt_ResumeSet */ -PR_IMPLEMENT(void) PR_ResumeTest(PRThread *thred) +static void pt_ResumeTest(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, - ("Begin PR_ResumeTest thred %X thread id = %X\n", thred, thred->id)); + ("Begin pt_ResumeTest thred %X thread id = %X\n", thred, thred->id)); /* * Wait for the threads resume state to change @@ -1351,12 +1350,12 @@ PR_IMPLEMENT(void) PR_ResumeTest(PRThread *thred) thred->suspend &= ~PT_THREAD_RESUMED; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ( - "End PR_ResumeTest thred %X tid %X\n", thred, thred->id)); -} /* PR_ResumeTest */ + "End pt_ResumeTest thred %X tid %X\n", thred, thred->id)); +} /* pt_ResumeTest */ static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT; -PR_IMPLEMENT(void) PR_SuspendAll() +PR_IMPLEMENT(void) PR_SuspendAll(void) { #ifdef DEBUG PRIntervalTime stime, etime; @@ -1379,7 +1378,7 @@ PR_IMPLEMENT(void) PR_SuspendAll() while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) - PR_SuspendSet(thred); + pt_SuspendSet(thred); thred = thred->next; } @@ -1388,7 +1387,7 @@ PR_IMPLEMENT(void) PR_SuspendAll() while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) - PR_SuspendTest(thred); + pt_SuspendTest(thred); thred = thred->next; } @@ -1402,7 +1401,7 @@ PR_IMPLEMENT(void) PR_SuspendAll() #endif } /* PR_SuspendAll */ -PR_IMPLEMENT(void) PR_ResumeAll() +PR_IMPLEMENT(void) PR_ResumeAll(void) { #ifdef DEBUG PRIntervalTime stime, etime; @@ -1421,7 +1420,7 @@ PR_IMPLEMENT(void) PR_ResumeAll() while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) - PR_ResumeSet(thred); + pt_ResumeSet(thred); thred = thred->next; } @@ -1429,7 +1428,7 @@ PR_IMPLEMENT(void) PR_ResumeAll() while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) - PR_ResumeTest(thred); + pt_ResumeTest(thred); thred = thred->next; } diff --git a/pr/src/threads/combined/prucpu.c b/pr/src/threads/combined/prucpu.c index d9159b52..3d575d6c 100644 --- a/pr/src/threads/combined/prucpu.c +++ b/pr/src/threads/combined/prucpu.c @@ -59,7 +59,8 @@ static PRUintn _pr_cpuID; static void PR_CALLBACK _PR_CPU_Idle(void *); -static _PRCPU *_PR_CreateCPU(PRThread *thread, PRBool needQueue); +static _PRCPU *_PR_CreateCPU(void); +static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread); #if !defined(_PR_LOCAL_THREADS_ONLY) static void _PR_RunCPU(void *arg); @@ -69,6 +70,9 @@ void _PR_InitCPUs() { PRThread *me = _PR_MD_CURRENT_THREAD(); + if (_native_threads_only) + return; + _pr_cpuID = 0; _MD_NEW_LOCK( &_pr_cpuLock); #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) @@ -80,13 +84,13 @@ void _PR_InitCPUs() #ifdef _PR_LOCAL_THREADS_ONLY #ifdef HAVE_CUSTOM_USER_THREADS - if (!_native_threads_only) - _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me); + _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me); #endif /* Now start the first CPU. */ - _pr_primordialCPU = _PR_CreateCPU(me, PR_TRUE); + _pr_primordialCPU = _PR_CreateCPU(); _pr_numCPU = 1; + _PR_StartCPU(_pr_primordialCPU, me); _PR_MD_SET_CURRENT_CPU(_pr_primordialCPU); @@ -97,21 +101,47 @@ void _PR_InitCPUs() #else /* Combined MxN model */ + _pr_primordialCPU = _PR_CreateCPU(); + _pr_numCPU = 1; _PR_CreateThread(PR_SYSTEM_THREAD, _PR_RunCPU, - me, + _pr_primordialCPU, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0, _PR_IDLE_THREAD); - _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT); #endif /* _PR_LOCAL_THREADS_ONLY */ _PR_MD_INIT_CPUS(); } +#ifdef WINNT +/* + * Right now this function merely stops the CPUs and does + * not do any other cleanup. + * + * It is only implemented for WINNT because bug 161998 only + * affects the WINNT version of NSPR, but it would be nice + * to implement this function for other platforms too. + */ +void _PR_CleanupCPUs(void) +{ + PRUintn i; + PRCList *qp; + _PRCPU *cpu; + + _pr_cpus_exit = 1; + for (i = 0; i < _pr_numCPU; i++) { + _PR_MD_WAKEUP_WAITER(NULL); + } + for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { + cpu = _PR_CPU_PTR(qp); + _PR_MD_JOIN_THREAD(&cpu->thread->md); + } +} +#endif static _PRCPUQueue *_PR_CreateCPUQueue(void) { @@ -137,89 +167,113 @@ static _PRCPUQueue *_PR_CreateCPUQueue(void) /* * Create a new CPU. + * + * This function initializes enough of the _PRCPU structure so + * that it can be accessed safely by a global thread or another + * CPU. This function does not create the native thread that + * will run the CPU nor does it initialize the parts of _PRCPU + * that must be initialized by that native thread. + * + * The reason we cannot simply have the native thread create + * and fully initialize a new CPU is that we need to be able to + * create a usable _pr_primordialCPU in _PR_InitCPUs without + * assuming that the primordial CPU thread we created can run + * during NSPR initialization. For example, on Windows while + * new threads can be created by DllMain, they won't be able + * to run during DLL initialization. If NSPR is initialized + * by DllMain, the primordial CPU thread won't run until DLL + * initialization is finished. */ -static _PRCPU *_PR_CreateCPU(PRThread *thread, PRBool needQueue) +static _PRCPU *_PR_CreateCPU(void) { _PRCPU *cpu; - /* - ** Create a new cpu. The assumption this code makes is that the - ** underlying operating system creates a stack to go with the new - ** native thread. That stack will be used by the cpu when pausing. - */ cpu = PR_NEWZAP(_PRCPU); if (cpu) { - cpu->last_clock = PR_IntervalNow(); - - if (needQueue == PR_TRUE) - cpu->queue = _PR_CreateCPUQueue(); - else - cpu->queue = _PR_MD_CURRENT_CPU()->queue; - + cpu->queue = _PR_CreateCPUQueue(); if (!cpu->queue) { PR_DELETE(cpu); return NULL; } - - /* Before we create any threads on this CPU we have to - * set the current CPU - */ - _PR_MD_SET_CURRENT_CPU(cpu); - _PR_MD_INIT_RUNNING_CPU(cpu); - thread->cpu = cpu; - - if (!_native_threads_only) { - - cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD, - _PR_CPU_Idle, - (void *)cpu, - PR_PRIORITY_NORMAL, - PR_LOCAL_THREAD, - PR_UNJOINABLE_THREAD, - 0, - _PR_IDLE_THREAD); - - if (!cpu->idle_thread) { - /* didn't clean up CPU queue XXXMB */ - PR_DELETE(cpu); - return NULL; - } - cpu->idle_thread->cpu = cpu; - - cpu->idle_thread->no_sched = 0; - } - - cpu->thread = thread; - - if (_pr_cpu_affinity_mask) - PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask); - - /* Created a new CPU */ - _PR_CPU_LIST_LOCK(); - cpu->id = _pr_cpuID++; - PR_APPEND_LINK(&cpu->links, &_PR_CPUQ()); - _PR_CPU_LIST_UNLOCK(); - } + } return cpu; } +/* + * Start a new CPU. + * + * 'cpu' is a _PRCPU structure created by _PR_CreateCPU(). + * 'thread' is the native thread that will run the CPU. + * + * If this function fails, 'cpu' is destroyed. + */ +static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread) +{ + /* + ** Start a new cpu. The assumption this code makes is that the + ** underlying operating system creates a stack to go with the new + ** native thread. That stack will be used by the cpu when pausing. + */ + + PR_ASSERT(!_native_threads_only); + + cpu->last_clock = PR_IntervalNow(); + + /* Before we create any threads on this CPU we have to + * set the current CPU + */ + _PR_MD_SET_CURRENT_CPU(cpu); + _PR_MD_INIT_RUNNING_CPU(cpu); + thread->cpu = cpu; + + cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD, + _PR_CPU_Idle, + (void *)cpu, + PR_PRIORITY_NORMAL, + PR_LOCAL_THREAD, + PR_UNJOINABLE_THREAD, + 0, + _PR_IDLE_THREAD); + + if (!cpu->idle_thread) { + /* didn't clean up CPU queue XXXMB */ + PR_DELETE(cpu); + return PR_FAILURE; + } + PR_ASSERT(cpu->idle_thread->cpu == cpu); + + cpu->idle_thread->no_sched = 0; + + cpu->thread = thread; + + if (_pr_cpu_affinity_mask) + PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask); + + /* Created and started a new CPU */ + _PR_CPU_LIST_LOCK(); + cpu->id = _pr_cpuID++; + PR_APPEND_LINK(&cpu->links, &_PR_CPUQ()); + _PR_CPU_LIST_UNLOCK(); + + return PR_SUCCESS; +} + #if !defined(_PR_GLOBAL_THREADS_ONLY) && !defined(_PR_LOCAL_THREADS_ONLY) /* ** This code is used during a cpu's initial creation. */ static void _PR_RunCPU(void *arg) { - _PRCPU *cpu; + _PRCPU *cpu = (_PRCPU *)arg; PRThread *me = _PR_MD_CURRENT_THREAD(); - PRThread *waiter = (PRThread *) arg; PR_ASSERT(NULL != me); /* - * _PR_CreateCPU calls _PR_CreateThread to create the + * _PR_StartCPU calls _PR_CreateThread to create the * idle thread. Because _PR_CreateThread calls PR_Lock, * the current thread has to remain a global thread - * during the _PR_CreateCPU call so that it can wait for + * during the _PR_StartCPU call so that it can wait for * the lock if the lock is held by another thread. If * we clear the _PR_GLOBAL_SCOPE flag in * _PR_MD_CREATE_PRIMORDIAL_THREAD, the current thread @@ -227,7 +281,7 @@ static void _PR_RunCPU(void *arg) * waiting for the lock because the CPU is not fully * constructed yet. * - * After the CPU is created, it is safe to mark the + * After the CPU is started, it is safe to mark the * current thread as a local thread. */ @@ -236,7 +290,7 @@ static void _PR_RunCPU(void *arg) #endif me->no_sched = 1; - cpu = _PR_CreateCPU(me, PR_TRUE); + _PR_StartCPU(cpu, me); #ifdef HAVE_CUSTOM_USER_THREADS me->flags &= (~_PR_GLOBAL_SCOPE); @@ -246,12 +300,6 @@ static void _PR_RunCPU(void *arg) _PR_MD_SET_CURRENT_THREAD(cpu->thread); me->cpu = cpu; - if (waiter) { - _pr_primordialCPU = cpu; - _pr_numCPU = 1; - _PR_MD_WAKEUP_WAITER(waiter); - } - while(1) { PRInt32 is; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); @@ -309,6 +357,12 @@ static void PR_CALLBACK _PR_CPU_Idle(void *_cpu) /* Wait for an IO to complete */ (void)_PR_MD_PAUSE_CPU(timeout); +#ifdef WINNT + if (_pr_cpus_exit) { + /* _PR_CleanupCPUs tells us to exit */ + _PR_MD_END_THREAD(); + } +#endif #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifdef _PR_HAVE_ATOMIC_OPS @@ -344,7 +398,8 @@ PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs) #else /* combined, MxN thread model */ PRUintn newCPU; - PRThread *cpu; + _PRCPU *cpu; + PRThread *thr; if (!_pr_initialized) _PR_ImplicitInitialization(); @@ -360,9 +415,10 @@ PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs) _PR_CPU_LIST_UNLOCK(); for (; newCPU; newCPU--) { - cpu = _PR_CreateThread(PR_SYSTEM_THREAD, + cpu = _PR_CreateCPU(); + thr = _PR_CreateThread(PR_SYSTEM_THREAD, _PR_RunCPU, - NULL, + cpu, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, diff --git a/pr/src/threads/combined/pruthr.c b/pr/src/threads/combined/pruthr.c index 77236df1..a86fe5d0 100644 --- a/pr/src/threads/combined/pruthr.c +++ b/pr/src/threads/combined/pruthr.c @@ -85,7 +85,6 @@ PRThread *suspendAllThread = NULL; extern PRCList _pr_active_global_threadQ; extern PRCList _pr_active_local_threadQ; -extern _PRCPU *_pr_primordialCPU; static void _PR_DecrActiveThreadCount(PRThread *thread); static PRThread *_PR_AttachThread(PRThreadType, PRThreadPriority, PRThreadStack *); @@ -1510,6 +1509,19 @@ PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type, PR_IMPLEMENT(void) PR_DetachThread(void) { + /* + * On IRIX, Solaris, and Windows, foreign threads are detached when + * they terminate. + */ +#if !defined(IRIX) && !defined(WIN32) \ + && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) + PRThread *me; + if (_pr_initialized) { + me = _PR_MD_GET_ATTACHED_THREAD(); + if ((me != NULL) && (me->flags & _PR_ATTACHED)) + _PRI_DetachThread(); + } +#endif } void _PRI_DetachThread(void) diff --git a/pr/src/threads/prcthr.c b/pr/src/threads/prcthr.c index 71dafca4..ff4c2364 100644 --- a/pr/src/threads/prcthr.c +++ b/pr/src/threads/prcthr.c @@ -55,8 +55,6 @@ extern PRLock *_pr_sleeplock; /* allocated and initialized in prinit */ */ void _PR_CleanupThread(PRThread *thread) { - PRUintn i; - /* Free up per-thread-data */ _PR_DestroyThreadPrivate(thread); diff --git a/pr/src/threads/prmon.c b/pr/src/threads/prmon.c index 24205ec2..f9c12be0 100644 --- a/pr/src/threads/prmon.c +++ b/pr/src/threads/prmon.c @@ -68,7 +68,8 @@ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor() PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); - mon->name = name; + if (mon) + mon->name = name; return mon; } diff --git a/pr/src/threads/prtpd.c b/pr/src/threads/prtpd.c index 42139329..6d8fd416 100644 --- a/pr/src/threads/prtpd.c +++ b/pr/src/threads/prtpd.c @@ -88,7 +88,7 @@ static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL; /* ** Initialize the thread private data manipulation */ -void _PR_InitTPD() +void _PR_InitTPD(void) { _pr_tpd_destructors = (PRThreadPrivateDTOR*) PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*)); diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in index 7e8dbaf7..58222546 100644 --- a/pr/tests/Makefile.in +++ b/pr/tests/Makefile.in @@ -45,10 +45,6 @@ include $(topsrcdir)/config/config.mk DIRS = dll -ifeq ($(OS_TARGET),OS2) -OS_CFLAGS = $(OS_EXE_CFLAGS) -endif - CSRCS = \ accept.c \ acceptread.c \ @@ -79,7 +75,9 @@ CSRCS = \ fileio.c \ foreign.c \ forktest.c \ + formattm.c \ fsync.c \ + getai.c \ gethost.c \ getproto.c \ i2l.c \ @@ -98,6 +96,7 @@ CSRCS = \ joinuu.c \ layer.c \ lazyinit.c \ + libfilename.c \ lltest.c \ lock.c \ lockfile.c \ @@ -221,19 +220,23 @@ TARGETS = $(PROGS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private ifeq ($(OS_ARCH), WINNT) +ifdef NS_USE_GCC + EXTRA_LIBS += -lwsock32 +else + EXTRA_LIBS += wsock32.lib LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO ifdef PROFILE LDOPTS += -PROFILE -MAP endif # profile +endif # NS_USE_GCC endif ifeq ($(OS_ARCH),OS2) ifeq ($(MOZ_OS2_TOOLS),VACPP) LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO else -ifeq ($(MOZ_OS2_EMX_OBJECTFORMAT),OMF) - LDOPTS = -Zlinker /PM:VIO -endif + EXTRA_LIBS = $(OS_LIBS) + LDOPTS = -Zomf -Zlinker /PM:VIO -Zlinker /ST:0x64000 endif endif @@ -296,8 +299,10 @@ endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -z -Wl,+s,+b,$(ABSOLUTE_LIB_DIR) ifeq ($(USE_64),1) - LDOPTS += +DA2.0W - EXTRA_LIBS = -lpthread + LDOPTS += +DD64 + endif + ifeq ($(USE_PTHREADS),1) + EXTRA_LIBS = $(LIBPTHREAD) endif endif @@ -431,7 +436,7 @@ LIBPTHREAD = -lpthread ifeq ($(OS_ARCH),AIX) LIBPTHREAD = -lpthreads endif -ifeq (,$(filter-out FreeBSD OpenBSD BSD_OS NTO Darwin OpenUNIX,$(OS_ARCH))) +ifeq (,$(filter-out FreeBSD OpenBSD BSD_OS QNX Darwin OpenUNIX,$(OS_ARCH))) LIBPTHREAD = endif ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10) @@ -480,11 +485,11 @@ else $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) -ifeq ($(OS_ARCH), WINNT) - link $(LDOPTS) $(EXTRA_LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) wsock32.lib -out:$@ +ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) + link $(LDOPTS) $(EXTRA_LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -out:$@ else -ifeq ($(OS_ARCH),OS2) - $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(OS_LIBS) $(EXTRA_LIBS) +ifeq ($(MOZ_OS2_TOOLS),VACPP) + $(LD) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(OS_LIBS) $(EXTRA_LIBS) else $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -o $@ endif # OS/2 diff --git a/pr/tests/affinity.c b/pr/tests/affinity.c index 513775f7..ee78434a 100644 --- a/pr/tests/affinity.c +++ b/pr/tests/affinity.c @@ -40,6 +40,7 @@ #include <stdlib.h> #include <string.h> +#ifndef XP_BEOS /* * Test PR_GetThreadAffinityMask @@ -109,3 +110,12 @@ int main(int argc, char **argv) return 0; } + +#else /* !XP_BEOS */ + +int main() +{ + printf( "This test is not supported on the BeOS\n" ); + return 0; +} +#endif /* !XP_BEOS */ diff --git a/pr/tests/attach.c b/pr/tests/attach.c index f13d7f3f..a17b31f5 100644 --- a/pr/tests/attach.c +++ b/pr/tests/attach.c @@ -329,19 +329,25 @@ int main(int argc, char **argv) #elif defined(OS2) +# ifdef __EMX__ + threadID = (TID) _beginthread((void *)threadStartFunc, NULL, + 32768, NULL); +# else threadID = (TID) _beginthread((void(* _Optlink)(void*))threadStartFunc, NULL, 32768, NULL); +# endif if (threadID == -1) { fprintf(stderr, "thread creation failed: error code %d\n", errno); - failed_already=1; - goto exit_now; + failed_already=1; + goto exit_now; } rv = DosWaitThread(&threadID, DCWW_WAIT); - if (debug_mode)PR_ASSERT(rv == NO_ERROR); - else if (rv == NO_ERROR) { - failed_already=1; - goto exit_now; - } + if (debug_mode) { + PR_ASSERT(rv == NO_ERROR); + } else if (rv != NO_ERROR) { + failed_already=1; + goto exit_now; + } #elif defined(XP_BEOS) diff --git a/pr/tests/dll/Makefile.in b/pr/tests/dll/Makefile.in index cd0cca6e..2d86a4ac 100644 --- a/pr/tests/dll/Makefile.in +++ b/pr/tests/dll/Makefile.in @@ -64,7 +64,11 @@ ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET), WIN16) # do nothing else +ifdef NS_USE_GCC +DLLBASE=-Wl,--image-base -Wl,0x30000000 +else DLLBASE=/BASE:0x30000000 +endif RES=$(OBJDIR)/my.res RESNAME=../../../pr/src/nspr.rc endif @@ -74,12 +78,11 @@ ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) IMPORT_LIBRARY = $(OBJDIR)/my.$(LIB_SUFFIX) SHARED_LIBRARY = $(OBJDIR)/my.dll ifeq ($(OS_ARCH), OS2) -LIBRARY = $(OBJDIR)/my_s.lib -# XXX $(LIBRARY) probably doesn't need to be added to TARGETS. -TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) -else -TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY) +MAPFILE = $(OBJDIR)/my.def +GARBAGE += $(MAPFILE) +MKSHLIB += $(MAPFILE) endif +TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY) else ifdef MKSHLIB SHARED_LIBRARY = $(OBJDIR)/libmy.$(DLL_SUFFIX) diff --git a/pr/tests/dll/my.def b/pr/tests/dll/my.def new file mode 100644 index 00000000..4423c0f0 --- /dev/null +++ b/pr/tests/dll/my.def @@ -0,0 +1,53 @@ +;+# +;+# The contents of this file are subject to the Mozilla Public +;+# License Version 1.1 (the "License"); you may not use this file +;+# except in compliance with the License. You may obtain a copy of +;+# the License at http://www.mozilla.org/MPL/ +;+# +;+# Software distributed under the License is distributed on an "AS +;+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +;+# implied. See the License for the specific language governing +;+# rights and limitations under the License. +;+# +;+# The Original Code is the Netscape Portable Runtime (NSPR). +;+# +;+# The Initial Developer of the Original Code is Netscape +;+# Communications Corporation. Portions created by Netscape are +;+# Copyright (C) 2002-2003 Netscape Communications Corporation. All +;+# Rights Reserved. +;+# +;+# Contributor(s): +;+# +;+# Alternatively, the contents of this file may be used under the +;+# terms of the GNU General Public License Version 2 or later (the +;+# "GPL"), in which case the provisions of the GPL are applicable +;+# instead of those above. If you wish to allow use of your +;+# version of this file only under the terms of the GPL and not to +;+# allow others to use your version of this file under the MPL, +;+# indicate your decision by deleting the provisions above and +;+# replace them with the notice and other provisions required by +;+# the GPL. If you do not delete the provisions above, a recipient +;+# may use your version of this file under either the MPL or the +;+# GPL. +;+# +;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS +;+# 1. For all unix platforms, the string ";-" means "remove this line" +;+# 2. For all unix platforms, the string " DATA " will be removed from any +;+# line on which it occurs. +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. +;+# On AIX, lines containing ";+" will be removed. +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. +;+# 5. For all unix platforms, after the above processing has taken place, +;+# all characters after the first ";" on the line will be removed. +;+# And for AIX, the first ";" will also be removed. +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX +;+# directives are hidden behind ";", ";+", and ";-" +;+# +;+MY_1.0 { +;+ global: +LIBRARY my ;- +EXPORTS ;- + My_GetValue; + My_SetValue; +;+ local: *; +;+}; diff --git a/pr/tests/foreign.c b/pr/tests/foreign.c index 2fe48b1b..5457cc8c 100644 --- a/pr/tests/foreign.c +++ b/pr/tests/foreign.c @@ -63,7 +63,7 @@ #include <stdlib.h> static enum { - thread_nspr, thread_pthread, thread_sproc, thread_win32 + thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32 } thread_provider; typedef void (*StartFn)(void*); @@ -94,6 +94,18 @@ static void *pthread_start(void *arg) } /* pthread_start */ #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ +#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) +#include <thread.h> +static void *uithread_start(void *arg) +{ + StartFn start = ((StartObject*)arg)->start; + void *data = ((StartObject*)arg)->arg; + PR_Free(arg); + start(data); + return NULL; +} /* uithread_start */ +#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */ + #if defined(IRIX) && !defined(_PR_PTHREADS) #include <sys/types.h> #include <sys/prctl.h> @@ -169,6 +181,29 @@ static PRStatus CreateThread(StartFn start, void *arg) break; #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ + case thread_uithread: +#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) + { + int rv; + thread_t id; + long flags; + StartObject *start_object; + start_object = PR_NEW(StartObject); + PR_ASSERT(NULL != start_object); + start_object->start = start; + start_object->arg = arg; + + flags = THR_DETACHED; + + rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id); + return (0 == rv) ? PR_SUCCESS : PR_FAILURE; + } +#else + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + rv = PR_FAILURE; + break; +#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */ + case thread_sproc: #if defined(IRIX) && !defined(_PR_PTHREADS) { @@ -335,6 +370,8 @@ PRIntn main(PRIntn argc, char **argv) thread_provider = thread_win32; #elif defined(_PR_PTHREADS) thread_provider = thread_pthread; +#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) + thread_provider = thread_uithread; #elif defined(IRIX) thread_provider = thread_sproc; #else diff --git a/pr/tests/formattm.c b/pr/tests/formattm.c new file mode 100644 index 00000000..a2f9f2ab --- /dev/null +++ b/pr/tests/formattm.c @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2003 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/* A test program for PR_FormatTime and PR_FormatTimeUSEnglish */ + +#include "prtime.h" + +#include <stdio.h> + +int main() +{ + char buffer[256]; + PRTime now; + PRExplodedTime tod; + + now = PR_Now(); + PR_ExplodeTime(now, PR_LocalTimeParameters, &tod); + (void)PR_FormatTime(buffer, sizeof(buffer), + "%a %b %d %H:%M:%S %Z %Y", &tod); + printf("%s\n", buffer); + (void)PR_FormatTimeUSEnglish(buffer, sizeof(buffer), + "%a %b %d %H:%M:%S %Z %Y", &tod); + printf("%s\n", buffer); + return 0; +} diff --git a/pr/tests/getai.c b/pr/tests/getai.c new file mode 100644 index 00000000..3e17736c --- /dev/null +++ b/pr/tests/getai.c @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2003 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "nspr.h" + +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) +{ + PRAddrInfo *ai; + void *iter; + PRNetAddr addr; + + ai = PR_GetAddrInfoByName(argv[1], PR_AF_UNSPEC, PR_AI_ADDRCONFIG); + if (ai == NULL) { + fprintf(stderr, "PR_GetAddrInfoByName failed: (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + printf("%s\n", PR_GetCanonNameFromAddrInfo(ai)); + iter = NULL; + while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) { + char buf[128]; + PR_NetAddrToString(&addr, buf, sizeof buf); + printf("%s\n", buf); + } + PR_FreeAddrInfo(ai); + return 0; +} diff --git a/pr/tests/libfilename.c b/pr/tests/libfilename.c new file mode 100644 index 00000000..4be50b09 --- /dev/null +++ b/pr/tests/libfilename.c @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2003 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +/*********************************************************************** +** +** Name: libfilename.c +** +** Description: test PR_GetLibraryFilePathname. +** +***********************************************************************/ + +#include "nspr.h" +#include "pprio.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +PRBool debug_mode = PR_FALSE; + +static PRStatus RunTest(const char *name, PRFuncPtr addr) +{ + char *pathname; + PRFileDesc *fd; + + pathname = PR_GetLibraryFilePathname(name, addr); + if (pathname == NULL) { + fprintf(stderr, "PR_GetLibraryFilePathname failed\n"); + /* we let this test pass if this function is not implemented */ + if (PR_GetError() == PR_NOT_IMPLEMENTED_ERROR) { + return PR_SUCCESS; + } + return PR_FAILURE; + } + + if (debug_mode) printf("Pathname is %s\n", pathname); + fd = PR_OpenFile(pathname, PR_RDONLY, 0); + if (fd == NULL) { + fprintf(stderr, "PR_Open failed: %d\n", (int)PR_GetError()); + return PR_FAILURE; + } + if (PR_Close(fd) == PR_FAILURE) { + fprintf(stderr, "PR_Close failed: %d\n", (int)PR_GetError()); + return PR_FAILURE; + } + PR_Free(pathname); + return PR_SUCCESS; +} + +int main(int argc, char *argv[]) +{ + char *name; + PRFuncPtr addr; + PRLibrary *lib; + PRBool failed = PR_FALSE; + + if (argc >= 2 && strcmp(argv[1], "-d") == 0) { + debug_mode = PR_TRUE; + } + + /* First test a library that is implicitly linked. */ +#ifdef WINNT + name = PR_Malloc(strlen("libnspr4.dll")+1); + strcpy(name, "libnspr4.dll"); +#else + name = PR_GetLibraryName(NULL, "nspr4"); +#endif + addr = (PRFuncPtr)PR_GetTCPMethods()->close; + if (RunTest(name, addr) == PR_FAILURE) { + failed = PR_TRUE; + } + PR_FreeLibraryName(name); + + /* Next test a library that is dynamically loaded. */ + name = PR_GetLibraryName("dll", "my"); + if (debug_mode) printf("Loading library %s\n", name); + lib = PR_LoadLibrary(name); + if (!lib) { + fprintf(stderr, "PR_LoadLibrary failed\n"); + exit(1); + } + PR_FreeLibraryName(name); + name = PR_GetLibraryName(NULL, "my"); + addr = PR_FindFunctionSymbol(lib, "My_GetValue"); + if (RunTest(name, addr) == PR_FAILURE) { + failed = PR_TRUE; + } + PR_FreeLibraryName(name); + PR_UnloadLibrary(lib); + if (failed) { + printf("FAIL\n"); + return 1; + } + printf("PASS\n"); + return 0; +} diff --git a/pr/tests/macbuild/NSPR20TestApp.mcp b/pr/tests/macbuild/NSPR20TestApp.mcp Binary files differdeleted file mode 100644 index aad1a297..00000000 --- a/pr/tests/macbuild/NSPR20TestApp.mcp +++ /dev/null diff --git a/pr/tests/provider.c b/pr/tests/provider.c index 5fd91bea..9fc68d13 100644 --- a/pr/tests/provider.c +++ b/pr/tests/provider.c @@ -127,7 +127,7 @@ typedef enum Verbosity } Verbosity; static enum { - thread_nspr, thread_pthread, thread_sproc, thread_win32 + thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32 } thread_provider; static PRInt32 domain = AF_INET; @@ -658,6 +658,20 @@ static void *pthread_start(void *arg) } /* pthread_start */ #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ +#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) +#include <thread.h> + +static void *uithread_start(void *arg) +{ + StartObject *so = (StartObject*)arg; + StartFn start = so->start; + void *data = so->arg; + PR_Free(so); + start(data); + return NULL; +} /* uithread_start */ +#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */ + #if defined(IRIX) && !defined(_PR_PTHREADS) #include <sys/types.h> #include <sys/prctl.h> @@ -698,6 +712,11 @@ static PRStatus JoinThread(PRThread *thread) rv = PR_SUCCESS; break; #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ + case thread_uithread: +#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) + rv = PR_SUCCESS; + break; +#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */ case thread_win32: #if defined(WIN32) rv = PR_SUCCESS; @@ -759,6 +778,29 @@ static PRStatus NewThread( #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ break; + case thread_uithread: +#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) + { + int rv; + thread_t id; + long flags; + StartObject *start_object; + start_object = PR_NEW(StartObject); + PR_ASSERT(NULL != start_object); + start_object->start = start; + start_object->arg = arg; + + flags = THR_DETACHED; + + rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id); + return (0 == rv) ? PR_SUCCESS : PR_FAILURE; + } +#else + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + rv = PR_FAILURE; +#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */ + break; + case thread_sproc: #if defined(IRIX) && !defined(_PR_PTHREADS) { @@ -947,9 +989,15 @@ static void PR_CALLBACK Server(void *arg) PRNetAddr serverAddress; CSServer_t *server = (CSServer_t*)arg; PRThread *me = server->thread = PR_CurrentThread(); + PRSocketOptionData sockOpt; server->listener = PR_Socket(domain, SOCK_STREAM, protocol); + sockOpt.option = PR_SockOpt_Reuseaddr; + sockOpt.value.reuse_addr = PR_TRUE; + rv = PR_SetSocketOption(server->listener, &sockOpt); + TEST_ASSERT(PR_SUCCESS == rv); + memset(&serverAddress, 0, sizeof(serverAddress)); rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); @@ -1063,7 +1111,7 @@ static void Help(void) 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-T <string> thread provider ('n' | 'p' | 'u' | 'w')(n)\n"); PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n"); PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n"); PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n"); @@ -1115,6 +1163,8 @@ PRIntn main(PRIntn argc, char** argv) thread_provider = thread_win32; #elif defined(_PR_PTHREADS) thread_provider = thread_pthread; +#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) + thread_provider = thread_uithread; #elif defined(IRIX) thread_provider = thread_sproc; #else @@ -1146,6 +1196,7 @@ PRIntn main(PRIntn argc, char** argv) case 'T': /* the thread provider */ if ('n' == *opt->value) thread_provider = thread_nspr; else if ('p' == *opt->value) thread_provider = thread_pthread; + else if ('u' == *opt->value) thread_provider = thread_uithread; else if ('w' == *opt->value) thread_provider = thread_win32; else {Help(); return 2; } break; @@ -1374,6 +1425,8 @@ PRIntn main(PRIntn argc, char** argv) thread_type = "\nWin32 Thread Statistics\n"; else if (thread_provider == thread_pthread) thread_type = "\npthread Statistics\n"; + else if (thread_provider == thread_uithread) + thread_type = "\nUnix International (UI) Thread Statistics\n"; else if (thread_provider == thread_sproc) thread_type = "\nsproc Statistics\n"; else { diff --git a/pr/tests/runtests.ksh b/pr/tests/runtests.ksh index c4d027ad..9a3b8171 100755 --- a/pr/tests/runtests.ksh +++ b/pr/tests/runtests.ksh @@ -39,7 +39,7 @@ SYSTEM_INFO=`uname -a` OS_ARCH=`uname -s` -if [ $OS_ARCH = "Windows_NT" ] +if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "OS/2" ] then NULL_DEVICE=nul else @@ -114,6 +114,7 @@ exit fdcach fileio foreign +formattm fsync gethost getproto @@ -132,6 +133,7 @@ joinuk joinuu layer lazyinit +libfilename lltest lock lockfile @@ -224,7 +226,7 @@ echo "\nNSPR Test Results - $OBJDIR\n" echo "BEGIN\t\t\t`date`" echo "NSPR_TEST_LOGFILE\t${LOGFILE}\n" echo "Test\t\t\tResult\n" -if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] ; then +if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] || [ $OS_PLATFORM = "OS/2" ] ; then for prog in $TESTS do echo "$prog\c" @@ -254,7 +256,7 @@ else fi wait $test_pid test_rval=$? - [ sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 + [ $sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 if [ 0 = $test_rval ] ; then echo "\t\t\tPassed"; else diff --git a/pr/tests/runtests.sh b/pr/tests/runtests.sh new file mode 100755 index 00000000..e4810d9c --- /dev/null +++ b/pr/tests/runtests.sh @@ -0,0 +1,288 @@ +#!/bin/sh +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape Portable Runtime (NSPR). +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# tests.ksh +# korn shell script for nspr tests +# + +SYSTEM_INFO=`uname -a` +OS_ARCH=`uname -s` +if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "OS/2" ] +then + NULL_DEVICE=nul +else + NULL_DEVICE=/dev/null +fi + +# +# Irrevelant tests +# +#bug1test - used to demonstrate a bug on NT +#bigfile2 - requires 4Gig file creation. See BugZilla #5451 +#bigfile3 - requires 4Gig file creation. See BugZilla #5451 +#dbmalloc - obsolete; originally for testing debug version of nspr's malloc +#dbmalloc1 - obsolete; originally for testing debug version of nspr's malloc +#depend - obsolete; used to test a initial spec for library dependencies +#dceemu - used to tests special functions in NSPR for DCE emulation +#ipv6 - IPV6 not in use by NSPR clients +#mbcs - tests use of multi-byte charset for filenames. See BugZilla #25140 +#sproc_ch - obsolete; sproc-based tests for Irix +#sproc_p - obsolete; sproc-based tests for Irix +#io_timeoutk - obsolete; subsumed in io_timeout +#io_timeoutu - obsolete; subsumed in io_timeout +#prftest1 - obsolete; subsumed by prftest +#prftest2 - obsolete; subsumed by prftest +#prselect - obsolete; PR_Select is obsolete +#select2 - obsolete; PR_Select is obsolete +#sem - obsolete; PRSemaphore is obsolete +#stat - for OS2? +#suspend - private interfaces PR_SuspendAll, PR_ResumeAll, etc.. +#thruput - needs to be run manually as client/server +#time - used to measure time with native calls and nspr calls +#tmoacc - should be run with tmocon +#tmocon - should be run with tmoacc +#op_noacc - limited use +#yield - limited use for PR_Yield + +# +# Tests not run (but should) +# + +#forktest (failed on IRIX) +#nbconn - fails on some platforms +#poll_er - fails on some platforms? limited use? +#prpoll - the bad-FD test needs to be moved to a different test +#sleep - specific to OS/2 + +LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE} + +# +# Tests run on all platforms +# + +TESTS=" +accept +acceptread +acceptreademu +affinity +alarm +anonfm +atomic +attach +bigfile +cleanup +cltsrv +concur +cvar +cvar2 +dlltest +dtoa +errcodes +exit +fdcach +fileio +foreign +formattm +fsync +gethost +getproto +i2l +initclk +inrval +instrumt +intrio +intrupt +io_timeout +ioconthr +join +joinkk +joinku +joinuk +joinuu +layer +lazyinit +libfilename +lltest +lock +lockfile +logger +many_cv +multiwait +nameshm1 +nblayer +nonblock +ntioto +ntoh +op_2long +op_excl +op_filnf +op_filok +op_nofil +parent +peek +perf +pipeping +pipeping2 +pipeself +poll_nm +poll_to +pollable +prftest +primblok +provider +prpollml +ranfile +randseed +rwlocktest +sel_spd +selct_er +selct_nm +selct_to +selintr +sema +semaerr +semaping +sendzlf +server_test +servr_kk +servr_uk +servr_ku +servr_uu +short_thread +sigpipe +socket +sockopt +sockping +sprintf +stack +stdio +str2addr +strod +switch +system +testbit +testfile +threads +timemac +timetest +tpd +udpsrv +vercheck +version +writev +xnotify +zerolen" + +rval=0 + + +# +# When set, value of the environment variable TEST_TIMEOUT is the maximum +# time (secs) allowed for a test program beyond which it is terminated. +# If TEST_TIMEOUT is not set or if it's value is 0, then test programs +# don't timeout. +# +# Running runtests.ksh under MKS toolkit on NT, 95, 98 does not cause +# timeout detection correctly. For these platforms, do not attempt timeout +# test. (lth). +# +# + +OS_PLATFORM=`uname` +OBJDIR=`basename $PWD` +printf "\nNSPR Test Results - $OBJDIR\n\n" +printf "BEGIN\t\t\t`date`\n" +printf "NSPR_TEST_LOGFILE\t${LOGFILE}\n\n" +printf "Test\t\t\tResult\n\n" +if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] || [ $OS_PLATFORM = "OS/2" ] ; then + for prog in $TESTS + do + printf "$prog" + printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1 + ./$prog >> ${LOGFILE} 2>&1 + if [ 0 = $? ] ; then + printf "\t\t\tPassed\n"; + else + printf "\t\t\tFAILED\n"; + rval=1 + fi; + printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1 + done +else + for prog in $TESTS + do + printf "$prog" + printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1 + export test_rval + ./$prog >> ${LOGFILE} 2>&1 & + test_pid=$! + sleep_pid=0 + if test -n "$TEST_TIMEOUT" && test "$TEST_TIMEOUT" -gt 0 + then + (sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) & + sleep_pid=$! + fi + wait $test_pid + test_rval=$? + [ $sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 + if [ 0 = $test_rval ] ; then + printf "\t\t\tPassed\n"; + else + printf "\t\t\tFAILED\n"; + rval=1 + fi; + printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1 + done +fi; + +printf "END\t\t\t`date`\n" +exit $rval + + + + + + + + + + + + + + + + + diff --git a/pr/tests/server_test.c b/pr/tests/server_test.c index 46c474b3..572fea46 100644 --- a/pr/tests/server_test.c +++ b/pr/tests/server_test.c @@ -61,7 +61,7 @@ #include <string.h> #define PORT 15004 -#define STACKSIZE 0 +#define THREAD_STACKSIZE 0 #define PASS 0 #define FAIL 1 @@ -225,7 +225,7 @@ WorkerThreadFunc(void *_listenSock) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) if (debug_mode) printf("Error creating client thread %d\n", workerThreads); @@ -314,7 +314,7 @@ ServerSetup(void) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); @@ -469,7 +469,7 @@ RunClients(void) PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); @@ -500,7 +500,7 @@ void do_work() PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; diff --git a/pr/tests/servr_kk.c b/pr/tests/servr_kk.c index d9423343..1a477f9a 100644 --- a/pr/tests/servr_kk.c +++ b/pr/tests/servr_kk.c @@ -63,7 +63,7 @@ #include <string.h> #define PORT 15004 -#define STACKSIZE 0 +#define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; @@ -191,7 +191,7 @@ WorkerThreadFunc(void *_listenSock) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) if (debug_mode) printf("Error creating client thread %d\n", workerThreads); @@ -291,7 +291,7 @@ ServerSetup(void) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); @@ -446,7 +446,7 @@ RunClients(void) PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); @@ -477,7 +477,7 @@ void do_work() PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; diff --git a/pr/tests/servr_ku.c b/pr/tests/servr_ku.c index d785e201..25808516 100644 --- a/pr/tests/servr_ku.c +++ b/pr/tests/servr_ku.c @@ -63,7 +63,7 @@ #include <string.h> #define PORT 15004 -#define STACKSIZE 0 +#define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; @@ -192,7 +192,7 @@ WorkerThreadFunc(void *_listenSock) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) if (debug_mode) printf("Error creating client thread %d\n", workerThreads); @@ -292,7 +292,7 @@ ServerSetup(void) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); @@ -447,7 +447,7 @@ RunClients(void) PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); @@ -478,7 +478,7 @@ void do_work() PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; diff --git a/pr/tests/servr_uk.c b/pr/tests/servr_uk.c index 685c76a1..eb7d48fb 100644 --- a/pr/tests/servr_uk.c +++ b/pr/tests/servr_uk.c @@ -63,7 +63,7 @@ #include <string.h> #define PORT 15004 -#define STACKSIZE 0 +#define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; @@ -194,7 +194,7 @@ WorkerThreadFunc(void *_listenSock) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) if (debug_mode) printf("Error creating client thread %d\n", workerThreads); @@ -294,7 +294,7 @@ ServerSetup(void) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); @@ -449,7 +449,7 @@ RunClients(void) PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); @@ -480,7 +480,7 @@ void do_work() PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; diff --git a/pr/tests/servr_uu.c b/pr/tests/servr_uu.c index 4722494b..1c6f2e8f 100644 --- a/pr/tests/servr_uu.c +++ b/pr/tests/servr_uu.c @@ -63,7 +63,7 @@ #include <string.h> #define PORT 15004 -#define STACKSIZE 0 +#define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; @@ -192,7 +192,7 @@ WorkerThreadFunc(void *_listenSock) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) if (debug_mode) printf("Error creating client thread %d\n", workerThreads); @@ -292,7 +292,7 @@ ServerSetup(void) PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); @@ -447,7 +447,7 @@ RunClients(void) PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); @@ -478,7 +478,7 @@ void do_work() PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, - STACKSIZE); + THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; diff --git a/pr/tests/sigpipe.c b/pr/tests/sigpipe.c index 2c708e29..28e7e251 100644 --- a/pr/tests/sigpipe.c +++ b/pr/tests/sigpipe.c @@ -69,7 +69,7 @@ int main(void) #endif #include <errno.h> -int main(void) +static void Test(void *arg) { #ifdef XP_OS2 HFILE pipefd[2]; @@ -79,9 +79,6 @@ int main(void) int rv; char c = '\0'; - /* This initializes NSPR. */ - PR_SetError(0, 0); - #ifdef XP_OS2 if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) { #else @@ -103,6 +100,27 @@ int main(void) } close(pipefd[1]); printf("write to broken pipe failed with EPIPE, as expected\n"); +} + +int main(void) +{ + PRThread *thread; + + /* This initializes NSPR. */ + PR_SetError(0, 0); + + thread = PR_CreateThread(PR_USER_THREAD, Test, NULL, PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); + if (thread == NULL) { + fprintf(stderr, "PR_CreateThread failed\n"); + exit(1); + } + if (PR_JoinThread(thread) == PR_FAILURE) { + fprintf(stderr, "PR_JoinThread failed\n"); + exit(1); + } + Test(NULL); + printf("PASSED\n"); return 0; } diff --git a/pr/tests/sockping.c b/pr/tests/sockping.c index fb377903..477851c2 100644 --- a/pr/tests/sockping.c +++ b/pr/tests/sockping.c @@ -124,7 +124,8 @@ int main() memset(buf, 0, sizeof(buf)); nBytes = PR_Read(sock[0], buf, sizeof(buf)); if (nBytes == -1) { - fprintf(stderr, "PR_Read failed\n"); + fprintf(stderr, "PR_Read failed: (%d, %d)\n", + PR_GetError(), PR_GetOSError()); exit(1); } printf("ping process: received \"%s\"\n", buf); diff --git a/pr/tests/thrpool_server.c b/pr/tests/thrpool_server.c index df56560e..e10dd5bd 100644 --- a/pr/tests/thrpool_server.c +++ b/pr/tests/thrpool_server.c @@ -54,6 +54,13 @@ #include <pthread.h> #endif +/* for getcwd */ +#if defined(XP_UNIX) || defined (XP_OS2_EMX) || defined(XP_BEOS) +#include <unistd.h> +#elif defined(XP_PC) +#include <direct.h> +#endif + #ifdef WIN32 #include <process.h> #endif diff --git a/pr/tests/vercheck.c b/pr/tests/vercheck.c index 4235a832..0e32ef53 100644 --- a/pr/tests/vercheck.c +++ b/pr/tests/vercheck.c @@ -49,12 +49,13 @@ #include <stdlib.h> /* - * This release (4.2) is backward compatible with the - * 4.0.x and 4.1.x releases. It, of course, is compatible - * with itself. + * This release (4.5) is backward compatible with the + * 4.0.x, 4.1.x, 4.2.x, 4.3.x, and 4.4.x releases. It, of course, + * is compatible with itself. */ static char *compatible_version[] = { - "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3", PR_VERSION + "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3", + "4.2", "4.2.1", "4.2.2", "4.3", "4.4", "4.4.1", PR_VERSION }; /* @@ -69,8 +70,8 @@ static char *incompatible_version[] = { "3.0", "3.0.1", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.5", "3.5.1", - "4.2.3", - "4.3", "4.3.1", + "4.5.3", + "4.6", "4.6.1", "10.0", "11.1", "12.14.20" }; |