diff options
author | wtc%netscape.com <devnull@localhost> | 1998-10-03 00:21:02 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 1998-10-03 00:21:02 +0000 |
commit | 14daeed9bb74395a844665bad68341bbfb62deeb (patch) | |
tree | d74a0973f82cacec0bdc55a6f3ba961d28f3d781 | |
parent | e75df7111184579018ab3ef4990a48c602a1f43f (diff) | |
download | nspr-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.
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 Binary files differindex 57934998..f15a68a2 100644 --- a/macbuild/NSPR20PPC.mcp +++ b/macbuild/NSPR20PPC.mcp 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) |