summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>1998-10-03 00:21:02 +0000
committerwtc%netscape.com <devnull@localhost>1998-10-03 00:21:02 +0000
commit14daeed9bb74395a844665bad68341bbfb62deeb (patch)
treed74a0973f82cacec0bdc55a6f3ba961d28f3d781
parente75df7111184579018ab3ef4990a48c602a1f43f (diff)
downloadnspr-hg-NSPRPUB_RELEASE_3_0_LANDING_BRANCH.tar.gz
Merging NSPR v3.0 release from internal source repository toNSPRPUB_RELEASE_3_0_LANDING_BRANCH
cvs.mozilla.org NSPRPUB_RELEASE_3_0_LANDING_BRANCH.
-rw-r--r--config/Linux.mk5
-rw-r--r--config/nsinstall.c7
-rw-r--r--lib/ds/plarena.c54
-rw-r--r--lib/libc/src/plerror.c1
-rw-r--r--lib/tests/arena.c265
-rw-r--r--macbuild/NSPR20PPC.mcpbin75653 -> 85613 bytes
-rw-r--r--macbuild/NSPRConfig.h6
-rw-r--r--pr/include/md/_dgux.h40
-rw-r--r--pr/include/md/_linux.h32
-rw-r--r--pr/include/md/_macos.h10
-rw-r--r--pr/include/md/_solaris.h1
-rw-r--r--pr/include/prinit.h4
-rw-r--r--pr/include/private/pprmwait.h9
-rw-r--r--pr/include/prsystem.h7
-rw-r--r--pr/src/io/prfile.c4
-rw-r--r--pr/src/io/prmwait.c111
-rw-r--r--pr/src/io/prprf.c4
-rw-r--r--pr/src/io/prsocket.c3
-rw-r--r--pr/src/md/mac/macio.c6
-rw-r--r--pr/src/md/unix/Makefile12
-rw-r--r--pr/src/md/unix/irix.c18
-rw-r--r--pr/src/md/unix/objs.mk8
-rw-r--r--pr/src/md/unix/os_SunOS_ultrasparc.s16
-rw-r--r--pr/src/md/unix/solaris.c93
-rw-r--r--pr/src/md/unix/unix.c14
-rw-r--r--pr/src/md/unix/unix_errors.c2
-rw-r--r--pr/src/md/unix/uxpoll.c2
-rw-r--r--pr/src/md/unix/uxwrap.c2
-rw-r--r--pr/src/md/windows/ntdllmn.c8
-rw-r--r--pr/src/md/windows/ntio.c3
-rw-r--r--pr/src/md/windows/w95dllmain.c8
-rw-r--r--pr/src/md/windows/w95io.c3
-rw-r--r--pr/src/misc/prinit.c1
-rw-r--r--pr/src/misc/prsystem.c17
-rw-r--r--pr/src/pthreads/ptio.c38
-rw-r--r--pr/src/pthreads/ptthread.c31
-rw-r--r--pr/tests/Makefile2
-rw-r--r--pr/tests/accept.c28
-rw-r--r--pr/tests/bigfile.c2
-rw-r--r--pr/tests/cltsrv.c6
-rw-r--r--pr/tests/foreign.c20
-rw-r--r--pr/tests/fsync.c2
-rw-r--r--pr/tests/instrumt.c1
-rw-r--r--pr/tests/ioconthr.c123
-rw-r--r--pr/tests/layer.c5
-rw-r--r--pr/tests/multiwait.c6
-rw-r--r--pr/tests/nbconn.c28
-rw-r--r--pr/tests/nblayer.c8
-rw-r--r--pr/tests/nonblock.c3
-rw-r--r--pr/tests/provider.c28
-rw-r--r--pr/tests/socket.c2
-rw-r--r--pr/tests/sockopt.c37
-rw-r--r--pr/tests/tmocon.c2
53 files changed, 946 insertions, 202 deletions
diff --git a/config/Linux.mk b/config/Linux.mk
index 50736123..855ac2c9 100644
--- a/config/Linux.mk
+++ b/config/Linux.mk
@@ -79,8 +79,7 @@ PLATFORM_FLAGS += -D_ALPHA_ -D__alpha -mieee
PORT_FLAGS += -D_XOPEN_SOURCE
endif
ifeq ($(CPU_ARCH),ppc)
-PLATFORM_FLAGS += -DMKLINUX
-OS_INCLUDES += -I/usr/local/include
+PORT_FLAGS += -D_XOPEN_SOURCE
endif
ifeq ($(CPU_ARCH),x86)
PLATFORM_FLAGS += -mno-486 -Di386
@@ -99,7 +98,7 @@ PLATFORM_FLAGS += -m68020-40
endif
#
-# Linux ppc and 2.0 have shared libraries.
+# Linux 2.x has shared libraries.
#
MKSHLIB = $(LD) $(DSO_LDOPTS) -soname $(@:$(OBJDIR)/%.so=%.so)
diff --git a/config/nsinstall.c b/config/nsinstall.c
index 8e48b357..c3a3bba8 100644
--- a/config/nsinstall.c
+++ b/config/nsinstall.c
@@ -84,6 +84,7 @@ mkdirs(char *path, mode_t mode)
{
char *cp;
struct stat sb;
+ int res;
while (*path == '/' && path[1] == '/')
path++;
@@ -97,7 +98,11 @@ mkdirs(char *path, mode_t mode)
}
*cp = '/';
}
- return mkdir(path, mode);
+ res = mkdir(path, mode);
+ if ((res != 0) && (errno == EEXIST))
+ return 0;
+ else
+ return res;
}
static uid_t
diff --git a/lib/ds/plarena.c b/lib/ds/plarena.c
index d14bf096..da6c1d01 100644
--- a/lib/ds/plarena.c
+++ b/lib/ds/plarena.c
@@ -27,6 +27,8 @@
#include "prmem.h"
#include "prbit.h"
#include "prlog.h"
+#include "prmon.h"
+#include "prinit.h"
static PLArena *arena_freelist;
@@ -40,6 +42,48 @@ static PLArenaStats *arena_stats_list;
#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
+static PRMonitor *arenaLock;
+static PRCallOnceType once;
+
+/*
+** InitializeArenas() -- Initialize arena operations.
+**
+** InitializeArenas() is called exactly once and only once from
+** LockArena(). This function creates the arena protection
+** monitor: arenaLock.
+**
+** Note: If the arenaLock cannot be created, InitializeArenas()
+** fails quietly, returning only PR_FAILURE. This percolates up
+** to the application using the Arena API. He gets no arena
+** from PL_ArenaAllocate(). It's up to him to fail gracefully
+** or recover.
+**
+*/
+static PRStatus InitializeArenas( void )
+{
+ PR_ASSERT( arenaLock == NULL );
+ arenaLock = PR_NewMonitor();
+ if ( arenaLock == NULL )
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+} /* end ArenaInitialize() */
+
+static PRStatus LockArena( void )
+{
+ PRStatus rc = PR_CallOnce( &once, InitializeArenas );
+
+ if ( PR_FAILURE != rc )
+ PR_EnterMonitor( arenaLock );
+ return(rc);
+} /* end LockArena() */
+
+static void UnlockArena( void )
+{
+ PR_ExitMonitor( arenaLock );
+ return;
+} /* end UnlockArena() */
+
PR_IMPLEMENT(void) PL_InitArenaPool(
PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
{
@@ -74,6 +118,8 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
if (nb >= 60000U)
return 0;
#endif /* WIN16 */
+ if ( PR_FAILURE == LockArena())
+ return(0);
ap = &arena_freelist;
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
if (a->next) { /* move to next arena */
@@ -94,7 +140,10 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
sz += sizeof *a + pool->mask; /* header and alignment slop */
b = (PLArena*)PR_MALLOC(sz);
if (!b)
+ {
+ UnlockArena();
return 0;
+ }
a = a->next = b;
a->next = 0;
a->limit = (PRUword)a + sz;
@@ -103,6 +152,7 @@ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
claim:
a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1);
}
+ UnlockArena();
p = (void *)a->avail;
a->avail += nb;
return p;
@@ -153,9 +203,11 @@ static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree)
do {
ap = &(*ap)->next;
} while (*ap);
+ LockArena();
*ap = arena_freelist;
arena_freelist = a;
head->next = 0;
+ UnlockArena();
}
pool->current = head;
@@ -219,11 +271,13 @@ PR_IMPLEMENT(void) PL_ArenaFinish()
{
PLArena *a, *next;
+ LockArena();
for (a = arena_freelist; a; a = next) {
next = a->next;
PR_DELETE(a);
}
arena_freelist = NULL;
+ UnlockArena();
}
#ifdef PL_ARENAMETER
diff --git a/lib/libc/src/plerror.c b/lib/libc/src/plerror.c
index 48f3f959..ce834675 100644
--- a/lib/libc/src/plerror.c
+++ b/lib/libc/src/plerror.c
@@ -96,6 +96,7 @@ static const char *tags[] =
"PR_END_OF_FILE_ERROR",
"PR_FILE_SEEK_ERROR",
"PR_FILE_IS_BUSY_ERROR",
+ "<unused error code>",
"PR_IN_PROGRESS_ERROR",
"PR_ALREADY_INITIATED_ERROR",
"PR_GROUP_EMPTY_ERROR",
diff --git a/lib/tests/arena.c b/lib/tests/arena.c
new file mode 100644
index 00000000..dc36fd51
--- /dev/null
+++ b/lib/tests/arena.c
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+** File: arena.c
+** Description: Testing arenas
+**
+*/
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "nspr.h"
+#include "plarena.h"
+#include "plgetopt.h"
+
+PRLogModuleInfo *tLM;
+PRIntn threadCount = 0;
+PRMonitor *tMon;
+PRBool failed_already = PR_FALSE;
+
+/* Arguments from the command line with default values */
+PRIntn debug_mode = 0;
+PRIntn poolMin = 4096;
+PRIntn poolMax = (100 * 4096);
+PRIntn arenaMin = 40;
+PRIntn arenaMax = (100 * 40);
+PRIntn stressIterations = 15;
+PRIntn maxAlloc = (1024 * 1024);
+PRIntn stressThreads = 4;
+
+/*
+** Test arena Mark and Release.
+*/
+static void MarkAndRelease( void )
+{
+ PLArenaPool ap;
+ void *ptr;
+ void *mark;
+
+ PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+
+ mark = PL_ARENA_MARK( &ap );
+
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+
+ PL_ARENA_RELEASE( &ap, mark );
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+
+ if ( ptr != mark )
+ {
+ failed_already = PR_TRUE;
+ PR_LOG( tLM, PR_LOG_ERROR, ("Mark and Release failed: expected %p, got %p\n", mark, ptr));
+ }
+ else
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Mark and Release passed\n"));
+
+ return;
+} /* end MarkAndRelease() */
+
+/*
+** RandSize() returns a random number in the range
+** min..max, rounded to the next doubleword
+**
+*/
+static PRIntn RandSize( PRIntn min, PRIntn max )
+{
+ PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
+
+ sz &= ~sizeof(double)-1;
+
+ return(sz);
+}
+
+
+/*
+** StressThread()
+** A bunch of these beat on individual arenas
+** This tests the free_list protection.
+**
+*/
+static void PR_CALLBACK StressThread( void *arg )
+{
+ PLArenaPool ap;
+ PRIntn i;
+ PRIntn sz;
+ void *ptr;
+ PRThread *tp = PR_GetCurrentThread();
+
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
+ PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
+
+ for ( i = 0; i < stressIterations; i++ )
+ {
+ PRIntn allocated = 0;
+
+ while ( allocated < maxAlloc )
+ {
+ sz = RandSize( arenaMin, arenaMax );
+ PL_ARENA_ALLOCATE( ptr, &ap, sz );
+ if ( ptr == NULL )
+ {
+ PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
+ break;
+ }
+ allocated += sz;
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
+ PL_FreeArenaPool( &ap );
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
+ PL_FinishArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
+
+ /* That's all folks! let's quit */
+ PR_EnterMonitor(tMon);
+ threadCount--;
+ PR_Notify(tMon);
+ PR_ExitMonitor(tMon);
+ return;
+}
+
+/*
+** Stress()
+** Flog the hell out of arenas multi-threaded.
+** Do NOT pass an individual arena to another thread.
+**
+*/
+static void Stress( void )
+{
+ PRThread *tt;
+ PRIntn i;
+
+ tMon = PR_NewMonitor();
+
+ for ( i = 0 ; i < stressThreads ; i++ )
+ {
+ PR_EnterMonitor(tMon);
+ tt = PR_CreateThread(PR_USER_THREAD,
+ StressThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ threadCount++;
+ PR_ExitMonitor(tMon);
+ }
+
+ /* Wait for all threads to exit */
+ PR_EnterMonitor(tMon);
+ while ( threadCount != 0 )
+ {
+ PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(tMon);
+ PR_DestroyMonitor(tMon);
+
+ return;
+} /* end Stress() */
+
+/*
+** EvaluateResults()
+** uses failed_already to display results and set program
+** exit code.
+*/
+static PRIntn EvaluateResults(void)
+{
+ PRIntn rc = 0;
+
+ if ( failed_already == PR_TRUE )
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
+ rc =1;
+ }
+ else
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
+ }
+ return(rc);
+} /* EvaluateResults() */
+
+void Help( void )
+{
+ printf("arena [options]\n");
+ printf("where options are:\n");
+ printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
+ printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
+ printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
+ printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
+ printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
+ printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
+ printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
+ printf("-d enable debug mode\n");
+ printf("\n");
+ exit(1);
+}
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'a': /* arena Min size */
+ arenaMin = atol( opt->value );
+ break;
+ case 'A': /* arena Max size */
+ arenaMax = atol( opt->value );
+ break;
+ case 'p': /* pool Min size */
+ poolMin = atol( opt->value );
+ break;
+ case 'P': /* pool Max size */
+ poolMax = atol( opt->value );
+ break;
+ case 'i': /* Iterations in stress tests */
+ stressIterations = atol( opt->value );
+ break;
+ case 's': /* storage to get per iteration */
+ maxAlloc = atol( opt->value );
+ break;
+ case 't': /* Number of stress threads to create */
+ stressThreads = atol( opt->value );
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'h': /* help */
+ default:
+ Help();
+ } /* end switch() */
+ } /* end while() */
+ PL_DestroyOptState(opt);
+
+ srand( (unsigned)time( NULL ) ); /* seed random number generator */
+ tLM = PR_NewLogModule("testcase");
+
+ MarkAndRelease();
+
+ Stress();
+
+ return(EvaluateResults());
+} /* end main() */
+
+/* arena.c */
diff --git a/macbuild/NSPR20PPC.mcp b/macbuild/NSPR20PPC.mcp
index 57934998..f15a68a2 100644
--- a/macbuild/NSPR20PPC.mcp
+++ b/macbuild/NSPR20PPC.mcp
Binary files differ
diff --git a/macbuild/NSPRConfig.h b/macbuild/NSPRConfig.h
index e97579b5..ba24c343 100644
--- a/macbuild/NSPRConfig.h
+++ b/macbuild/NSPRConfig.h
@@ -16,11 +16,9 @@
* Reserved.
*/
-#define OLDROUTINELOCATIONS 0
+#include "DefinesMac.h"
+#include "DefinesMozilla.h"
-#define XP_MAC 1
#define _PR_NO_PREEMPT 1
#define _NO_FAST_STRING_INLINES_ 1
#define FORCE_PR_LOG 1
-#define NSPR20 1
-
diff --git a/pr/include/md/_dgux.h b/pr/include/md/_dgux.h
index f428e03a..ba8497bd 100644
--- a/pr/include/md/_dgux.h
+++ b/pr/include/md/_dgux.h
@@ -46,6 +46,8 @@
#define _PR_NEED_STRCASECMP
#define _PR_POLL_AVAILABLE
#define _PR_USE_POLL
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
#define USE_SETJMP
@@ -115,8 +117,44 @@ struct _MDSegment {
PRInt8 notused;
};
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
struct _MDCPU {
- struct _MDCPU_Unix md_unix;
+ struct _MDCPU_Unix md_unix;
};
#define _MD_INIT_LOCKS()
diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h
index c7c33ce8..403b6cea 100644
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -59,13 +59,11 @@
#define HAVE_DLL
#define USE_DLFCN
-#if !defined(MKLINUX) && !defined(NEED_TIME_R)
-#define NEED_TIME_R
-#endif
-
#define USE_SETJMP
+#if defined(__GLIBC__) && __GLIBC__ >= 2
#define _PR_POLL_AVAILABLE
-#define _PR_USE_POLL
+#endif
+#undef _PR_USE_POLL
#define _PR_STAT_HAS_ONLY_ST_ATIME
#if defined(__alpha)
#define _PR_HAVE_LARGE_OFF_T
@@ -87,8 +85,17 @@ extern void _MD_CleanupBeforeExit(void);
#define CONTEXT(_th) ((_th)->md.context)
#ifdef __powerpc__
-/* PowerPC based MkLinux */
+/*
+ * PowerPC based MkLinux
+ *
+ * On the PowerPC, the new style jmp_buf isn't used until glibc
+ * 2.1.
+ */
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_GPR1]
+#else
#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__misc[0]
+#endif /* __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 */
#define _MD_SET_FP(_t, val)
#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
#define _MD_GET_FP_PTR(_t) ((void *) 0)
@@ -192,6 +199,18 @@ extern void _MD_CleanupBeforeExit(void);
#error "Linux/MIPS pre-glibc2 not supported yet"
#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+#elif defined(__arm__)
+/* ARM/Linux */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[20]
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[19] = (val))
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[19])
+#define _MD_SP_TYPE __ptr_t
+#else
+#error "ARM/Linux pre-glibc2 not supported yet"
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
#else
#error "Unknown CPU architecture"
@@ -293,6 +312,7 @@ struct _MDSegment {
/*
* md-specific cpu structure field
*/
+#include <sys/time.h> /* for FD_SETSIZE */
#define _PR_MD_MAX_OSFD FD_SETSIZE
struct _MDCPU_Unix {
diff --git a/pr/include/md/_macos.h b/pr/include/md/_macos.h
index ffeb1fa8..a4e9b137 100644
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -463,13 +463,11 @@ typedef short PROSFD;
// Errors not found in the Mac StdCLib
#define EACCES 13 // Permission denied
#define ENOENT -43 // No such file or directory
-#define EMFILE 24 // Too many open files
#define _OS_INVALID_FD_VALUE -1
#define STDERR_FILENO 2
#if !defined(MAC_NSPR_STANDALONE)
-#define MAC_PATH_SEPARATOR ':'
#define PATH_SEPARATOR ':'
#define PATH_SEPARATOR_STR ":"
#define DIRECTORY_SEPARATOR '/'
@@ -479,10 +477,6 @@ typedef short PROSFD;
#define UNIX_THIS_DIRECTORY_STR "./"
#define UNIX_PARENT_DIRECTORY_STR "../"
-#define MAX_PATH 512
-#define MAX_MAC_FILENAME 31
-#define MAXPATHLEN MAX_PATH
-
// Alias a few names
#define getenv PR_GetEnv
@@ -534,10 +528,6 @@ extern void dprintf(const char *format, ...);
extern PRUint8 CallCacheFlushers(size_t blockSize);
#endif
-enum {
- kPrivateNSPREventType = 13
-};
-
#if defined(MAC_NSPR_STANDALONE)
extern void* reallocSmaller(void* block, size_t newSize);
#endif
diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h
index aaa646c1..616c666b 100644
--- a/pr/include/md/_solaris.h
+++ b/pr/include/md/_solaris.h
@@ -340,7 +340,6 @@ extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
#define _MD_SELECT _select
-#include <stropts.h>
#include <poll.h>
#define _MD_POLL _poll
extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
diff --git a/pr/include/prinit.h b/pr/include/prinit.h
index 7ba12fea..b531b85d 100644
--- a/pr/include/prinit.h
+++ b/pr/include/prinit.h
@@ -44,11 +44,11 @@ PR_BEGIN_EXTERN_C
** The format of the version string is
** "<major version>.<minor version> <build date>"
*/
-#define PR_VERSION "3.0 yyyymmdd"
+#define PR_VERSION "3.0 19981002"
#define PR_VMAJOR 3
#define PR_VMINOR 0
#define PR_VPATCH 0
-#define PR_BETA PR_TRUE
+#define PR_BETA PR_FALSE
/*
** PRVersionCheck
diff --git a/pr/include/private/pprmwait.h b/pr/include/private/pprmwait.h
index edad3420..a47e4668 100644
--- a/pr/include/private/pprmwait.h
+++ b/pr/include/private/pprmwait.h
@@ -25,14 +25,19 @@
#include "prclist.h"
#include "prthread.h"
-#define _PR_HASH_OFFSET 75013
#define MAX_POLLING_INTERVAL 100
#define _PR_POLL_COUNT_FUDGE 64
#define MAX_POLLING_INTERVAL 100
#define _PR_DEFAULT_HASH_LENGTH 59
-#define _MW_REHASH(a, i, m) _MW_HASH((PRUptrdiff)(a) + (i) + _PR_HASH_OFFSET, m)
+/*
+ * Our hash table resolves collisions by open addressing with
+ * double hashing. See Cormen, Leiserson, and Rivest,
+ * Introduction to Algorithms, p. 232, The MIT Press, 1990.
+ */
+
#define _MW_HASH(a, m) ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m))
+#define _MW_HASH2(a, m) (1 + ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m - 2)))
#define _MW_ABORTED(_rv) \
((PR_FAILURE == (_rv)) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
diff --git a/pr/include/prsystem.h b/pr/include/prsystem.h
index cb153e76..96c57d50 100644
--- a/pr/include/prsystem.h
+++ b/pr/include/prsystem.h
@@ -32,6 +32,13 @@ PR_BEGIN_EXTERN_C
** [<sep><root_component><sep>]*(<component><sep>)<leaf_name>
*/
+PR_EXTERN(char) PR_GetDirectorySeparator(void);
+
+/*
+** OBSOLETE -- the function name is misspelled.
+** Use PR_GetDirectorySeparator instead.
+*/
+
PR_EXTERN(char) PR_GetDirectorySepartor(void);
diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c
index bb9730f1..ece72b0a 100644
--- a/pr/src/io/prfile.c
+++ b/pr/src/io/prfile.c
@@ -507,6 +507,8 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
HANDLE readEnd, writeEnd;
SECURITY_ATTRIBUTES pipeAttributes;
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
ZeroMemory(&pipeAttributes, sizeof(pipeAttributes));
pipeAttributes.nLength = sizeof(pipeAttributes);
pipeAttributes.bInheritHandle = TRUE;
@@ -534,6 +536,8 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
#elif defined(XP_UNIX)
int pipefd[2];
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
if (pipe(pipefd) == -1) {
/* XXX map pipe error */
PR_SetError(PR_UNKNOWN_ERROR, errno);
diff --git a/pr/src/io/prmwait.c b/pr/src/io/prmwait.c
index 5f6e9a72..98becef2 100644
--- a/pr/src/io/prmwait.c
+++ b/pr/src/io/prmwait.c
@@ -268,6 +268,8 @@ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
PRIntn rehash = _MW_REHASH_MAX;
PRRecvWait **waiter;
PRUintn hidx = _MW_HASH(desc->fd, hash->length);
+ PRUintn hoffset = 0;
+
while (rehash-- > 0)
{
waiter = &hash->recv_wait;
@@ -294,7 +296,12 @@ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
"table[*%u:%u:%u]: 0x%x->0x%x\n",
hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd);
#endif
- hidx = _MW_REHASH(desc->fd, hidx, hash->length);
+ if (0 == hoffset)
+ {
+ hoffset = _MW_HASH2(desc->fd, hash->length);
+ PR_ASSERT(0 != hoffset);
+ }
+ hidx = (hidx + hoffset) % (hash->length);
}
return _prmw_rehash;
} /* MW_AddHashInternal */
@@ -302,56 +309,71 @@ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
static _PR_HashStory MW_ExpandHashInternal(PRWaitGroup *group)
{
PRRecvWait **desc;
- PRUint32 pidx, length = 0;
+ PRUint32 pidx, length;
_PRWaiterHash *newHash, *oldHash = group->waiter;
-
+ PRBool retry;
+ _PR_HashStory hrv;
static const PRInt32 prime_number[] = {
_PR_DEFAULT_HASH_LENGTH, 179, 521, 907, 1427,
2711, 3917, 5021, 8219, 11549, 18911, 26711, 33749, 44771};
- PRUintn primes = (sizeof(prime_number) / sizeof(PRIntn));
+ PRUintn primes = (sizeof(prime_number) / sizeof(PRInt32));
/* look up the next size we'd like to use for the hash table */
for (pidx = 0; pidx < primes; ++pidx)
{
if (prime_number[pidx] == oldHash->length)
{
- length = prime_number[pidx + 1];
break;
}
}
- if (0 == length)
- {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return _prmw_error; /* we're hosed */
- }
+ /* table size must be one of the prime numbers */
+ PR_ASSERT(pidx < primes);
- /* allocate the new hash table and fill it in with the old */
- newHash = (_PRWaiterHash*)PR_CALLOC(
- sizeof(_PRWaiterHash) + (length * sizeof(PRRecvWait*)));
- if (NULL == newHash)
+ /* if pidx == primes - 1, we can't expand the table any more */
+ while (pidx < primes - 1)
{
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return _prmw_error;
- }
+ /* next size */
+ ++pidx;
+ length = prime_number[pidx];
+
+ /* allocate the new hash table and fill it in with the old */
+ newHash = (_PRWaiterHash*)PR_CALLOC(
+ sizeof(_PRWaiterHash) + (length * sizeof(PRRecvWait*)));
+ if (NULL == newHash)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return _prmw_error;
+ }
- newHash->length = length;
- for (desc = &oldHash->recv_wait; newHash->count < oldHash->count; ++desc)
- {
- if (NULL != *desc)
+ newHash->length = length;
+ retry = PR_FALSE;
+ for (desc = &oldHash->recv_wait;
+ newHash->count < oldHash->count; ++desc)
{
- if (_prmw_success != MW_AddHashInternal(*desc, newHash))
+ PR_ASSERT(desc < &oldHash->recv_wait + oldHash->length);
+ if (NULL != *desc)
{
- PR_ASSERT(!"But, but, but ...");
- PR_DELETE(newHash);
- return _prmw_error;
+ hrv = MW_AddHashInternal(*desc, newHash);
+ PR_ASSERT(_prmw_error != hrv);
+ if (_prmw_success != hrv)
+ {
+ PR_DELETE(newHash);
+ retry = PR_TRUE;
+ break;
+ }
}
}
+ if (retry) continue;
+
+ PR_DELETE(group->waiter);
+ group->waiter = newHash;
+ group->p_timestamp += 1;
+ return _prmw_success;
}
- PR_DELETE(group->waiter);
- group->waiter = newHash;
- group->p_timestamp += 1;
- return _prmw_success;
+
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return _prmw_error; /* we're hosed */
} /* MW_ExpandHashInternal */
#ifndef WINNT
@@ -387,12 +409,18 @@ static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd)
PRIntn rehash = _MW_REHASH_MAX;
_PRWaiterHash *hash = group->waiter;
PRUintn hidx = _MW_HASH(fd, hash->length);
+ PRUintn hoffset = 0;
while (rehash-- > 0)
{
desc = (&hash->recv_wait) + hidx;
if ((*desc != NULL) && ((*desc)->fd == fd)) return desc;
- hidx = _MW_REHASH(fd, hidx, hash->length);
+ if (0 == hoffset)
+ {
+ hoffset = _MW_HASH2(fd, hash->length);
+ PR_ASSERT(0 != hoffset);
+ }
+ hidx = (hidx + hoffset) % (hash->length);
}
return NULL;
} /* _MW_LookupInternal */
@@ -849,6 +877,14 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
me->state = _PR_RUNNING;
PR_Lock(group->ml);
_PR_MD_LOCK(&group->mdlock);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ PR_REMOVE_LINK(&me->waitQLinks);
+ _PR_MD_UNLOCK(&group->mdlock);
+ me->flags &= ~_PR_INTERRUPT;
+ me->io_suspended = PR_FALSE;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ goto aborted;
+ }
}
io_ready = PR_LIST_HEAD(&group->io_ready);
PR_ASSERT(io_ready != NULL);
@@ -948,11 +984,12 @@ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
PR_REMOVE_LINK(io_ready);
} while (NULL == io_ready);
-aborted:
failed_poll:
#endif
+aborted:
+
group->waiting_threads -= 1;
invalid_state:
(void)MW_TestForShutdownInternal(group);
@@ -1184,6 +1221,18 @@ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
overlapped = (_MDOverlapped *)
((char *)head - offsetof(_MDOverlapped, data));
head = &overlapped->data.mw.desc->internal;
+ if (NULL != overlapped->data.mw.timer)
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ != overlapped->data.mw.desc->timeout);
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ else
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ == overlapped->data.mw.desc->timeout);
+ }
+ PR_DELETE(overlapped);
#endif
recv_wait = (PRRecvWait*)head;
}
diff --git a/pr/src/io/prprf.c b/pr/src/io/prprf.c
index 2ce93d18..ee6fc44d 100644
--- a/pr/src/io/prprf.c
+++ b/pr/src/io/prprf.c
@@ -35,11 +35,11 @@
** Note: on some platforms va_list is defined as an array,
** and requires array notation.
*/
-#if defined(MKLINUX) || defined(WIN16)
+#if (defined(LINUX) && defined(__powerpc__)) || defined(WIN16)
#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
#else
#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
-#endif /*MKLINUX*/
+#endif
/*
** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it)
diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c
index 11611cfa..22dcd721 100644
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -1116,6 +1116,8 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
#ifdef XP_UNIX
PRInt32 rv, osfd[2];
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd);
if (rv == -1) {
return PR_FAILURE;
@@ -1356,7 +1358,6 @@ PRInt32 _PR_EmulateAcceptRead(
return rv;
}
-failed:
PR_Close(accepted);
return rv;
}
diff --git a/pr/src/md/mac/macio.c b/pr/src/md/mac/macio.c
index 8a1474f4..24d9f29f 100644
--- a/pr/src/md/mac/macio.c
+++ b/pr/src/md/mac/macio.c
@@ -333,7 +333,7 @@ PRInt32 _MD_Open(const char *path, PRIntn oflag, int mode)
#pragma unused (mode)
OSErr err;
- ParamBlockRec pb;
+ HParamBlockRec pb;
char *macFileName = NULL;
Str255 pascalName;
PRInt8 perm;
@@ -375,13 +375,13 @@ open:
pb.ioParam.ioMisc = NULL;
- err = PBOpenSync(&pb);
+ err = PBHOpenSync(&pb);
if (err == noErr)
return pb.ioParam.ioRefNum;
else if ((err != fnfErr) || ((oflag & O_CREAT) == 0))
goto ErrorExit;
- err = PBCreateSync(&pb);
+ err = PBHCreateSync(&pb);
if (err == noErr)
goto open;
diff --git a/pr/src/md/unix/Makefile b/pr/src/md/unix/Makefile
index 7d36371c..0ab98fdc 100644
--- a/pr/src/md/unix/Makefile
+++ b/pr/src/md/unix/Makefile
@@ -195,7 +195,7 @@ ifeq ($(OS_ARCH),SunOS)
else
ifneq ($(OS_RELEASE),4.1.3_U1)
ifneq ($(LOCAL_THREADS_ONLY),1)
- ASFILES = os_$(OS_ARCH).s
+ ASFILES += os_$(OS_ARCH).s
endif
endif
endif
@@ -226,12 +226,10 @@ endif
ifeq ($(OS_ARCH),SunOS)
ifneq ($(OS_RELEASE),4.1.3_U1)
ifeq ($(OS_TEST),sun4u)
- LIBRARY_NAME = $(ULTRASPARC_LIBRARY)
- LIBRARY_VERSION = $(MOD_VERSION)
ULTRASPARC_ASFILES = os_$(OS_ARCH)_ultrasparc.s
+ ASFILES += $(ULTRASPARC_ASFILES)
+ CFLAGS += -D_PR_ULTRASPARC
ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
- TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY)
- RELEASE_LIBS = $(SHARED_LIBRARY)
endif
endif
endif
@@ -252,10 +250,6 @@ export:: $(TARGETS)
ifeq ($(OS_ARCH),SunOS)
ifneq ($(OS_RELEASE),4.1.3_U1)
ifeq ($(OS_TEST),sun4u)
-$(SHARED_LIBRARY): $(ULTRASPARC_ASOBJS)
- $(LD) -G -z text -o $@ $(ULTRASPARC_ASOBJS)
- $(INSTALL) -m 444 $(SHARED_LIBRARY) $(DIST)/lib
-
$(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES)
/usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v8plus $<
endif
diff --git a/pr/src/md/unix/irix.c b/pr/src/md/unix/irix.c
index 9e1963b5..2432838d 100644
--- a/pr/src/md/unix/irix.c
+++ b/pr/src/md/unix/irix.c
@@ -105,6 +105,7 @@ PRInt32 _pr_irix_process_exit = 0; /* process exiting due to call to
int _pr_irix_primoridal_cpu_fd[2] = { -1, -1 };
static void (*libc_exit)(int) = NULL;
+static void *libc_handle = NULL;
#define _NSPR_DEF_INITUSERS 100 /* default value of CONF_INITUSERS */
#define _NSPR_DEF_INITSIZE (4 * 1024 * 1024) /* 4 MB */
@@ -1002,10 +1003,20 @@ void exit(int status)
{
PRThread *me, *thr;
PRCList *qp;
-void __exit(int status);
- if (!_pr_initialized)
- __exit(status);
+ if (!_pr_initialized) {
+ if (!libc_exit) {
+
+ if (!libc_handle)
+ libc_handle = dlopen("libc.so",RTLD_NOW);
+ if (libc_handle)
+ libc_exit = (void (*)(int)) dlsym(libc_handle, "exit");
+ }
+ if (libc_exit)
+ (*libc_exit)(status);
+ else
+ _exit(status);
+ }
me = _PR_MD_CURRENT_THREAD();
@@ -1429,7 +1440,6 @@ void _MD_IrixInit()
#if !defined(_PR_PTHREADS)
struct sigaction sigact;
PRThread *me = _PR_MD_CURRENT_THREAD();
- void *libc_handle;
int rv;
#ifndef IRIX5_3
diff --git a/pr/src/md/unix/objs.mk b/pr/src/md/unix/objs.mk
index 1d321324..7c74f98a 100644
--- a/pr/src/md/unix/objs.mk
+++ b/pr/src/md/unix/objs.mk
@@ -194,6 +194,14 @@ ifeq ($(OS_ARCH),SunOS)
endif
endif
+ifeq ($(OS_ARCH),SunOS)
+ ifneq ($(OS_RELEASE),4.1.3_U1)
+ ifeq ($(OS_TEST),sun4u)
+ ASFILES += os_$(OS_ARCH)_ultrasparc.s
+ endif
+ endif
+endif
+
ifeq ($(OS_ARCH), SINIX)
ASFILES = os_ReliantUNIX.s
endif
diff --git a/pr/src/md/unix/os_SunOS_ultrasparc.s b/pr/src/md/unix/os_SunOS_ultrasparc.s
index 8dd70636..c3faf106 100644
--- a/pr/src/md/unix/os_SunOS_ultrasparc.s
+++ b/pr/src/md/unix/os_SunOS_ultrasparc.s
@@ -49,7 +49,7 @@
! %o3 [local] - work register
! -----------------------
- ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue
+ ENTRY(_pr_md_ultrasparc_inc) ! standard assembler/ELF prologue
retryAI:
ld [%o0], %o2 ! set o2 to the current value
@@ -62,7 +62,7 @@ retryAI:
retl ! return back to the caller
mov %o1, %o0 ! set the return code to the new value
- SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue
+ SET_SIZE(_pr_md_ultrasparc_inc) ! standard assembler/ELF epilogue
!
! end
@@ -93,7 +93,7 @@ retryAI:
! %o3 [local] - work register
! -----------------------
- ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue
+ ENTRY(_pr_md_ultrasparc_dec) ! standard assembler/ELF prologue
retryAD:
ld [%o0], %o2 ! set o2 to the current value
@@ -106,7 +106,7 @@ retryAD:
retl ! return back to the caller
mov %o1, %o0 ! set the return code to the new value
- SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue
+ SET_SIZE(_pr_md_ultrasparc_dec) ! standard assembler/ELF epilogue
!
! end
@@ -136,7 +136,7 @@ retryAD:
! %o3 [local] - work register
! -----------------------
- ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue
+ ENTRY(_pr_md_ultrasparc_set) ! standard assembler/ELF prologue
retryAS:
ld [%o0], %o2 ! set o2 to the current value
@@ -148,7 +148,7 @@ retryAS:
retl ! return back to the caller
mov %o3, %o0 ! set the return code to the prev value
- SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue
+ SET_SIZE(_pr_md_ultrasparc_set) ! standard assembler/ELF epilogue
!
! end
@@ -164,7 +164,7 @@ retryAS:
! usage : newval = PR_AtomicAdd(address, val)
! return: the value after addition
!
- ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue
+ ENTRY(_pr_md_ultrasparc_add) ! standard assembler/ELF prologue
retryAA:
ld [%o0], %o2 ! set o2 to the current value
@@ -177,7 +177,7 @@ retryAA:
retl ! return back to the caller
mov %o4, %o0 ! set the return code to the new value
- SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue
+ SET_SIZE(_pr_md_ultrasparc_add) ! standard assembler/ELF epilogue
!
! end
diff --git a/pr/src/md/unix/solaris.c b/pr/src/md/unix/solaris.c
index 882cbca4..9edb6b5b 100644
--- a/pr/src/md/unix/solaris.c
+++ b/pr/src/md/unix/solaris.c
@@ -19,6 +19,7 @@
#undef _FILE_OFFSET_BITS
#include "primpl.h"
+#include <sys/systeminfo.h>
extern PRBool suspendAllOn;
@@ -58,8 +59,24 @@ PRIntervalTime _MD_Solaris_GetInterval(void)
}
#ifdef _PR_PTHREADS
+
+static PRInt32 _md_ultrasparc = 0;
+
void _MD_EarlyInit(void)
{
+#define MACHINE_NAME_LEN 32
+#define ULTRASPARC "sun4u"
+char machine[MACHINE_NAME_LEN];
+int rv;
+
+ rv = sysinfo(SI_MACHINE, machine, MACHINE_NAME_LEN);
+ /*
+ * detect an ultrasparc (Sparc V9) system
+ */
+ if ((rv > 0) && (rv <= MACHINE_NAME_LEN)) {
+ if (!strncmp(machine,ULTRASPARC, strlen(ULTRASPARC)))
+ _md_ultrasparc = 1;
+ }
}
PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
@@ -90,13 +107,22 @@ PRInt32
_MD_AtomicIncrement(PRInt32 *val)
{
PRInt32 rv;
- if (mutex_lock(&_solaris_atomic) != 0)
- PR_ASSERT(0);
- rv = ++(*val);
+#ifdef _PR_ULTRASPARC
+ if (_md_ultrasparc) {
+ rv = _pr_md_ultrasparc_inc(val);
+ } else {
+#endif
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
- if (mutex_unlock(&_solaris_atomic) != 0)\
- PR_ASSERT(0);
+ rv = ++(*val);
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+#ifdef _PR_ULTRASPARC
+ }
+#endif
return rv;
}
@@ -105,13 +131,22 @@ PRInt32
_MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
{
PRInt32 rv;
- if (mutex_lock(&_solaris_atomic) != 0)
- PR_ASSERT(0);
- rv = ((*ptr) += val);
+#ifdef _PR_ULTRASPARC
+ if (_md_ultrasparc) {
+ rv = _pr_md_ultrasparc_add(ptr, val);
+ } else {
+#endif
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = ((*ptr) += val);
- if (mutex_unlock(&_solaris_atomic) != 0)\
- PR_ASSERT(0);
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+#ifdef _PR_ULTRASPARC
+ }
+#endif
return rv;
}
@@ -120,14 +155,22 @@ PRInt32
_MD_AtomicDecrement(PRInt32 *val)
{
PRInt32 rv;
- if (mutex_lock(&_solaris_atomic) != 0)
- PR_ASSERT(0);
- rv = --(*val);
+#ifdef _PR_ULTRASPARC
+ if (_md_ultrasparc) {
+ rv = _pr_md_ultrasparc_dec(val);
+ } else {
+#endif
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
- if (mutex_unlock(&_solaris_atomic) != 0)\
- PR_ASSERT(0);
+ rv = --(*val);
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+#ifdef _PR_ULTRASPARC
+ }
+#endif
return rv;
}
@@ -135,15 +178,23 @@ PRInt32
_MD_AtomicSet(PRInt32 *val, PRInt32 newval)
{
PRInt32 rv;
- if (mutex_lock(&_solaris_atomic) != 0)
- PR_ASSERT(0);
- rv = *val;
- *val = newval;
+#ifdef _PR_ULTRASPARC
+ if (_md_ultrasparc) {
+ rv = _pr_md_ultrasparc_set(val, newval);
+ } else {
+#endif
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
- if (mutex_unlock(&_solaris_atomic) != 0)\
- PR_ASSERT(0);
+ rv = *val;
+ *val = newval;
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+#ifdef _PR_ULTRASPARC
+ }
+#endif
return rv;
}
#endif /* _PR_HAVE_ATOMIC_OPS */
diff --git a/pr/src/md/unix/unix.c b/pr/src/md/unix/unix.c
index dd7e6d91..57d167ba 100644
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -30,7 +30,7 @@
#include <sys/mman.h>
#ifdef _PR_POLL_AVAILABLE
-#include <sys/poll.h>
+#include <poll.h>
#endif
/* To get FIONREAD */
@@ -1429,16 +1429,15 @@ extern sigset_t ints_off;
*/
if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
if (_PR_IOQ_POLLFDS(me->cpu) != NULL)
- PR_DELETE(pollfds);
+ PR_DELETE(_PR_IOQ_POLLFDS(me->cpu));
pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
_PR_IOQ_POLLFDS(me->cpu) = pollfds;
_PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
- pollfdPtr = pollfds;
} else {
pollfds = _PR_IOQ_POLLFDS(me->cpu);
- pollfdPtr = pollfds;
}
+ pollfdPtr = pollfds;
/*
* If we need to poll the pipe for waking up a native thread,
@@ -2522,7 +2521,12 @@ static PRIntn _MD_solaris25_stat64(const char *fn, _MDStat64 *buf)
static PRIntn _MD_Unix_lockf64(PRIntn osfd, PRIntn function, PRInt64 size)
{
-#if defined(RHAPSODY) || defined(BSDI)
+#if defined(HAVE_BSD_FLOCK)
+ /*
+ * XXX: HAVE_BSD_FLOCK is not really the appropriate macro
+ * to test for here. We are trying to identify the platforms
+ * that don't have lockf, e.g., BSD/OS, FreeBSD, and Rhapsody.
+ */
/* No lockf */
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
return -1;
diff --git a/pr/src/md/unix/unix_errors.c b/pr/src/md/unix/unix_errors.c
index e080138a..21e44464 100644
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -18,7 +18,7 @@
#include "primpl.h"
#if defined(_PR_POLL_AVAILABLE)
-#include <sys/poll.h>
+#include <poll.h>
#endif
#include <errno.h>
diff --git a/pr/src/md/unix/uxpoll.c b/pr/src/md/unix/uxpoll.c
index a4f6b6fc..244782bf 100644
--- a/pr/src/md/unix/uxpoll.c
+++ b/pr/src/md/unix/uxpoll.c
@@ -25,7 +25,7 @@
#include <fcntl.h>
#ifdef _PR_USE_POLL
-#include <sys/poll.h>
+#include <poll.h>
#endif
#if defined(_PR_USE_POLL)
diff --git a/pr/src/md/unix/uxwrap.c b/pr/src/md/unix/uxwrap.c
index 9a26c90d..a6c7cc06 100644
--- a/pr/src/md/unix/uxwrap.c
+++ b/pr/src/md/unix/uxwrap.c
@@ -303,7 +303,7 @@ int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
*-----------------------------------------------------------------------
*/
-#include <sys/poll.h>
+#include <poll.h>
#if defined(AIX4_1)
int wrap_poll(void *listptr, unsigned long nfds, long timeout)
diff --git a/pr/src/md/windows/ntdllmn.c b/pr/src/md/windows/ntdllmn.c
index c9736a6e..2f660d3d 100644
--- a/pr/src/md/windows/ntdllmn.c
+++ b/pr/src/md/windows/ntdllmn.c
@@ -56,9 +56,11 @@ PRThread *me;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
- me = _MD_GET_ATTACHED_THREAD();
- if ((me != NULL) && (me->flags & _PR_ATTACHED))
- _PRI_DetachThread();
+ if (_pr_initialized) {
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ }
break;
case DLL_PROCESS_DETACH:
break;
diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c
index 160f2cf0..0e09cd8b 100644
--- a/pr/src/md/windows/ntio.c
+++ b/pr/src/md/windows/ntio.c
@@ -2101,8 +2101,7 @@ _PR_MD_FSYNC(PRFileDesc *fd)
* because of this, and if it was, I ignore the error.
*/
- long handle = _get_osfhandle(fd->secret->md.osfd);
- BOOL ok = FlushFileBuffers((HANDLE)handle);
+ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd);
if (!ok) {
DWORD err = GetLastError();
diff --git a/pr/src/md/windows/w95dllmain.c b/pr/src/md/windows/w95dllmain.c
index ae83ec44..1ef299d3 100644
--- a/pr/src/md/windows/w95dllmain.c
+++ b/pr/src/md/windows/w95dllmain.c
@@ -39,9 +39,11 @@ PRThread *me;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
- me = _MD_GET_ATTACHED_THREAD();
- if ((me != NULL) && (me->flags & _PR_ATTACHED))
- _PRI_DetachThread();
+ if (_pr_initialized) {
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ }
break;
case DLL_PROCESS_DETACH:
break;
diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c
index 913d6ef9..173a3a58 100644
--- a/pr/src/md/windows/w95io.c
+++ b/pr/src/md/windows/w95io.c
@@ -282,8 +282,7 @@ _PR_MD_FSYNC(PRFileDesc *fd)
* to this bogosity, and if it was, I ignore the error.
*/
- long handle = _get_osfhandle(fd->secret->md.osfd);
- BOOL ok = FlushFileBuffers((HANDLE)handle);
+ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd);
if (!ok) {
DWORD err = GetLastError();
diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c
index 4178e3ee..6960b153 100644
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -355,6 +355,7 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
* _PR_XXXCleanup() that we can call here.
*/
_PR_CleanupBeforeExit();
+ _pr_initialized = PR_FALSE;
return PR_SUCCESS;
}
return PR_FAILURE;
diff --git a/pr/src/misc/prsystem.c b/pr/src/misc/prsystem.c
index cf23e256..de907d5a 100644
--- a/pr/src/misc/prsystem.c
+++ b/pr/src/misc/prsystem.c
@@ -25,9 +25,24 @@
#include <sys/utsname.h>
#endif
-PR_IMPLEMENT(char) PR_GetDirectorySepartor()
+PR_IMPLEMENT(char) PR_GetDirectorySeparator()
{
return PR_DIRECTORY_SEPARATOR;
+} /* PR_GetDirectorySeparator */
+
+/*
+** OBSOLETE -- the function name is misspelled.
+*/
+PR_IMPLEMENT(char) PR_GetDirectorySepartor()
+{
+#if defined(DEBUG)
+ static PRBool warn = PR_TRUE;
+ if (warn) {
+ warn = _PR_Obsolete("PR_GetDirectorySepartor()",
+ "PR_GetDirectorySeparator()");
+ }
+#endif
+ return PR_GetDirectorySeparator();
} /* PR_GetDirectorySepartor */
PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen)
diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c
index e813b91d..02335004 100644
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -749,7 +749,10 @@ recycle:
if (NULL != pt_tq.tail)
{
- pt_tq.tail->status = pt_continuation_recycle;
+ if (pt_tq.tail->status != pt_continuation_abort)
+ {
+ pt_tq.tail->status = pt_continuation_recycle;
+ }
PR_NotifyCondVar(pt_tq.tail->complete);
#if defined(DEBUG)
pt_debug.recyclesNeeded += 1;
@@ -789,7 +792,7 @@ static PRIntn pt_Continue(pt_Continuation *op)
** will certainly be times within the function when it gets
** released.
*/
- pt_tq.thread = PR_GetCurrentThread(); /* I'm taking control */
+ pt_tq.thread = self; /* I'm taking control */
pt_ContinuationThreadInternal(op); /* go slash and burn */
PR_ASSERT(pt_continuation_done == op->status);
pt_tq.thread = NULL; /* I'm abdicating my rule */
@@ -809,15 +812,36 @@ static PRIntn pt_Continue(pt_Continuation *op)
* notice, this operation will be finished and the op's status
* marked as pt_continuation_done.
*/
- if ((PR_FAILURE == rv) /* the wait failed */
- && (pt_continuation_pending == op->status) /* but the op hasn't */
- && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) /* was interrupted */
+ if ((PR_FAILURE == rv) /* the wait was interrupted */
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
{
- op->status = pt_continuation_abort; /* go around the loop again */
+ if (pt_continuation_done == op->status)
+ {
+ /*
+ * The op is done and has been removed
+ * from the timed queue. We must not
+ * change op->status, otherwise this
+ * thread will go around the loop again.
+ *
+ * It's harsh to mark the op failed with
+ * interrupt error when the io is already
+ * done, but we should indicate the fact
+ * that the thread was interrupted. So
+ * we set the aborted flag to abort the
+ * thread's next blocking call. Is this
+ * the right thing to do?
+ */
+ self->state |= PT_THREAD_ABORTED;
+ }
+ else
+ {
+ /* go around the loop again */
+ op->status = pt_continuation_abort;
+ }
}
/*
* If we're to recycle, continue within this loop. This will
- * cause this thread to be come the continuation thread.
+ * cause this thread to become the continuation thread.
*/
}
diff --git a/pr/src/pthreads/ptthread.c b/pr/src/pthreads/ptthread.c
index bea53f56..b20f7c60 100644
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -199,24 +199,15 @@ static PRThread* pt_AttachThread(void)
* We cannot have PR_AttachThread call implicit initialization
* because if multiple threads call PR_AttachThread simultaneously,
* NSPR may be initialized more than once.
- * We can't call PR_SetError() either.
+ * We can't call any function that calls PR_GetCurrentThread()
+ * either (e.g., PR_SetError()) as that will result in infinite
+ * recursion.
*/
if (!_pr_initialized) return NULL;
- /*
- * If the thread is already known, it will have a non-NULL value
- * in its private data. If that's the case, simply suppress the
- * attach and note an error.
- */
- PTHREAD_GETSPECIFIC(pt_book.key, privateData);
- if (NULL != privateData)
- {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return NULL;
- }
+ /* PR_NEWZAP must not call PR_GetCurrentThread() */
thred = PR_NEWZAP(PRThread);
- if (NULL == thred) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- else
+ if (NULL != thred)
{
int rv;
@@ -717,6 +708,17 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks)
static void _pt_thread_death(void *arg)
{
PRThread *thred = (PRThread*)arg;
+
+ if (thred->state & PT_THREAD_FOREIGN)
+ {
+ PR_Lock(pt_book.ml);
+ thred->prev->next = thred->next;
+ if (NULL == thred->next)
+ pt_book.last = thred->prev;
+ else
+ thred->next->prev = thred->prev;
+ PR_Unlock(pt_book.ml);
+ }
_PR_DestroyThreadPrivate(thred);
if (NULL != thred->errorString)
PR_Free(thred->errorString);
@@ -835,6 +837,7 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_DestroyLock(pt_book.ml); pt_book.ml = NULL;
}
_pt_thread_death(me);
+ _pr_initialized = PR_FALSE;
return PR_SUCCESS;
}
return PR_FAILURE;
diff --git a/pr/tests/Makefile b/pr/tests/Makefile
index d1fc8afd..a004d214 100644
--- a/pr/tests/Makefile
+++ b/pr/tests/Makefile
@@ -37,7 +37,6 @@ OS_CFLAGS = $(OS_EXE_CFLAGS)
endif
CSRCS = \
- acceptread.c \
accept.c \
alarm.c \
atomic.c \
@@ -63,6 +62,7 @@ CSRCS = \
instrumt.c \
intrupt.c \
io_timeout.c \
+ ioconthr.c \
ipv6.c \
join.c \
joinkk.c \
diff --git a/pr/tests/accept.c b/pr/tests/accept.c
index 5318de74..69be2c01 100644
--- a/pr/tests/accept.c
+++ b/pr/tests/accept.c
@@ -48,7 +48,7 @@
#include "plgetopt.h"
#include "plerror.h"
-#define BASE_PORT 8001
+#define BASE_PORT 10000
#define CLIENT_DATA 128
@@ -62,6 +62,8 @@
#define CLIENT_TIMEOUT_ACCEPT 0x2
#define CLIENT_TIMEOUT_SEND 0x3
+#define SERVER_MAX_BIND_COUNT 100
+
#if defined(XP_MAC) || defined(XP_OS2)
#define TIMEOUTSECS 10
#else
@@ -185,6 +187,7 @@ static PRInt32 bytesRead;
static void
RunTest(PRInt32 acceptType, PRInt32 clientAction)
{
+int i;
/* First bind to the socket */
listenSock = PR_NewTCPSocket();
@@ -194,17 +197,28 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
PR_fprintf(output, "unable to create listen socket\n");
return;
}
+ memset(&listenAddr, 0 , sizeof(listenAddr));
listenAddr.inet.family = PR_AF_INET;
listenAddr.inet.port = PR_htons(BASE_PORT);
listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
- rv = PR_Bind(listenSock, &listenAddr);
- if (rv == PR_FAILURE) {
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ listenAddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
failed_already=1;
if (debug_mode)
- PR_fprintf(output, "unable to bind\n");
- return;
+ PR_fprintf(output,"accept: ERROR - PR_Bind failed\n");
+ return;
}
+
rv = PR_Listen(listenSock, 100);
if (rv == PR_FAILURE) {
failed_already=1;
@@ -308,7 +322,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
TEST_ASSERT(status == CLIENT_DATA);
break;
case CLIENT_TIMEOUT_SEND:
- TEST_ASSERT(clientSock);
+ TEST_ASSERT(clientSock == NULL);
TEST_ASSERT(status == -1);
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
break;
@@ -330,7 +344,7 @@ RunTest(PRInt32 acceptType, PRInt32 clientAction)
case CLIENT_TIMEOUT_SEND:
if (debug_mode)
PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
- TEST_ASSERT(clientSock);
+ TEST_ASSERT(clientSock == NULL);
TEST_ASSERT(status == -1);
TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
break;
diff --git a/pr/tests/bigfile.c b/pr/tests/bigfile.c
index 399da8cd..50db2fb5 100644
--- a/pr/tests/bigfile.c
+++ b/pr/tests/bigfile.c
@@ -165,7 +165,7 @@ PRIntn main(PRIntn argc, char **argv)
if (NULL == filename)
{
if (DEFAULT_FILESIZE != filesize) return Usage();
- else filename = "/usr/tmp/bigfile.dat";
+ else filename = "bigfile.dat";
}
if (PR_FAILURE == DeleteIfFound(filename)) return 1;
diff --git a/pr/tests/cltsrv.c b/pr/tests/cltsrv.c
index f3333be4..a66076de 100644
--- a/pr/tests/cltsrv.c
+++ b/pr/tests/cltsrv.c
@@ -513,9 +513,10 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
server->bytesTransferred += filebytes;
PR_Unlock(server->ml);
- rv = PR_Close(file); file = NULL;
+ rv = PR_Close(file);
if (Aborted(rv)) goto aborted;
TEST_ASSERT(PR_SUCCESS == rv);
+ file = NULL;
TEST_LOG(
cltsrv_log_file, TEST_LOG_VERBOSE,
@@ -596,9 +597,10 @@ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
if (Aborted(rv)) goto aborted;
- rv = PR_Close(file); file = NULL;
+ rv = PR_Close(file);
if (Aborted(rv)) goto aborted;
TEST_ASSERT(PR_SUCCESS == rv);
+ file = NULL;
aborted:
PR_ClearInterrupt();
diff --git a/pr/tests/foreign.c b/pr/tests/foreign.c
index dcf88250..b26a5fea 100644
--- a/pr/tests/foreign.c
+++ b/pr/tests/foreign.c
@@ -212,6 +212,9 @@ static void PR_CALLBACK lazyEntry(void *arg)
static void OneShot(void *arg)
{
PRUintn pdkey;
+ PRLock *lock;
+ PRFileDesc *fd;
+ PRDir *dir;
PRFileDesc *pair[2];
PRIntn test = (PRIntn)arg;
@@ -220,9 +223,10 @@ static void OneShot(void *arg)
switch (test)
{
case 0:
- (void)PR_NewLock();
+ lock = PR_NewLock();
DPRINTF((output,"Thread[0x%x] called PR_NewLock\n",
PR_GetCurrentThread()));
+ PR_DestroyLock(lock);
break;
case 1:
@@ -239,27 +243,31 @@ static void OneShot(void *arg)
break;
case 3:
- (void)PR_Open("/usr/tmp/", PR_RDONLY, 0);
+ fd = PR_Open("foreign.tmp", PR_CREATE_FILE | PR_RDWR, 0666);
DPRINTF((output,"Thread[0x%x] called PR_Open\n",
PR_GetCurrentThread()));
+ PR_Close(fd);
break;
case 4:
- (void)PR_NewUDPSocket();
+ fd = PR_NewUDPSocket();
DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n",
PR_GetCurrentThread()));
+ PR_Close(fd);
break;
case 5:
- (void)PR_NewTCPSocket();
+ fd = PR_NewTCPSocket();
DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n",
PR_GetCurrentThread()));
+ PR_Close(fd);
break;
case 6:
- (void)PR_OpenDir("/usr/tmp/");
+ dir = PR_OpenDir("/usr/tmp/");
DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n",
PR_GetCurrentThread()));
+ PR_CloseDir(dir);
break;
case 7:
@@ -278,6 +286,8 @@ static void OneShot(void *arg)
(void)PR_NewTCPSocketPair(pair);
DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n",
PR_GetCurrentThread()));
+ PR_Close(pair[0]);
+ PR_Close(pair[1]);
break;
case 10:
diff --git a/pr/tests/fsync.c b/pr/tests/fsync.c
index 38fb5e69..5a51a330 100644
--- a/pr/tests/fsync.c
+++ b/pr/tests/fsync.c
@@ -42,7 +42,7 @@ PRIntn main(PRIntn argc, char **argv)
PLOptStatus os;
PRUint8 *buffer;
PRFileDesc *file = NULL;
- const char *filename = "/usr/tmp/sync.dat";
+ const char *filename = "sync.dat";
PRUint32 index, loops, iterations = 10, filesize = 10;
PRIntn flags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
PLOptState *opt = PL_CreateOptState(argc, argv, "hSK:c:");
diff --git a/pr/tests/instrumt.c b/pr/tests/instrumt.c
index 5a51a9f3..ee2b33b5 100644
--- a/pr/tests/instrumt.c
+++ b/pr/tests/instrumt.c
@@ -334,7 +334,6 @@ static void TraceTest( void )
size = SMALL_TRACE_BUFSIZE;
PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
- PR_ASSERT( i == size );
PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
diff --git a/pr/tests/ioconthr.c b/pr/tests/ioconthr.c
new file mode 100644
index 00000000..60d6949b
--- /dev/null
+++ b/pr/tests/ioconthr.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.0 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All Rights
+ * Reserved.
+ */
+
+/*
+ * This is a test for the io continuation thread machinery
+ * in pthreads.
+ */
+
+#include "nspr.h"
+#include <stdio.h>
+
+int num_threads = 10; /* must be an even number */
+PRThreadScope thread_scope = PR_GLOBAL_THREAD;
+
+void ThreadFunc(void *arg)
+{
+ PRFileDesc *fd = (PRFileDesc *) arg;
+ char buf[1024];
+ PRInt32 nbytes;
+ PRErrorCode err;
+
+ nbytes = PR_Recv(fd, buf, sizeof(buf), 0, PR_SecondsToInterval(20));
+ if (nbytes == -1) {
+ err = PR_GetError();
+ if (err != PR_PENDING_INTERRUPT_ERROR) {
+ fprintf(stderr, "PR_Recv failed: (%d, %d)\n",
+ err, PR_GetOSError());
+ PR_ProcessExit(1);
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ PR_ProcessExit(1);
+ }
+ } else {
+ fprintf(stderr, "PR_Recv received %d bytes!?\n", nbytes);
+ PR_ProcessExit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc **fds;
+ PRThread **threads;
+ PRIntervalTime start, elapsed;
+ int index;
+
+ fds = (PRFileDesc **) PR_MALLOC(num_threads * sizeof(PRFileDesc *));
+ PR_ASSERT(fds != NULL);
+ threads = (PRThread **) PR_MALLOC(num_threads * sizeof(PRThread *));
+ PR_ASSERT(threads != NULL);
+
+ for (index = 0; index < (num_threads / 2); index++) {
+ if (PR_NewTCPSocketPair(&fds[2 * index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ PR_ProcessExit(1);
+ }
+
+ threads[2 * index] = PR_CreateThread(
+ PR_USER_THREAD, ThreadFunc, fds[2 * index],
+ PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == threads[2 * index]) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ PR_ProcessExit(1);
+ }
+ threads[2 * index + 1] = PR_CreateThread(
+ PR_USER_THREAD, ThreadFunc, fds[2 * index + 1],
+ PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == threads[2 * index + 1]) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+
+ /* Let the threads block in PR_Recv */
+ PR_Sleep(PR_SecondsToInterval(2));
+
+ printf("Interrupting the threads\n");
+ fflush(stdout);
+ start = PR_IntervalNow();
+ for (index = 0; index < num_threads; index++) {
+ if (PR_Interrupt(threads[index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Interrupt failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+ for (index = 0; index < num_threads; index++) {
+ if (PR_JoinThread(threads[index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
+ printf("Threads terminated in %d milliseconds\n",
+ PR_IntervalToMilliseconds(elapsed));
+ fflush(stdout);
+
+ /* We are being very generous and allow 10 seconds. */
+ if (elapsed >= PR_SecondsToInterval(10)) {
+ fprintf(stderr, "Interrupting threads took longer than 10 seconds!!\n");
+ PR_ProcessExit(1);
+ }
+
+ PR_DELETE(threads);
+ PR_DELETE(fds);
+ printf("PASS\n");
+ PR_Cleanup();
+ return 0;
+}
diff --git a/pr/tests/layer.c b/pr/tests/layer.c
index 0c93e4b6..4e61523a 100644
--- a/pr/tests/layer.c
+++ b/pr/tests/layer.c
@@ -84,6 +84,9 @@ static void PR_CALLBACK Client(void *arg)
PRIntn bytes_read, bytes_sent;
PRFileDesc *stack = (PRFileDesc*)arg;
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
PR_ASSERT(PR_SUCCESS == rv);
while (minor_iterations-- > 0)
@@ -157,7 +160,7 @@ static PRInt32 PR_CALLBACK MyRecv(
{
char *b = (char*)buf;
PRFileDesc *lo = fd->lower;
- PRInt32 rv, readin = 0, request;
+ PRInt32 rv, readin = 0, request = 0;
rv = lo->methods->recv(lo, &request, sizeof(request), flags, timeout);
if (verbosity > chatty) PR_fprintf(
logFile, "MyRecv sending permission for %d bytes\n", request);
diff --git a/pr/tests/multiwait.c b/pr/tests/multiwait.c
index 4358b350..ad961b17 100644
--- a/pr/tests/multiwait.c
+++ b/pr/tests/multiwait.c
@@ -156,6 +156,9 @@ static void PR_CALLBACK ClientThread(void* arg)
if (verbosity > chatty)
PR_fprintf(debug, "%s: Server socket @0x%x\n", shared->title, server);
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
rv = PR_InitializeNetAddr(PR_IpAddrLoopback, default_port, &server_address);
MW_ASSERT(PR_SUCCESS == rv);
@@ -259,8 +262,6 @@ static void ManyOpOneThread(Shared *shared)
PRRecvWait *desc_in;
PRRecvWait *desc_out;
- desc_in = (PRRecvWait*)PR_CALLOC(sizeof(PRRecvWait*) * wait_objects);
-
if (verbosity > quiet)
PR_fprintf(debug, "%s: adding %d descs\n", shared->title, wait_objects);
@@ -604,6 +605,7 @@ static void RealOneGroupIO(Shared *shared)
rv = PR_JoinThread(client_thread[index]);
MW_ASSERT(PR_SUCCESS == rv);
}
+ PR_DELETE(client_thread);
if (verbosity > quiet)
PR_fprintf(debug, "%s: interrupting/joining enumeration_thread\n", shared->title);
diff --git a/pr/tests/nbconn.c b/pr/tests/nbconn.c
index b206f991..885ba3b6 100644
--- a/pr/tests/nbconn.c
+++ b/pr/tests/nbconn.c
@@ -50,6 +50,7 @@ static char *hosts[4] = {"cynic", "warp", "gandalf", "neon"};
#define SERVER_MAX_BIND_COUNT 100
#define DATA_BUF_SIZE 256
#define TCP_SERVER_PORT 10000
+#define TCP_UNUSED_PORT 211
typedef struct Server_Param {
PRFileDesc *sp_fd; /* server port */
@@ -70,7 +71,7 @@ int main(int argc, char **argv)
PRPollDesc pd;
PRStatus rv;
PRSocketOptionData optData;
- const char *hostname;
+ const char *hostname = NULL;
PRIntn default_case, n, bytes_read, bytes_sent;
PRInt32 failed_already = 0;
#ifdef XP_MAC
@@ -279,7 +280,7 @@ connection_success_test()
Server_Param sp;
char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
PRIntn default_case, n, bytes_read, bytes_sent;
- PRIntn failed_already;
+ PRIntn failed_already = 0;
/*
* Create a tcp socket
@@ -341,11 +342,6 @@ connection_success_test()
failed_already=1;
goto def_exit;
}
- } else {
- PR_ASSERT(rv == PR_SUCCESS);
- fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
- failed_already=1;
- goto def_exit;
}
/*
* Now create a thread to accept a connection
@@ -373,12 +369,6 @@ connection_success_test()
failed_already=1;
goto def_exit;
}
- if (pd.out_flags != PR_POLL_WRITE) {
- fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
- pd.out_flags);
- failed_already=1;
- goto def_exit;
- }
if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
PRInt32 rv;
@@ -520,6 +510,12 @@ connection_failure_test()
failed_already=1;
goto def_exit;
}
+#ifdef AIX
+ /*
+ * On AIX, set to unused/reserved port
+ */
+ netaddr.inet.port = PR_htons(TCP_UNUSED_PORT);
+#endif
if ((conn_fd = PR_NewTCPSocket()) == NULL) {
fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
failed_already=1;
@@ -551,12 +547,6 @@ connection_failure_test()
failed_already=1;
goto def_exit;
}
- if (pd.out_flags != PR_POLL_WRITE) {
- fprintf(stderr,"Error - PR_Poll returned invalid outflags: 0x%x\n",
- pd.out_flags);
- failed_already=1;
- goto def_exit;
- }
if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
PRInt32 rv;
fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n");
diff --git a/pr/tests/nblayer.c b/pr/tests/nblayer.c
index b14073a1..5b304d2c 100644
--- a/pr/tests/nblayer.c
+++ b/pr/tests/nblayer.c
@@ -100,6 +100,9 @@ static void PR_CALLBACK Client(void *arg)
PRIntn bytes_read, bytes_sent;
PRFileDesc *stack = (PRFileDesc*)arg;
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError()))
{
@@ -299,9 +302,8 @@ static void PR_CALLBACK Server(void *arg)
} while (0 != bytes_read);
if (verbosity > quiet)
- PR_fprintf(logFile, "Server shutting down and closing stack\n");
+ PR_fprintf(logFile, "Server shutting down stack\n");
rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
- rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
} /* Server */
@@ -630,4 +632,4 @@ PRIntn main(PRIntn argc, char **argv)
return 0;
} /* main */
-/* layer.c */
+/* nblayer.c */
diff --git a/pr/tests/nonblock.c b/pr/tests/nonblock.c
index c15807b7..9c44135e 100644
--- a/pr/tests/nonblock.c
+++ b/pr/tests/nonblock.c
@@ -74,6 +74,9 @@ clientThreadFunc(void *arg)
PRStatus retVal;
PRInt32 nBytes;
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buf, 0, sizeof(buf));
+
addr.inet.family = PR_AF_INET;
addr.inet.port = PR_htons((PRUint16)port);
addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
diff --git a/pr/tests/provider.c b/pr/tests/provider.c
index 49428b3a..eab7f8d9 100644
--- a/pr/tests/provider.c
+++ b/pr/tests/provider.c
@@ -81,7 +81,7 @@
#define SEND_FLAGS 0
#define BUFFER_SIZE 1024
#define DEFAULT_BACKLOG 5
-#define DEFAULT_PORT 12848
+#define DEFAULT_PORT 13000
#define DEFAULT_CLIENTS 1
#define ALLOWED_IN_ACCEPT 1
#define DEFAULT_CLIPPING 1000
@@ -706,7 +706,7 @@ static PRStatus NewThread(
PRThread *thread = PR_CreateThread(
PR_USER_THREAD, start, arg,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD, 0);
+ PR_JOINABLE_THREAD, 0);
rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
}
break;
@@ -1070,6 +1070,7 @@ PRIntn main(PRIntn argc, char** argv)
CSClient_t *client;
PRStatus rv, joinStatus;
CSServer_t *server = NULL;
+ char *thread_type;
PRUintn backlog = DEFAULT_BACKLOG;
PRUintn clients = DEFAULT_CLIENTS;
@@ -1095,6 +1096,16 @@ PRIntn main(PRIntn argc, char** argv)
PLOptStatus os;
PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:T:vdhp");
+#if defined(WIN32)
+ thread_provider = thread_win32;
+#elif defined(_PR_PTHREADS)
+ thread_provider = thread_pthread;
+#elif defined(IRIX)
+ thread_provider = thread_sproc;
+#else
+ thread_provider = thread_nspr;
+#endif
+
debug_out = PR_GetSpecialFD(PR_StandardError);
while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
@@ -1347,7 +1358,18 @@ PRIntn main(PRIntn argc, char** argv)
cltsrv_log_file, TEST_LOG_ALWAYS,
("main(0x%p): test complete\n", PR_CurrentThread()));
- PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+ if (thread_provider == thread_win32)
+ thread_type = "\nWin32 Thread Statistics\n";
+ else if (thread_provider == thread_pthread)
+ thread_type = "\npthread Statistics\n";
+ else if (thread_provider == thread_sproc)
+ thread_type = "\nsproc Statistics\n";
+ else {
+ PR_ASSERT(thread_provider == thread_nspr);
+ thread_type = "\nPRThread Statistics\nn";
+ }
+
+ PT_FPrintStats(debug_out, thread_type);
TimeOfDayMessage("Test exiting at", PR_CurrentThread());
return 0;
diff --git a/pr/tests/socket.c b/pr/tests/socket.c
index 770d5f71..47c134d2 100644
--- a/pr/tests/socket.c
+++ b/pr/tests/socket.c
@@ -58,7 +58,7 @@ extern void SetupMacPrintfLog(char *logFile);
#define DPRINTF(arg) if (_debug_on) printf arg
#ifdef XP_PC
-char *TEST_DIR = "C:\\tmp\\prdir";
+char *TEST_DIR = "prdir";
char *SMALL_FILE_NAME = "prsmallf";
char *LARGE_FILE_NAME = "prlargef";
#else
diff --git a/pr/tests/sockopt.c b/pr/tests/sockopt.c
index 37854044..e3eb0eab 100644
--- a/pr/tests/sockopt.c
+++ b/pr/tests/sockopt.c
@@ -129,8 +129,10 @@ PRIntn main(PRIntn argc, char *argv)
value = &boolean;
size = &booleansize;
break;
+#ifndef WIN32
case PR_SockOpt_MaxSegment: /* maximum segment size */
socket = tcp;
+#endif
case PR_SockOpt_RecvBufferSize: /* send buffer size */
case PR_SockOpt_SendBufferSize: /* receive buffer size */
value = &segment;
@@ -150,9 +152,20 @@ PRIntn main(PRIntn argc, char *argv)
default:
continue;
}
-
- rv = PR_SetSockOpt(socket, option, value, *size);
- if (PR_FAILURE == rv) Failed("PR_SetSockOpt()", tag[option]);
+ /*
+ * TCP_MAXSEG can only be read, not set
+ */
+ if (option != PR_SockOpt_MaxSegment) {
+#ifdef WIN32
+ if ((option != PR_SockOpt_McastTimeToLive) &&
+ (option != PR_SockOpt_McastLoopback))
+#endif
+ {
+ rv = PR_SetSockOpt(socket, option, value, *size);
+ if (PR_FAILURE == rv) Failed("PR_SetSockOpt()",
+ tag[option]);
+ }
+ }
rv = PR_GetSockOpt(socket, option, &value, size);
if (PR_FAILURE == rv) Failed("PR_GetSockOpt()", tag[option]);
@@ -200,14 +213,28 @@ PRIntn main(PRIntn argc, char *argv)
case PR_SockOpt_NoDelay:
data.value.no_delay = PR_TRUE;
break;
+#ifndef WIN32
case PR_SockOpt_MaxSegment:
data.value.max_segment = segment;
break;
+#endif
default: continue;
}
- rv = PR_SetSocketOption(fd, &data);
- if (PR_FAILURE == rv) Failed("PR_SetSocketOption()", tag[option]);
+ /*
+ * TCP_MAXSEG can only be read, not set
+ */
+ if (option != PR_SockOpt_MaxSegment) {
+#ifdef WIN32
+ if ((option != PR_SockOpt_McastTimeToLive) &&
+ (option != PR_SockOpt_McastLoopback))
+#endif
+ {
+ rv = PR_SetSocketOption(fd, &data);
+ if (PR_FAILURE == rv)
+ Failed("PR_SetSocketOption()", tag[option]);
+ }
+ }
rv = PR_GetSocketOption(fd, &data);
if (PR_FAILURE == rv) Failed("PR_GetSocketOption()", tag[option]);
diff --git a/pr/tests/tmocon.c b/pr/tests/tmocon.c
index 018c98b6..a850f720 100644
--- a/pr/tests/tmocon.c
+++ b/pr/tests/tmocon.c
@@ -425,7 +425,7 @@ int Tmocon(int argc, char **argv)
PR_fprintf(
PR_GetSpecialFD(PR_StandardError), "%s\n",
((shared->failed) ? "FAILED" : "PASSED"));
- return (shared->failed) ? 0 : 1;
+ return (shared->failed) ? 1 : 0;
}
int main(int argc, char **argv)