More mozilla/nsprpub updates, including:

- Patch for MkLinux and glibc 2.1.  Removed the MKLINUX macro.
  This patch is contributed by Tom Rini <trini@kernel.crashing.org>.
- Patch to make the emulated threads work on ARM/Linux.  Contributed
  by raff@netwinder.org.
This commit is contained in:
wtc%netscape.com 1998-10-05 18:58:25 +00:00
parent c5b5342df7
commit 6462b9a6d7
44 changed files with 888 additions and 179 deletions

View File

@ -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)

View File

@ -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

View File

@ -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",

265
nsprpub/lib/tests/arena.c Normal file
View File

@ -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 */

View File

@ -59,10 +59,6 @@
#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
@ -89,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)
@ -194,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"

View File

@ -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);

View File

@ -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

View File

@ -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()))

View File

@ -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);

View File

@ -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);

View File

@ -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];
newHash->length = length;
for (desc = &oldHash->recv_wait; newHash->count < oldHash->count; ++desc)
{
if (NULL != *desc)
/* 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 (_prmw_success != MW_AddHashInternal(*desc, newHash))
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return _prmw_error;
}
newHash->length = length;
retry = PR_FALSE;
for (desc = &oldHash->recv_wait;
newHash->count < oldHash->count; ++desc)
{
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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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 */
@ -990,7 +991,6 @@ PRThread *me = _PR_MD_CURRENT_THREAD();
}
}
#if 0 /* wtc: comment out */
/*
* Override the exit() function in libc to cause the process to exit
* when the primodial/main nspr thread calls exit. Calls to exit by any
@ -1003,10 +1003,20 @@ void exit(int status)
{
PRThread *me, *thr;
PRCList *qp;
void __exit(int status); /* XXX some IRIX machines don't have this symbol */
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();
@ -1081,7 +1091,6 @@ void __exit(int status); /* XXX some IRIX machines don't have this symbol */
(*libc_exit)(status);
}
}
#endif /* 0 */
void
@ -1431,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

View File

@ -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

View File

@ -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

View File

@ -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);
if (mutex_unlock(&_solaris_atomic) != 0)\
PR_ASSERT(0);
rv = ((*ptr) += val);
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 */

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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.
*/
}

View File

@ -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;

View File

@ -62,6 +62,7 @@ CSRCS = \
instrumt.c \
intrupt.c \
io_timeout.c \
ioconthr.c \
ipv6.c \
join.c \
joinkk.c \

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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:

View File

@ -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:");

View File

@ -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" );

123
nsprpub/pr/tests/ioconthr.c Normal file
View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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]);

View File

@ -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)