summaryrefslogtreecommitdiff
path: root/pr/src
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src')
-rw-r--r--pr/src/io/prfdcach.c4
-rw-r--r--pr/src/io/prfile.c18
-rw-r--r--pr/src/io/prio.c2
-rw-r--r--pr/src/io/priometh.c10
-rw-r--r--pr/src/io/prlayer.c4
-rw-r--r--pr/src/io/prlog.c9
-rw-r--r--pr/src/io/prmapopt.c6
-rw-r--r--pr/src/io/prmwait.c39
-rw-r--r--pr/src/io/prsocket.c106
-rw-r--r--pr/src/linking/prlink.c43
-rw-r--r--pr/src/malloc/prmem.c74
-rw-r--r--pr/src/md/beos/bfile.c419
-rw-r--r--pr/src/md/beos/bmisc.c7
-rw-r--r--pr/src/md/beos/bnet.c773
-rw-r--r--pr/src/md/beos/bproc.c184
-rw-r--r--pr/src/md/mac/macdll.c106
-rw-r--r--pr/src/md/mac/macio.c15
-rw-r--r--pr/src/md/mac/macsocket.h1
-rw-r--r--pr/src/md/mac/macsockotpt.c341
-rw-r--r--pr/src/md/mac/macthr.c170
-rw-r--r--pr/src/md/mac/mdcriticalregion.c1
-rw-r--r--pr/src/md/mac/mdmac.c5
-rw-r--r--pr/src/md/os2/os2_errors.c125
-rw-r--r--pr/src/md/os2/os2cv.c108
-rw-r--r--pr/src/md/os2/os2inrval.c43
-rw-r--r--pr/src/md/os2/os2io.c6
-rw-r--r--pr/src/md/os2/os2misc.c344
-rw-r--r--pr/src/md/os2/os2poll.c266
-rw-r--r--pr/src/md/os2/os2sock.c1020
-rw-r--r--pr/src/md/os2/os2thred.c10
-rw-r--r--pr/src/md/os2/os2vacpp.asm199
-rw-r--r--pr/src/md/unix/darwin.c27
-rw-r--r--pr/src/md/unix/irix.c8
-rw-r--r--pr/src/md/unix/unix.c50
-rw-r--r--pr/src/md/unix/unix_errors.c7
-rw-r--r--pr/src/md/unix/uxproces.c2
-rw-r--r--pr/src/md/unix/uxrng.c19
-rw-r--r--pr/src/md/unix/uxshm.c5
-rw-r--r--pr/src/md/windows/Makefile.in8
-rw-r--r--pr/src/md/windows/ntthread.c7
-rw-r--r--pr/src/md/windows/w95sock.c26
-rw-r--r--pr/src/md/windows/w95thred.c8
-rw-r--r--pr/src/misc/pralarm.c2
-rw-r--r--pr/src/misc/prdtoa.c10
-rw-r--r--pr/src/misc/prenv.c2
-rw-r--r--pr/src/misc/prerr.c2
-rw-r--r--pr/src/misc/prerror.c4
-rw-r--r--pr/src/misc/prinit.c26
-rw-r--r--pr/src/misc/prinrval.c4
-rw-r--r--pr/src/misc/prnetdb.c222
-rw-r--r--pr/src/misc/prsystem.c14
-rw-r--r--pr/src/misc/prtime.c46
-rw-r--r--pr/src/misc/prtpool.c4
-rw-r--r--pr/src/pthreads/Makefile.in5
-rw-r--r--pr/src/pthreads/ptio.c293
-rw-r--r--pr/src/pthreads/ptsynch.c9
-rw-r--r--pr/src/pthreads/ptthread.c31
-rw-r--r--pr/src/threads/combined/prucpu.c173
-rw-r--r--pr/src/threads/combined/pruthr.c1
-rw-r--r--pr/src/threads/prtpd.c2
60 files changed, 3503 insertions, 1972 deletions
diff --git a/pr/src/io/prfdcach.c b/pr/src/io/prfdcach.c
index 8803a419..82cbf058 100644
--- a/pr/src/io/prfdcach.c
+++ b/pr/src/io/prfdcach.c
@@ -73,7 +73,7 @@ static PRFileDesc **stack2fd = &(((PRFileDesc*)NULL)->higher);
** Get a FileDescriptor from the cache if one exists. If not allocate
** a new one from the heap.
*/
-PRFileDesc *_PR_Getfd()
+PRFileDesc *_PR_Getfd(void)
{
PRFileDesc *fd;
/*
@@ -248,7 +248,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high)
return PR_SUCCESS;
} /* PR_SetFDCacheSize */
-void _PR_InitFdCache()
+void _PR_InitFdCache(void)
{
/*
** The fd caching is enabled by default for DEBUG builds,
diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c
index e19705c7..adb2ea55 100644
--- a/pr/src/io/prfile.c
+++ b/pr/src/io/prfile.c
@@ -203,7 +203,7 @@ static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd)
return PR_SUCCESS;
}
-static PRStatus PR_CALLBACK FileInfo(PRFileDesc *fd, PRFileInfo *info)
+static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info)
{
PRInt32 rv;
@@ -214,7 +214,7 @@ static PRStatus PR_CALLBACK FileInfo(PRFileDesc *fd, PRFileInfo *info)
return PR_SUCCESS;
}
-static PRStatus PR_CALLBACK FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
+static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info)
{
#ifdef XP_MAC
#pragma unused( fd, info )
@@ -276,8 +276,8 @@ static PRIOMethods _pr_fileMethods = {
FileSync,
FileSeek,
FileSeek64,
- FileInfo,
- FileInfo64,
+ FileGetInfo,
+ FileGetInfo64,
(PRWritevFN)_PR_InvalidInt,
(PRConnectFN)_PR_InvalidStatus,
(PRAcceptFN)_PR_InvalidDesc,
@@ -735,7 +735,7 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
(*readPipe)->secret->inheritable = _PR_TRI_TRUE;
(*writePipe)->secret->inheritable = _PR_TRI_TRUE;
return PR_SUCCESS;
-#elif defined(XP_UNIX) || defined(XP_OS2)
+#elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
#ifdef XP_OS2
HFILE pipefd[2];
#else
@@ -765,9 +765,13 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
close(pipefd[1]);
return PR_FAILURE;
}
- _MD_MakeNonblock(*readPipe);
+#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
+ _PR_MD_MAKE_NONBLOCK(*readPipe);
+#endif
_PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE);
- _MD_MakeNonblock(*writePipe);
+#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
+ _PR_MD_MAKE_NONBLOCK(*writePipe);
+#endif
_PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE);
return PR_SUCCESS;
#else
diff --git a/pr/src/io/prio.c b/pr/src/io/prio.c
index 250d9b6f..36c8df8a 100644
--- a/pr/src/io/prio.c
+++ b/pr/src/io/prio.c
@@ -164,7 +164,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
PRFileDesc *fd,
PRBool inheritable)
{
-#if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2)
+#if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2) || defined(XP_BEOS)
/*
* Only a non-layered, NSPR file descriptor can be inherited
* by a child process.
diff --git a/pr/src/io/priometh.c b/pr/src/io/priometh.c
index a2b8e9c8..b9279fad 100644
--- a/pr/src/io/priometh.c
+++ b/pr/src/io/priometh.c
@@ -76,21 +76,21 @@ PRIOMethods _pr_faulty_methods = {
(PRReservedFN)_PR_InvalidInt
};
-PRIntn _PR_InvalidInt()
+PRIntn _PR_InvalidInt(void)
{
PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return -1;
} /* _PR_InvalidInt */
-PRInt16 _PR_InvalidInt16()
+PRInt16 _PR_InvalidInt16(void)
{
PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
return -1;
} /* _PR_InvalidInt */
-PRInt64 _PR_InvalidInt64()
+PRInt64 _PR_InvalidInt64(void)
{
PRInt64 rv;
LL_I2L(rv, -1);
@@ -103,7 +103,7 @@ PRInt64 _PR_InvalidInt64()
* An invalid method that returns PRStatus
*/
-PRStatus _PR_InvalidStatus()
+PRStatus _PR_InvalidStatus(void)
{
PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
@@ -114,7 +114,7 @@ PRStatus _PR_InvalidStatus()
* An invalid method that returns a pointer
*/
-PRFileDesc *_PR_InvalidDesc()
+PRFileDesc *_PR_InvalidDesc(void)
{
PR_ASSERT(!"I/O method is invalid");
PR_SetError(PR_INVALID_METHOD_ERROR, 0);
diff --git a/pr/src/io/prlayer.c b/pr/src/io/prlayer.c
index d74fa8be..d377f546 100644
--- a/pr/src/io/prlayer.c
+++ b/pr/src/io/prlayer.c
@@ -459,7 +459,7 @@ static PRIOMethods pl_methods = {
(PRReservedFN)_PR_InvalidInt
};
-PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void)
{
return &pl_methods;
} /* PR_GetDefaultIOMethods */
@@ -736,7 +736,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity i
return NULL;
} /* PR_GetIdentitiesLayer */
-void _PR_InitLayerCache()
+void _PR_InitLayerCache(void)
{
memset(&identity_cache, 0, sizeof(identity_cache));
identity_cache.ml = PR_NewLock();
diff --git a/pr/src/io/prlog.c b/pr/src/io/prlog.c
index 16f68823..334fddcc 100644
--- a/pr/src/io/prlog.c
+++ b/pr/src/io/prlog.c
@@ -277,11 +277,16 @@ void _PR_LogCleanup(void)
while (lm != NULL) {
PRLogModuleInfo *next = lm->next;
- PR_Free((/*const*/ char *)lm->name);
+ free((/*const*/ char *)lm->name);
PR_Free(lm);
lm = next;
}
logModules = NULL;
+
+ if (_pr_logLock) {
+ PR_DestroyLock(_pr_logLock);
+ _pr_logLock = NULL;
+ }
}
static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
@@ -361,7 +366,7 @@ PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
#else
PRFileDesc *newLogFile;
- newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE, 0666);
+ newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0666);
if (newLogFile) {
if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
PR_Close(logFile);
diff --git a/pr/src/io/prmapopt.c b/pr/src/io/prmapopt.c
index f017c36a..5828bf9e 100644
--- a/pr/src/io/prmapopt.c
+++ b/pr/src/io/prmapopt.c
@@ -57,7 +57,7 @@
#include <netinet/in_systm.h> /* n_short, n_long, n_time */
#endif
-#if defined(XP_UNIX) || defined(OS2)
+#if defined(XP_UNIX) || defined(OS2) || (defined(XP_BEOS) && defined(BONE_VERSION))
#include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */
#endif
@@ -86,7 +86,7 @@ PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionDat
{
case PR_SockOpt_Linger:
{
-#if !defined(XP_BEOS)
+#if !defined(XP_BEOS) || defined(BONE_VERSION)
struct linger linger;
length = sizeof(linger);
rv = _PR_MD_GETSOCKOPT(
@@ -244,7 +244,7 @@ PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOpt
{
case PR_SockOpt_Linger:
{
-#if !defined(XP_BEOS)
+#if !defined(XP_BEOS) || defined(BONE_VERSION)
struct linger linger;
linger.l_onoff = data->value.linger.polarity;
linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);
diff --git a/pr/src/io/prmwait.c b/pr/src/io/prmwait.c
index a48fbc19..65ea1cd6 100644
--- a/pr/src/io/prmwait.c
+++ b/pr/src/io/prmwait.c
@@ -58,19 +58,8 @@ typedef struct TimerEvent {
struct {
PRLock *ml;
PRCondVar *new_timer;
- PRCondVar *cancel_timer; /* The cancel_timer condition variable is
- * used to cancel a timer (i.e., remove a
- * timer event from the timer queue). At
- * startup I'm borrowing this condition
- * variable for a different purpose (to
- * tell the primordial thread that the
- * timer manager thread has started) so
- * that I don't need to create a new
- * condition variable just for this one
- * time use.
- */
+ PRCondVar *cancel_timer;
PRThread *manager_thread;
- PRBool manager_started;
PRCList timer_queue;
} tm_vars;
@@ -88,11 +77,6 @@ static void TimerManager(void *arg)
TimerEvent *timer;
PR_Lock(tm_vars.ml);
- /* tell the primordial thread that we have started */
- tm_vars.manager_started = PR_TRUE;
- if (!_native_threads_only) {
- PR_NotifyCondVar(tm_vars.cancel_timer);
- }
while (1)
{
if (PR_CLIST_IS_EMPTY(&tm_vars.timer_queue))
@@ -216,16 +200,6 @@ static PRStatus TimerInit(void)
{
goto failed;
}
- /*
- * Need to wait until the timer manager thread starts
- * if the timer manager thread is a local thread.
- */
- if (!_native_threads_only) {
- PR_Lock(tm_vars.ml);
- while (!tm_vars.manager_started)
- PR_WaitCondVar(tm_vars.cancel_timer, PR_INTERVAL_NO_TIMEOUT);
- PR_Unlock(tm_vars.ml);
- }
return PR_SUCCESS;
failed:
@@ -269,6 +243,17 @@ void _PR_InitMW(void)
max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL);
} /* _PR_InitMW */
+void _PR_CleanupMW(void)
+{
+ PR_DestroyLock(mw_lock);
+ mw_lock = NULL;
+ if (mw_state->group) {
+ PR_DestroyWaitGroup(mw_state->group);
+ /* mw_state->group is set to NULL as a side effect. */
+ }
+ PR_DELETE(mw_state);
+} /* _PR_CleanupMW */
+
static PRWaitGroup *MW_Init2(void)
{
PRWaitGroup *group = mw_state->group; /* it's the null group */
diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c
index 2483f963..652632fc 100644
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -338,27 +338,16 @@ static PRStatus PR_CALLBACK SocketConnectContinue(
#elif defined(XP_OS2)
- if (out_flags & PR_POLL_EXCEPT) {
- int len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len)
- < 0) {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
- }
- if (err != 0) {
- _PR_MD_MAP_CONNECT_ERROR(err);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- }
+ err = _MD_os2_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
return PR_FAILURE;
}
-
- PR_ASSERT(out_flags & PR_POLL_WRITE);
return PR_SUCCESS;
#elif defined(XP_MAC)
- err = _MD_mac_get_nonblocking_connect_error(osfd);
+ err = _MD_mac_get_nonblocking_connect_error(fd);
if (err == -1)
return PR_FAILURE;
else
@@ -366,13 +355,23 @@ static PRStatus PR_CALLBACK SocketConnectContinue(
#elif defined(XP_BEOS)
+#ifdef BONE_VERSION /* bug 122364 */
+ /* temporary workaround until getsockopt(SO_ERROR) works in BONE */
+ if (out_flags & PR_POLL_EXCEPT) {
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ PR_ASSERT(out_flags & PR_POLL_WRITE);
+ return PR_SUCCESS;
+#else
err = _MD_beos_get_nonblocking_connect_error(fd);
if( err != 0 ) {
- _PR_MD_MAP_CONNECT_ERROR(err);
- return PR_FAILURE;
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return PR_FAILURE;
}
else
- return PR_SUCCESS;
+ return PR_SUCCESS;
+#endif /* BONE_VERSION */
#else
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
@@ -1396,7 +1395,7 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
*/
SOCKET listenSock;
SOCKET osfd[2];
- struct sockaddr_in selfAddr;
+ struct sockaddr_in selfAddr, peerAddr;
int addrLen;
if (!_pr_initialized) _PR_ImplicitInitialization();
@@ -1440,10 +1439,24 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
addrLen) == SOCKET_ERROR) {
goto failed;
}
- osfd[1] = accept(listenSock, NULL, NULL);
+ /*
+ * A malicious local process may connect to the listening
+ * socket, so we need to verify that the accepted connection
+ * is made from our own socket osfd[0].
+ */
+ if (getsockname(osfd[0], (struct sockaddr *) &selfAddr,
+ &addrLen) == SOCKET_ERROR) {
+ goto failed;
+ }
+ osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen);
if (osfd[1] == INVALID_SOCKET) {
goto failed;
}
+ if (peerAddr.sin_port != selfAddr.sin_port) {
+ /* the connection we accepted is not from osfd[0] */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ goto failed;
+ }
closesocket(listenSock);
f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
@@ -1480,7 +1493,7 @@ failed:
* default implementation
*/
PRFileDesc *listenSock;
- PRNetAddr selfAddr;
+ PRNetAddr selfAddr, peerAddr;
PRUint16 port;
f[0] = f[1] = NULL;
@@ -1503,6 +1516,17 @@ failed:
if (f[0] == NULL) {
goto failed;
}
+#ifdef _PR_CONNECT_DOES_NOT_BIND
+ /*
+ * If connect does not implicitly bind the socket (e.g., on
+ * BeOS), we have to bind the socket so that we can get its
+ * port with getsockname later.
+ */
+ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr);
+ if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+#endif
PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);
/*
@@ -1518,10 +1542,23 @@ failed:
== PR_FAILURE) {
goto failed;
}
- f[1] = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ /*
+ * A malicious local process may connect to the listening
+ * socket, so we need to verify that the accepted connection
+ * is made from our own socket f[0].
+ */
+ if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT);
if (f[1] == NULL) {
goto failed;
}
+ if (peerAddr.inet.port != selfAddr.inet.port) {
+ /* the connection we accepted is not from f[0] */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ goto failed;
+ }
PR_Close(listenSock);
return PR_SUCCESS;
@@ -1532,6 +1569,9 @@ failed:
if (f[0]) {
PR_Close(f[0]);
}
+ if (f[1]) {
+ PR_Close(f[1]);
+ }
return PR_FAILURE;
#endif
}
@@ -1539,20 +1579,14 @@ failed:
PR_IMPLEMENT(PRInt32)
PR_FileDesc2NativeHandle(PRFileDesc *fd)
{
- if (fd) {
- /*
- * The fd may be layered. Chase the links to the
- * bottom layer to get the osfd.
- */
- PRFileDesc *bottom = fd;
- while (bottom->lower != NULL) {
- bottom = bottom->lower;
- }
- return bottom->secret->md.osfd;
- } else {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- return -1;
- }
+ if (fd) {
+ fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
+ }
+ if (!fd) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ return fd->secret->md.osfd;
}
PR_IMPLEMENT(void)
diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c
index b3802055..24a15f8a 100644
--- a/pr/src/linking/prlink.c
+++ b/pr/src/linking/prlink.c
@@ -262,6 +262,10 @@ void _PR_InitLinker(void)
}
#if defined(WIN16)
+/*
+ * _PR_ShutdownLinker unloads all dlls loaded by the application via
+ * calls to PR_LoadLibrary
+ */
void _PR_ShutdownLinker(void)
{
PR_EnterMonitor(pr_linker_lock);
@@ -282,6 +286,32 @@ void _PR_ShutdownLinker(void)
PR_DestroyMonitor(pr_linker_lock);
pr_linker_lock = NULL;
}
+#else
+/*
+ * _PR_ShutdownLinker was originally only used on WIN16 (see above),
+ * but I think it should also be used on other platforms. However,
+ * I disagree with the original implementation's unloading the dlls
+ * for the application. Any dlls that still remain on the pr_loadmap
+ * list when NSPR shuts down are application programming errors. The
+ * only exception is pr_exe_loadmap, which was added to the list by
+ * NSPR and hence should be cleaned up by NSPR.
+ */
+void _PR_ShutdownLinker(void)
+{
+ /* FIXME: pr_exe_loadmap should be destroyed. */
+
+ PR_DestroyMonitor(pr_linker_lock);
+ pr_linker_lock = NULL;
+
+ if (_pr_currentLibPath) {
+ free(_pr_currentLibPath);
+ _pr_currentLibPath = NULL;
+ }
+
+#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR)
+ PR_DELETE(errStrBuf);
+#endif
+}
#endif
/******************************************************************************/
@@ -292,7 +322,9 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
if (!_pr_initialized) _PR_ImplicitInitialization();
PR_EnterMonitor(pr_linker_lock);
- PR_FREEIF(_pr_currentLibPath);
+ if (_pr_currentLibPath) {
+ free(_pr_currentLibPath);
+ }
if (path) {
_pr_currentLibPath = strdup(path);
if (!_pr_currentLibPath) {
@@ -310,7 +342,7 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
** Return the library path for finding shared libraries.
*/
PR_IMPLEMENT(char *)
-PR_GetLibraryPath()
+PR_GetLibraryPath(void)
{
char *ev;
char *copy = NULL; /* a copy of _pr_currentLibPath */
@@ -342,7 +374,7 @@ PR_GetLibraryPath()
ev = "";
len = strlen(ev) + 1; /* +1 for the null */
- p = (char*) PR_MALLOC(len);
+ p = (char*) malloc(len);
if (p) {
strcpy(p, ev);
}
@@ -369,7 +401,7 @@ PR_GetLibraryPath()
#endif
len = strlen(ev) + 1; /* +1 for the null */
- p = (char*) PR_MALLOC(len);
+ p = (char*) malloc(len);
if (p) {
strcpy(p, ev);
} /* if (p) */
@@ -1148,7 +1180,8 @@ PR_UnloadLibrary(PRLibrary *lib)
freeLib:
PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
- PR_DELETE(lib->name);
+ free(lib->name);
+ lib->name = NULL;
PR_DELETE(lib);
if (result == -1) {
PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
diff --git a/pr/src/malloc/prmem.c b/pr/src/malloc/prmem.c
index 0a70b439..20cf7e99 100644
--- a/pr/src/malloc/prmem.c
+++ b/pr/src/malloc/prmem.c
@@ -97,20 +97,79 @@ _PR_DestroyZones(void)
while (mz->head) {
MemBlockHdr *hdr = mz->head;
mz->head = hdr->s.next; /* unlink it */
- pr_ZoneFree(hdr);
+ free(hdr);
mz->elements--;
}
}
}
+ use_zone_allocator = PR_FALSE;
}
+/*
+** pr_FindSymbolInProg
+**
+** Find the specified data symbol in the program and return
+** its address.
+*/
+
+#ifdef USE_DLFCN
+
+#include <dlfcn.h>
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ void *h;
+ void *sym;
+
+ h = dlopen(0, RTLD_LAZY);
+ if (h == NULL)
+ return NULL;
+ sym = dlsym(h, name);
+ (void)dlclose(h);
+ return sym;
+}
+
+#elif defined(USE_HPSHL)
+
+#include <dl.h>
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ shl_t h = NULL;
+ void *sym;
+
+ if (shl_findsym(&h, name, TYPE_DATA, &sym) == -1)
+ return NULL;
+ return sym;
+}
+
+#elif defined(USE_MACH_DYLD)
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ /* FIXME: not implemented */
+ return NULL;
+}
+
+#else
+
+#error "The zone allocator is not supported on this platform"
+
+#endif
+
void
_PR_InitZones(void)
{
int i, j;
char *envp;
+ PRBool *sym;
- if (envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) {
+ if ((sym = pr_FindSymbolInProg("nspr_use_zone_allocator")) != NULL) {
+ use_zone_allocator = *sym;
+ } else if ((envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) != NULL) {
use_zone_allocator = (atoi(envp) == 1);
}
@@ -275,6 +334,11 @@ pr_ZoneRealloc(void *oldptr, PRUint32 bytes)
PR_ASSERT(mb->s.magic == ZONE_MAGIC);
if (mb->s.magic != ZONE_MAGIC) {
/* Maybe this just came from ordinary malloc */
+#ifdef DEBUG
+ fprintf(stderr,
+ "Warning: reallocing memory block %p from ordinary malloc\n",
+ oldptr);
+#endif
/* We don't know how big it is. But we can fix that. */
oldptr = realloc(oldptr, bytes);
if (!oldptr) {
@@ -329,6 +393,10 @@ pr_ZoneFree(void *ptr)
if (mb->s.magic != ZONE_MAGIC) {
/* maybe this came from ordinary malloc */
+#ifdef DEBUG
+ fprintf(stderr,
+ "Warning: freeing memory block %p from ordinary malloc\n", ptr);
+#endif
free(ptr);
return;
}
@@ -342,7 +410,7 @@ pr_ZoneFree(void *ptr)
if (!mz) {
PR_ASSERT(blockSize > 65536);
/* This block was not in any zone. Just free it. */
- free(ptr);
+ free(mb);
return;
}
PR_ASSERT(mz->blockSize == blockSize);
diff --git a/pr/src/md/beos/bfile.c b/pr/src/md/beos/bfile.c
index e80181cc..38da1f33 100644
--- a/pr/src/md/beos/bfile.c
+++ b/pr/src/md/beos/bfile.c
@@ -118,18 +118,45 @@ _MD_make_nonblock (PRFileDesc *fd)
}
+PRStatus
+_MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
+{
+ int rv;
+
+ rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
+ if (-1 == rv) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
void
_MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
{
- /* XXX this function needs to be implemented */
- fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ if (imported) {
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ if (flags == -1) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return;
+ }
+ fd->secret->inheritable = (flags & FD_CLOEXEC) ?
+ _PR_TRI_TRUE : _PR_TRI_FALSE;
+ }
}
void
_MD_query_fd_inheritable (PRFileDesc *fd)
{
- /* XXX this function needs to be implemented */
- PR_ASSERT(0);
+ int flags;
+
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+ flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ PR_ASSERT(-1 != flags);
+ fd->secret->inheritable = (flags & FD_CLOEXEC) ?
+ _PR_TRI_FALSE : _PR_TRI_TRUE;
}
PRInt32
@@ -223,12 +250,14 @@ _MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
return( rv );
}
+#ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
PRInt32
-_MD_writev (PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size,
+_MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
PRIntervalTime timeout)
{
return PR_NOT_IMPLEMENTED_ERROR;
}
+#endif
PRInt32
_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
@@ -524,191 +553,277 @@ int rv, err;
}
PRInt32
-_MD_pr_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+_MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
- PRInt32 rc = 0;
- fd_set rd, wr;
- struct timeval tv, *tvp = NULL;
+ PRInt32 rv = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ /*
+ * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
+ */
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
PRPollDesc *pd, *epd;
- int i = 0, j = 0;
- int maxfd = -1;
- PRInt32 osfd;
- PRInt16 in_flags;
- PRFileDesc *bottom;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
- /*printf("POLL: entering _MD_pr_poll\n");*/
-
- /*
- * Is it an empty set? If so, just sleep for the timeout and return
- */
- if (npds < 1)
- {
- /*printf("POLL: empty set. exiting _MD_pr_poll\n");*/
- PR_Sleep(timeout);
- return rc;
- }
+ struct timeval tv, *tvp = NULL;
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ if (0 == npds) {
+ PR_Sleep(timeout);
+ return rv;
+ }
- FD_ZERO(&rd);
- FD_ZERO(&wr);
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
- /*
- * first, sort out the new connects, the reads, and the writes
- */
- epd = pds + npds;
- for(pd = pds; pd < epd; pd++)
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
{
- in_flags = pd->in_flags;
- bottom = pd->fd;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
- if(bottom != 0 && in_flags != 0)
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
{
- while(bottom->lower != 0)
+ if (pd->in_flags & PR_POLL_READ)
{
- bottom = bottom->lower;
+ in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
}
- osfd = bottom->secret->md.osfd;
-
- if(in_flags & PR_POLL_WRITE || in_flags & PR_POLL_EXCEPT)
+ if (pd->in_flags & PR_POLL_WRITE)
{
- /*printf("POLL: adding to write\n");*/
- FD_SET(osfd, &wr);
- if( osfd > maxfd ) maxfd = osfd;
+ in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
}
- if(in_flags & PR_POLL_READ || in_flags & PR_POLL_EXCEPT)
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
{
- /*printf("POLL: adding to read\n");*/
- FD_SET(osfd, &rd);
- if( osfd > maxfd ) maxfd = osfd;
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
}
}
-
-
- }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
- if(maxfd >= 0)
+ remaining = timeout;
+ start = PR_IntervalNow();
+
+ retry:
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = remaining - (ticksPerSecond * tv.tv_sec);
+ tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond;
+ tvp = &tv;
+ }
+
+ ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
+
+ if (ready == -1 && errno == EINTR)
{
- PRInt32 n;
- do {
- PRIntervalTime start = PR_IntervalNow();
- if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
{
- /*printf("POLL: timeout = %ld\n", (long) PR_IntervalToMicroseconds(timeout));*/
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
- tvp = &tv;
+ remaining = timeout - elapsed;
+ goto retry;
}
+ }
+ }
-
- n = select(maxfd + 1, &rd, &wr, 0, tvp);
- /*printf("POLL: maxfd = %d, select returns %d, errno = %d %s\n", maxfd, n, errno, strerror(errno));*/
- if (n == 0 || (n < 0 && errno == EINTR))
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
{
- if (timeout != PR_INTERVAL_NO_TIMEOUT)
- {
- timeout -= PR_IntervalNow() - start;
- if(timeout <= 0)
+ PRInt32 osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
+
+ if (FD_ISSET(osfd, &rd))
{
- /* timed out */
- n = 0;
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
}
- }
- }
-
- } while(n < 0 && errno == EINTR);
-
- if(n > 0)
- {
- epd = pds + npds;
- for(pd = pds; pd < epd; pd++)
- {
- int selected;
- in_flags = pd->in_flags;
- bottom = pd->fd;
- selected = 0;
-
- if(bottom != 0 && in_flags != 0)
+ if (FD_ISSET(osfd, &wt))
{
- while(bottom->lower != 0)
- {
- bottom = bottom->lower;
- }
- osfd = bottom->secret->md.osfd;
- if (FD_ISSET(osfd, &rd))
- {
- pd->out_flags |= PR_POLL_READ;
- selected++;
- }
- if (FD_ISSET(osfd, &wr))
- {
- pd->out_flags |= PR_POLL_WRITE;
- selected++;
- }
-
- if(selected > 0)
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+
+/* Workaround for nonblocking connects under net_server */
+#ifndef BONE_VERSION
+ if (out_flags)
+ {
+ /* check if it is a pending connect */
+ int i = 0, j = 0;
+ PR_Lock( _connectLock );
+ for( i = 0; i < connectCount; i++ )
{
- rc++;
- /*
- * check if it is a pending connect
- */
- PR_Lock( _connectLock );
- for( i = 0; i < connectCount; i++ )
+ if(connectList[i].osfd == osfd)
{
- if(connectList[i].osfd == osfd)
+ int connectError;
+ int connectResult;
+
+ connectResult = connect(connectList[i].osfd,
+ &connectList[i].addr,
+ connectList[i].addrlen);
+ connectError = errno;
+
+ if(connectResult < 0 )
{
- int connectError;
- int connectResult;
-
- connectResult = connect(connectList[i].osfd,
- &connectList[i].addr,
- connectList[i].addrlen);
- connectError = errno;
-
- if(connectResult < 0 )
+ if(connectError == EINTR || connectError == EWOULDBLOCK ||
+ connectError == EINPROGRESS || connectError == EALREADY)
{
- if(connectError == EINTR || connectError == EWOULDBLOCK
- || connectError == EINPROGRESS || connectError == EALREADY)
- {
- break;
- }
+ break;
}
-
- if(i == (connectCount - 1))
+ }
+
+ if(i == (connectCount - 1))
+ {
+ connectList[i].osfd = -1;
+ } else {
+ for(j = i; j < connectCount; j++ )
{
- connectList[i].osfd = -1;
- } else {
- for(j = i; j < connectCount; j++ )
- {
- memcpy( &connectList[j], &connectList[j+1],
- sizeof(connectList[j]));
- }
+ memcpy( &connectList[j], &connectList[j+1],
+ sizeof(connectList[j]));
}
- connectCount--;
-
- bottom->secret->md.connectReturnValue = connectResult;
- bottom->secret->md.connectReturnError = connectError;
- bottom->secret->md.connectValueValid = PR_TRUE;
- break;
}
+ connectCount--;
+
+ bottom->secret->md.connectReturnValue = connectResult;
+ bottom->secret->md.connectReturnError = connectError;
+ bottom->secret->md.connectValueValid = PR_TRUE;
+ break;
}
-
-
- PR_Unlock( _connectLock );
}
- } else {
- pd->out_flags = 0;
- continue;
+ PR_Unlock( _connectLock );
}
-
+#endif
}
- } else if (n < 0) {
- /* hit error that's not EINTR. */
- rc = -1;
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
}
+ PR_ASSERT(ready > 0);
}
-
- /*printf("POLL: exiting _MD_pr_poll with %d\n", rc);*/
- return rc;
-}
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+ return ready;
+} /* _MD_pr_poll */
/*
* File locking.
diff --git a/pr/src/md/beos/bmisc.c b/pr/src/md/beos/bmisc.c
index 634bea11..056d26a9 100644
--- a/pr/src/md/beos/bmisc.c
+++ b/pr/src/md/beos/bmisc.c
@@ -37,8 +37,12 @@
#include <stdlib.h>
PRLock *_connectLock = NULL;
+
+#ifndef BONE_VERSION
+/* Workaround for nonblocking connects under net_server */
PRUint32 connectCount = 0;
ConnectListNode connectList[64];
+#endif
void
_MD_cleanup_before_exit (void)
@@ -63,7 +67,10 @@ _MD_final_init (void)
{
_connectLock = PR_NewLock();
PR_ASSERT(NULL != _connectLock);
+#ifndef BONE_VERSION
+ /* Workaround for nonblocking connects under net_server */
connectCount = 0;
+#endif
}
void
diff --git a/pr/src/md/beos/bnet.c b/pr/src/md/beos/bnet.c
index 86943b3b..2aa0194f 100644
--- a/pr/src/md/beos/bnet.c
+++ b/pr/src/md/beos/bnet.c
@@ -1,5 +1,5 @@
/* -*- Mode: C++; c-basic-offset: 4 -*- */
-/*
+/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
@@ -49,6 +49,7 @@
*/
#define _PRSockLen_t int
+
/*
** Global lock variable used to bracket calls into rusty libraries that
** aren't thread safe (like libc, libX, etc).
@@ -56,135 +57,154 @@
static PRLock *_pr_rename_lock = NULL;
static PRMonitor *_pr_Xfe_mon = NULL;
-/*
+#define READ_FD 1
+#define WRITE_FD 2
+
+/*
** This is a support routine to handle "deferred" i/o on sockets.
** It uses "select", so it is subject to all of the BeOS limitations
** (only READ notification, only sockets)
*/
-#define READ_FD 1
-#define WRITE_FD 2
+
+/*
+ * socket_io_wait --
+ *
+ * wait for socket i/o, periodically checking for interrupt
+ *
+ */
static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
- PRIntervalTime timeout)
+ PRIntervalTime timeout)
{
- PRInt32 rv = -1;
- struct timeval tv, *tvp;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- PRIntervalTime epoch, now, elapsed, remaining;
- PRInt32 syserror;
- fd_set rd_wr;
-
- switch (timeout) {
- case PR_INTERVAL_NO_WAIT:
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- break;
- case PR_INTERVAL_NO_TIMEOUT:
- /*
- * This is a special case of the 'default' case below.
- * Please see the comments there.
- */
- tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
- tv.tv_usec = 0;
- tvp = &tv;
- FD_ZERO(&rd_wr);
- do {
- FD_SET(osfd, &rd_wr);
- if (fd_type == READ_FD)
- rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
- else
- rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- if (syserror == EBADF) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, syserror);
- }
- if( _PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- break;
- }
- break;
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- default:
- now = epoch = PR_IntervalNow();
- remaining = timeout;
- tvp = &tv;
- FD_ZERO(&rd_wr);
- do {
- /*
- * We block in _MD_SELECT for at most
- * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
- * so that there is an upper limit on the delay
- * before the interrupt bit is checked.
- */
- tv.tv_sec = PR_IntervalToSeconds(remaining);
- if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
- tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
- tv.tv_usec = 0;
- } else {
- tv.tv_usec = PR_IntervalToMicroseconds(
- remaining -
- PR_SecondsToInterval(tv.tv_sec));
- }
- FD_SET(osfd, &rd_wr);
- if (fd_type == READ_FD)
- rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
- else
- rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
- /*
- * we don't consider EINTR a real error
- */
- if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
- if (syserror == EBADF) {
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
- } else {
- PR_SetError(PR_UNKNOWN_ERROR, syserror);
- }
- break;
- }
- if (_PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
- rv = -1;
- break;
- }
- /*
- * We loop again if _MD_SELECT timed out or got interrupted
- * by a signal, and the timeout deadline has not passed yet.
- */
- if (rv == 0 || (rv == -1 && syserror == EINTR)) {
- /*
- * If _MD_SELECT timed out, we know how much time
- * we spent in blocking, so we can avoid a
- * PR_IntervalNow() call.
- */
- if (rv == 0) {
- now += PR_SecondsToInterval(tv.tv_sec)
- + PR_MicrosecondsToInterval(tv.tv_usec);
- } else {
- now = PR_IntervalNow();
- }
- elapsed = (PRIntervalTime) (now - epoch);
- if (elapsed >= timeout) {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
- break;
- } else {
- remaining = timeout - elapsed;
- }
- }
- } while (rv == 0 || (rv == -1 && syserror == EINTR));
- break;
- }
- return(rv);
+ PRInt32 rv = -1;
+ struct timeval tv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
+ fd_set rd_wr;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+#ifdef BONE_VERSION
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+#else
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+#endif
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ FD_ZERO(&rd_wr);
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+#ifdef BONE_VERSION
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+#else
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+#endif
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
}
-
-
PRInt32
_MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
PRIntervalTime timeout)
@@ -193,33 +213,44 @@ _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifndef BONE_VERSION
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
- _PR_MD_MAP_RECV_ERROR(EPIPE);
- return -1;
+ _PR_MD_MAP_RECV_ERROR(EPIPE);
+ return -1;
}
+#endif
+
+#ifdef BONE_VERSION
+ /*
+ ** Gah, stupid hack. If reading a zero amount, instantly return success.
+ ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
+ ** mozilla use to check for socket availability.
+ */
+
+ if( 0 == amount ) return(0);
+#endif
while ((rv = recv(osfd, buf, amount, flags)) == -1) {
- err = _MD_ERRNO();
+ err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- /* If socket was supposed to be blocking,
- wait a while for the condition to be
- satisfied. */
- if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
- goto done;
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
- continue;
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If socket was supposed to be blocking,
+ wait a while for the condition to be
+ satisfied. */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
- } else {
- break;
- }
+ } else
+ break;
}
if (rv < 0) {
- _PR_MD_MAP_RECV_ERROR(err);
+ _PR_MD_MAP_RECV_ERROR(err);
}
done:
@@ -235,31 +266,38 @@ _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
PRThread *me = _PR_MD_CURRENT_THREAD();
while ((*addrlen = PR_NETADDR_SIZE(addr)),
- ((rv = recvfrom(osfd, buf, amount, flags,
- (struct sockaddr *) addr,
- (_PRSockLen_t *)addrlen)) == -1)) {
- err = _MD_ERRNO();
-
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1)) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
goto done;
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
- continue;
-
- } else {
- break;
- }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+ } else {
+ break;
+ }
}
if (rv < 0) {
- _PR_MD_MAP_RECVFROM_ERROR(err);
+ _PR_MD_MAP_RECVFROM_ERROR(err);
}
done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
return(rv);
}
@@ -271,46 +309,56 @@ _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifndef BONE_VERSION
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
{
- _PR_MD_MAP_SEND_ERROR(EPIPE);
- return -1;
+ _PR_MD_MAP_SEND_ERROR(EPIPE);
+ return -1;
}
+#endif
while ((rv = send(osfd, buf, amount, flags)) == -1) {
- err = _MD_ERRNO();
+ err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
- if( _PR_PENDING_INTERRUPT(me)) {
+#ifndef BONE_VERSION
+ if( _PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
return -1;
}
- /* in UNIX implementations, you could do a socket_io_wait here.
- * but since BeOS doesn't yet support WRITE notification in select,
- * you're spanked.
- */
- snooze( 10000L );
- continue;
-
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
- continue;
+ /* in UNIX implementations, you could do a socket_io_wait here.
+ * but since BeOS doesn't yet support WRITE notification in select,
+ * you're spanked.
+ */
+ snooze( 10000L );
+ continue;
+#else /* BONE_VERSION */
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+#endif
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
- } else {
- break;
- }
+ } else {
+ break;
+ }
}
if (rv < 0) {
- _PR_MD_MAP_SEND_ERROR(err);
+ _PR_MD_MAP_SEND_ERROR(err);
}
+#ifdef BONE_VERSION
+done:
+#endif
return(rv);
}
@@ -321,32 +369,97 @@ _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
while ((rv = sendto(osfd, buf, amount, flags,
- (struct sockaddr *) addr, addrlen)) == -1) {
- err = _MD_ERRNO();
+ (struct sockaddr *) &addrCopy, addrlen)) == -1) {
+#else
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+#endif
+ err = _MD_ERRNO();
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
- printf( "This should be a blocking sendto call!!!\n" );
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
- continue;
+#ifdef BONE_VERSION
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+#endif
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
- } else {
- break;
- }
+ } else {
+ break;
+ }
}
if (rv < 0) {
- _PR_MD_MAP_SENDTO_ERROR(err);
+ _PR_MD_MAP_SENDTO_ERROR(err);
}
+#ifdef BONE_VERSION
+done:
+#endif
+ return(rv);
+}
+
+#ifdef BONE_VERSION
+
+PRInt32 _MD_writev(
+ PRFileDesc *fd, const PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
return(rv);
}
+#endif /* BONE_VERSION */
+
PRInt32
_MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
PRIntervalTime timeout)
@@ -356,42 +469,39 @@ _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
PRThread *me = _PR_MD_CURRENT_THREAD();
while ((rv = accept(osfd, (struct sockaddr *) addr,
- (_PRSockLen_t *)addrlen)) == -1) {
- err = _MD_ERRNO();
-
- if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
- if (fd->secret->nonblocking) {
- break;
- }
- /* If it's SUPPOSED to be a blocking thread, wait
- * a while to see if the triggering condition gets
- * satisfied.
- */
- /* Assume that we're always using a native thread */
- if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
- goto done;
- } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
- continue;
- } else {
- break;
- }
- }
-
- if (addr) addr->raw.family = AF_INET;
+ (_PRSockLen_t *)addrlen)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If it's SUPPOSED to be a blocking thread, wait
+ * a while to see if the triggering condition gets
+ * satisfied.
+ */
+ /* Assume that we're always using a native thread */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+ } else {
+ break;
+ }
+ }
if (rv < 0) {
- _PR_MD_MAP_ACCEPT_ERROR(err);
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ } else if (addr != NULL) {
+ /* bug 134099 */
+ err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
}
done:
#ifdef _PR_HAVE_SOCKADDR_LEN
if (rv != -1) {
- /* Mask off the first byte of struct sockaddr (the length field) */
- if (addr) {
- *((unsigned char *) addr) = 0;
-#ifdef IS_LITTLE_ENDIAN
- addr->raw.family = ntohs(addr->raw.family);
-#endif
- }
+ /* Mask off the first byte of struct sockaddr (the length field) */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
}
#endif /* _PR_HAVE_SOCKADDR_LEN */
return(rv);
@@ -401,62 +511,118 @@ PRInt32
_MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
PRIntervalTime timeout)
{
- PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+#ifndef BONE_VERSION
fd->secret->md.connectValueValid = PR_FALSE;
+#endif
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+#endif
+
+ /* (Copied from unix.c)
+ * We initiate the connection setup by making a nonblocking connect()
+ * call. If the connect() call fails, there are two cases we handle
+ * specially:
+ * 1. The connect() call was interrupted by a signal. In this case
+ * we simply retry connect().
+ * 2. The NSPR socket is nonblocking and connect() fails with
+ * EINPROGRESS. We first wait until the socket becomes writable.
+ * Then we try to find out whether the connection setup succeeded
+ * or failed.
+ */
retry:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
+#else
if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+#endif
err = _MD_ERRNO();
- fd->secret->md.connectReturnValue = rv;
- fd->secret->md.connectReturnError = err;
- fd->secret->md.connectValueValid = PR_TRUE;
-
- if( err == EINTR ) {
+#ifndef BONE_VERSION
+ fd->secret->md.connectReturnValue = rv;
+ fd->secret->md.connectReturnError = err;
+ fd->secret->md.connectValueValid = PR_TRUE;
+#endif
+ if( err == EINTR ) {
- if( _PR_PENDING_INTERRUPT(me)) {
+ if( _PR_PENDING_INTERRUPT(me)) {
- me->flags &= ~_PR_INTERRUPT;
+ me->flags &= ~_PR_INTERRUPT;
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
return -1;
}
- snooze( 100000L );
+#ifndef BONE_VERSION
+ snooze( 100000L );
+#endif
goto retry;
}
+#ifndef BONE_VERSION
if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
- /*
- ** There's no timeout on this connect, but that's not
- ** a big deal, since the connect times out anyways
- ** after 30 seconds. Just sleep for 1/10th of a second
- ** and retry until we go through or die.
- */
+ /*
+ ** There's no timeout on this connect, but that's not
+ ** a big deal, since the connect times out anyways
+ ** after 30 seconds. Just sleep for 1/10th of a second
+ ** and retry until we go through or die.
+ */
- if( _PR_PENDING_INTERRUPT(me)) {
+ if( _PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
return -1;
- }
+ }
+
+ goto retry;
+ }
- goto retry;
- }
+ if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
+ PR_Lock(_connectLock);
+ if (connectCount < sizeof(connectList)/sizeof(connectList[0])) {
+ connectList[connectCount].osfd = osfd;
+ memcpy(&connectList[connectCount].addr, addr, addrlen);
+ connectList[connectCount].addrlen = addrlen;
+ connectList[connectCount].timeout = timeout;
+ connectCount++;
+ PR_Unlock(_connectLock);
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ } else {
+ PR_Unlock(_connectLock);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+ return rv;
+ }
+#else /* BONE_VERSION */
+ if(!fd->secret->nonblocking && (err == EINTR)) {
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
+ }
- if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
- PR_Lock(_connectLock);
- connectList[connectCount].osfd = osfd;
- memcpy(&connectList[connectCount].addr, addr, addrlen);
- connectList[connectCount].addrlen = addrlen;
- connectList[connectCount].timeout = timeout;
- connectCount++;
- PR_Unlock(_connectLock);
- _PR_MD_MAP_CONNECT_ERROR(err);
- return rv;
- }
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ err = _MD_beos_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ return 0;
+ }
+#endif
- _PR_MD_MAP_CONNECT_ERROR(err);
+ _PR_MD_MAP_CONNECT_ERROR(err);
}
return rv;
@@ -466,9 +632,16 @@ PRInt32
_MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
{
PRInt32 rv, err;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
+#else
rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
-
+#endif
if (rv < 0) {
err = _MD_ERRNO();
_PR_MD_MAP_BIND_ERROR(err);
@@ -482,12 +655,14 @@ _MD_listen (PRFileDesc *fd, PRIntn backlog)
{
PRInt32 rv, err;
+#ifndef BONE_VERSION
/* Bug workaround! Setting listen to 0 on Be accepts no connections.
** On most UN*Xes this sets the default.
*/
if( backlog == 0 ) backlog = 5;
-
+#endif
+
rv = listen(fd->secret->md.osfd, backlog);
if (rv < 0) {
err = _MD_ERRNO();
@@ -502,15 +677,24 @@ _MD_shutdown (PRFileDesc *fd, PRIntn how)
{
PRInt32 rv, err;
+#ifndef BONE_VERSION
if (how == PR_SHUTDOWN_SEND)
- fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
else if (how == PR_SHUTDOWN_RCV)
- fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
else if (how == PR_SHUTDOWN_BOTH) {
- fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
+ fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
}
return 0;
+#else /* BONE_VERSION */
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SHUTDOWN_ERROR(err);
+ }
+ return(rv);
+#endif
}
PRInt32
@@ -522,7 +706,11 @@ _MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
PRInt32
_MD_close_socket (PRInt32 osfd)
{
+#ifdef BONE_VERSION
+ close( osfd );
+#else
closesocket( osfd );
+#endif
}
PRStatus
@@ -532,7 +720,14 @@ _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
rv = getsockname(fd->secret->md.osfd,
(struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
-
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv == 0) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
if (rv < 0) {
err = _MD_ERRNO();
_PR_MD_MAP_GETSOCKNAME_ERROR(err);
@@ -560,9 +755,6 @@ PRStatus
_MD_getsockopt (PRFileDesc *fd, PRInt32 level,
PRInt32 optname, char* optval, PRInt32* optlen)
{
- return PR_NOT_IMPLEMENTED_ERROR;
-
-#if 0
PRInt32 rv, err;
rv = getsockopt(fd->secret->md.osfd, level, optname,
@@ -573,7 +765,6 @@ _MD_getsockopt (PRFileDesc *fd, PRInt32 level,
}
return rv==0?PR_SUCCESS:PR_FAILURE;
-#endif
}
PRStatus
@@ -597,6 +788,7 @@ _MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
return PR_NOT_IMPLEMENTED_ERROR;
}
+#ifndef BONE_VERSION
PRInt32
_MD_socket (int af, int type, int flags)
{
@@ -606,17 +798,43 @@ _MD_socket (int af, int type, int flags)
if( -1 == osfd ) {
- err = _MD_ERRNO();
- _PR_MD_MAP_SOCKET_ERROR( err );
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR( err );
}
return( osfd );
}
+#else
+PRInt32
+_MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket(domain, type, proto);
+
+ if (osfd == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
+
+ return(osfd);
+}
+#endif
PRInt32
_MD_socketavailable (PRFileDesc *fd)
{
+#ifdef BONE_VERSION
+ PRInt32 result;
+
+ if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
+ return -1;
+ }
+ return result;
+#else
return PR_NOT_IMPLEMENTED_ERROR;
+#endif
}
PRInt32
@@ -628,32 +846,25 @@ _MD_get_socket_error (void)
PRStatus
_MD_gethostname (char *name, PRUint32 namelen)
{
-PRInt32 rv, err;
+ PRInt32 rv, err;
rv = gethostname(name, namelen);
if (rv == 0)
{
- err = _MD_ERRNO();
- _PR_MD_MAP_GETHOSTNAME_ERROR(err);
- return PR_FAILURE;
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETHOSTNAME_ERROR(err);
+ return PR_FAILURE;
}
return PR_SUCCESS;
}
+#ifndef BONE_VERSION
PRInt32
_MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
{
int rv;
int flags = 0;
- if( fd->secret->md.connectValueValid == PR_TRUE )
-
- if( fd->secret->md.connectReturnValue == -1 )
-
- return fd->secret->md.connectReturnError;
- else
- return 0; /* No error */
-
rv = recv(fd->secret->md.osfd, NULL, 0, flags);
PR_ASSERT(-1 == rv || 0 == rv);
if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
@@ -661,3 +872,17 @@ _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
}
return 0; /* no error */
}
+#else
+PRInt32
+_MD_beos_get_nonblocking_connect_error(int osfd)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+ // int err;
+ // _PRSockLen_t optlen = sizeof(err);
+ // if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
+ // return errno;
+ // } else {
+ // return err;
+ // }
+}
+#endif /* BONE_VERSION */
diff --git a/pr/src/md/beos/bproc.c b/pr/src/md/beos/bproc.c
index 5d9ac0a5..54ccaa0f 100644
--- a/pr/src/md/beos/bproc.c
+++ b/pr/src/md/beos/bproc.c
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
@@ -33,28 +33,202 @@
*/
#include "primpl.h"
+#include <stdio.h>
+#include <signal.h>
+
+#define _PR_SIGNALED_EXITSTATUS 256
PRProcess*
_MD_create_process (const char *path, char *const *argv,
char *const *envp, const PRProcessAttr *attr)
{
- return NULL;
+ PRProcess *process;
+ int nEnv, idx;
+ char *const *childEnvp;
+ char **newEnvp = NULL;
+ int flags;
+
+ process = PR_NEW(PRProcess);
+ if (!process) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ childEnvp = envp;
+ if (attr && attr->fdInheritBuffer) {
+ if (NULL == childEnvp) {
+ childEnvp = environ;
+ }
+ for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
+ }
+ newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
+ if (NULL == newEnvp) {
+ PR_DELETE(process);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ for (idx = 0; idx < nEnv; idx++) {
+ newEnvp[idx] = childEnvp[idx];
+ }
+ newEnvp[idx++] = attr->fdInheritBuffer;
+ newEnvp[idx] = NULL;
+ childEnvp = newEnvp;
+ }
+
+ process->md.pid = fork();
+
+ if ((pid_t) -1 == process->md.pid) {
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ return NULL;
+ } else if (0 == process->md.pid) { /* the child process */
+ /*
+ * If the child process needs to exit, it must call _exit().
+ * Do not call exit(), because exit() will flush and close
+ * the standard I/O file descriptors, and hence corrupt
+ * the parent process's standard I/O data structures.
+ */
+
+ if (attr) {
+ /* the osfd's to redirect stdin, stdout, and stderr to */
+ int in_osfd = -1, out_osfd = -1, err_osfd = -1;
+
+ if (attr->stdinFd
+ && attr->stdinFd->secret->md.osfd != 0) {
+ in_osfd = attr->stdinFd->secret->md.osfd;
+ if (dup2(in_osfd, 0) != 0) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(0, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stdoutFd
+ && attr->stdoutFd->secret->md.osfd != 1) {
+ out_osfd = attr->stdoutFd->secret->md.osfd;
+ if (dup2(out_osfd, 1) != 1) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(1, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stderrFd
+ && attr->stderrFd->secret->md.osfd != 2) {
+ err_osfd = attr->stderrFd->secret->md.osfd;
+ if (dup2(err_osfd, 2) != 2) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(2, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (in_osfd != -1) {
+ close(in_osfd);
+ }
+ if (out_osfd != -1 && out_osfd != in_osfd) {
+ close(out_osfd);
+ }
+ if (err_osfd != -1 && err_osfd != in_osfd
+ && err_osfd != out_osfd) {
+ close(err_osfd);
+ }
+ if (attr->currentDirectory) {
+ if (chdir(attr->currentDirectory) < 0) {
+ _exit(1); /* failed */
+ }
+ }
+ }
+
+ if (childEnvp) {
+ (void)execve(path, argv, childEnvp);
+ } else {
+ /* Inherit the environment of the parent. */
+ (void)execv(path, argv);
+ }
+ /* Whoops! It returned. That's a bad sign. */
+ _exit(1);
+ }
+
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+
+ return process;
}
PRStatus
_MD_detach_process (PRProcess *process)
{
- return PR_NOT_IMPLEMENTED_ERROR;
+ /* If we kept a process table like unix does,
+ * we'd remove the entry here.
+ * Since we dont', just delete the process variable
+ */
+ PR_DELETE(process);
+ return PR_SUCCESS;
}
PRStatus
_MD_wait_process (PRProcess *process, PRInt32 *exitCode)
{
- return PR_NOT_IMPLEMENTED_ERROR;
+ PRStatus retVal = PR_SUCCESS;
+ int ret, status;
+
+ /* Ignore interruptions */
+ do {
+ ret = waitpid(process->md.pid, &status, 0);
+ } while (ret == -1 && errno == EINTR);
+
+ /*
+ * waitpid() cannot return 0 because we did not invoke it
+ * with the WNOHANG option.
+ */
+ PR_ASSERT(0 != ret);
+
+ if (ret < 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+
+ /* If child process exited normally, return child exit code */
+ if (WIFEXITED(status)) {
+ *exitCode = WEXITSTATUS(status);
+ } else {
+ PR_ASSERT(WIFSIGNALED(status));
+ *exitCode = _PR_SIGNALED_EXITSTATUS;
+ }
+
+ PR_DELETE(process);
+ return PR_SUCCESS;
}
PRStatus
_MD_kill_process (PRProcess *process)
{
- return PR_NOT_IMPLEMENTED_ERROR;
+ PRErrorCode prerror;
+ PRInt32 oserror;
+
+ if (kill(process->md.pid, SIGKILL) == 0) {
+ return PR_SUCCESS;
+ }
+ oserror = errno;
+ switch (oserror) {
+ case EPERM:
+ prerror = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ESRCH:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, oserror);
+ return PR_FAILURE;
}
diff --git a/pr/src/md/mac/macdll.c b/pr/src/md/mac/macdll.c
index 2cfe79db..23b32759 100644
--- a/pr/src/md/mac/macdll.c
+++ b/pr/src/md/mac/macdll.c
@@ -218,7 +218,7 @@ GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, v
// see if this symbol is in this fragment
if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
- tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, pFilterData->inName, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
+ tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
else
return;
@@ -503,19 +503,30 @@ done:
OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
{
- UInt32 fragOffset, fragLength;
- Ptr main;
- Str255 fragName = "\p";
- Str255 errName;
- OSErr err;
-
- err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
- if (err != noErr) return err;
-
- err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
- kLoadCFrag, outConnectionID, &main, errName);
-
- return err;
+ UInt32 fragOffset, fragLength;
+ short fragNameLength;
+ Ptr main;
+ Str255 fragName;
+ Str255 errName;
+ OSErr err;
+
+ err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
+ if (err != noErr) return err;
+
+ // convert fragment name to pascal string
+ fragNameLength = strlen(fragmentName);
+ if (fragNameLength > 255)
+ fragNameLength = 255;
+ BlockMoveData(fragmentName, &fragName[1], fragNameLength);
+ fragName[0] = fragNameLength;
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+
+ return err;
}
@@ -532,39 +543,42 @@ OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFra
-----------------------------------------------------------------*/
OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
- char** outFragName, CFragConnectionID *outConnectionID)
+ char** outFragName, CFragConnectionID *outConnectionID)
{
- UInt32 fragOffset, fragLength;
- char *fragNameBlock = NULL;
- Ptr main;
- Str255 fragName = "\p";
- Str255 errName;
- OSErr err;
-
- *outFragName = NULL;
-
- err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
- if (err != noErr) return err;
-
- if (fragNameBlock)
- {
- UInt32 nameLen = strlen(fragNameBlock);
- if (nameLen > 63)
- nameLen = 63;
- BlockMoveData(fragNameBlock, &fragName[1], nameLen);
- fragName[0] = nameLen;
- }
-
- err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
- kLoadCFrag, outConnectionID, &main, errName);
- if (err != noErr)
- {
- free(fragNameBlock);
- return err;
- }
-
- *outFragName = fragNameBlock;
- return noErr;
+ UInt32 fragOffset, fragLength;
+ char *fragNameBlock = NULL;
+ Ptr main;
+ Str255 fragName = "\p";
+ Str255 errName;
+ OSErr err;
+
+ *outFragName = NULL;
+
+ err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
+ if (err != noErr) return err;
+
+ if (fragNameBlock)
+ {
+ UInt32 nameLen = strlen(fragNameBlock);
+ if (nameLen > 63)
+ nameLen = 63;
+ BlockMoveData(fragNameBlock, &fragName[1], nameLen);
+ fragName[0] = nameLen;
+ }
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+ if (err != noErr)
+ {
+ free(fragNameBlock);
+ return err;
+ }
+
+ *outFragName = fragNameBlock;
+ return noErr;
}
diff --git a/pr/src/md/mac/macio.c b/pr/src/md/mac/macio.c
index 0a546635..ef404db5 100644
--- a/pr/src/md/mac/macio.c
+++ b/pr/src/md/mac/macio.c
@@ -81,15 +81,16 @@ static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr)
if (_PR_MD_GET_INTSOFF()) {
thread->md.missedIONotify = PR_TRUE;
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- return;
- }
+ } else {
+ _PR_INTSOFF(is);
- _PR_INTSOFF(is);
+ thread->md.osErrCode = noErr;
+ DoneWaitingOnThisThread(thread);
- thread->md.osErrCode = noErr;
- DoneWaitingOnThisThread(thread);
+ _PR_FAST_INTSON(is);
+ }
- _PR_FAST_INTSON(is);
+ SignalIdleSemaphore();
}
void _MD_SetError(OSErr oserror)
@@ -266,7 +267,7 @@ PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
a 32 byte Ptr in the heap, so only do this once
*/
if (!sCompletionUPP)
- sCompletionUPP = NewIOCompletionProc((IOCompletionProcPtr)&AsyncIOCompletion);
+ sCompletionUPP = NewIOCompletionUPP((IOCompletionProcPtr)&AsyncIOCompletion);
/* grab the thread so we know which one to post to at completion */
pbAsync.thread = me;
diff --git a/pr/src/md/mac/macsocket.h b/pr/src/md/mac/macsocket.h
index b1045e36..b9194c52 100644
--- a/pr/src/md/mac/macsocket.h
+++ b/pr/src/md/mac/macsocket.h
@@ -39,6 +39,7 @@
// Interface visible to xp code
// C socket type definitions and routines
// from sys/socket.h
+#include <Files.h>
#include <OpenTptInternet.h> // All the internet typedefs
#include <utime.h> // For timeval
/*
diff --git a/pr/src/md/mac/macsockotpt.c b/pr/src/md/mac/macsockotpt.c
index ef15a56b..42462740 100644
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -38,6 +38,7 @@
#include <string.h>
#include <Gestalt.h>
+#include <Files.h>
#include <OpenTransport.h>
#include <OSUtils.h>
@@ -173,9 +174,9 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O
if (_PR_MD_GET_INTSOFF()) {
dnsContext.thread->md.missedIONotify = PR_TRUE;
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- return;
+ } else {
+ DoneWaitingOnThisThread(dnsContext.thread);
}
- DoneWaitingOnThisThread(dnsContext.thread);
break;
case kOTProviderWillClose:
@@ -189,9 +190,9 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O
if (_PR_MD_GET_INTSOFF()) {
dnsContext.thread->md.missedIONotify = PR_TRUE;
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- return;
+ } else {
+ DoneWaitingOnThisThread(dnsContext.thread);
}
- DoneWaitingOnThisThread(dnsContext.thread);
break;
default: // or else we don't handle the event
@@ -199,6 +200,8 @@ static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, O
}
// or else we don't handle the event
+
+ SignalIdleSemaphore();
}
@@ -296,10 +299,12 @@ WakeUpNotifiedThread(PRThread *thread, OTResult result)
if (_PR_MD_GET_INTSOFF()) {
thread->md.missedIONotify = PR_TRUE;
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- return;
+ } else {
+ DoneWaitingOnThisThread(thread);
}
- DoneWaitingOnThisThread(thread);
}
+
+ SignalIdleSemaphore();
}
// Notification routine
@@ -369,6 +374,8 @@ static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResul
PR_ASSERT(err == kOTNoError);
secret->md.exceptReady = PR_TRUE; // XXX Check this
+ md->disconnectError = discon.reason; // save for _MD_mac_get_nonblocking_connect_error
+
// wake up waiting threads, if any
result = -3199 - discon.reason; // obtain the negative error code
if ((readThread = secret->md.read.thread) != NULL) {
@@ -1080,12 +1087,12 @@ typedef struct RawEndpointAndThread
// A5 is OK. Cannot allocate memory here
static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
{
- RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr;
+ RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr;
PRThread * thread = endthr->thread;
EndpointRef * endpoint = endthr->endpoint;
_PRCPU * cpu = _PR_MD_CURRENT_CPU();
- OSStatus err;
- OTResult resultOT;
+ OSStatus err;
+ OTResult resultOT;
switch (code)
{
@@ -1169,10 +1176,12 @@ static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode co
if (_PR_MD_GET_INTSOFF()) {
thread->md.asyncNotifyPending = PR_TRUE;
cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
- return;
+ } else {
+ DoneWaitingOnThisThread(thread);
}
- DoneWaitingOnThisThread(thread);
}
+
+ SignalIdleSemaphore();
}
PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
@@ -1309,7 +1318,7 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva
err = kEFAULTErr;
goto ErrorExit;
}
-
+
// Bind to a local port; let the system assign it.
bindAddr.inet.family = AF_INET;
@@ -1320,19 +1329,19 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva
bindReq.addr.buf = (UInt8*) &bindAddr;
bindReq.qlen = 0;
- PR_Lock(fd->secret->md.miscLock);
+ PR_Lock(fd->secret->md.miscLock);
PrepareForAsyncCompletion(me, fd->secret->md.osfd);
- fd->secret->md.misc.thread = me;
+ fd->secret->md.misc.thread = me;
err = OTBind(endpoint, &bindReq, NULL);
if (err != kOTNoError) {
- me->io_pending = PR_FALSE;
- PR_Unlock(fd->secret->md.miscLock);
- goto ErrorExit;
- }
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
- PR_Unlock(fd->secret->md.miscLock);
+ PR_Unlock(fd->secret->md.miscLock);
err = me->md.osErrCode;
if (err != kOTNoError)
@@ -1344,26 +1353,26 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva
sndCall.addr.len = addrlen;
sndCall.addr.buf = (UInt8*) addr;
- if (!fd->secret->nonblocking) {
- PrepareForAsyncCompletion(me, fd->secret->md.osfd);
- PR_ASSERT(fd->secret->md.write.thread == NULL);
- fd->secret->md.write.thread = me;
+ if (!fd->secret->nonblocking) {
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ PR_ASSERT(fd->secret->md.write.thread == NULL);
+ fd->secret->md.write.thread = me;
}
-
+
err = OTConnect (endpoint, &sndCall, NULL);
- if (err == kOTNoError) {
- PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");
- }
- if (fd->secret->nonblocking) {
- if (err == kOTNoDataErr)
- err = EINPROGRESS;
- goto ErrorExit;
- } else {
- if (err != kOTNoError && err != kOTNoDataErr) {
- me->io_pending = PR_FALSE;
- goto ErrorExit;
- }
- }
+ if (err == kOTNoError) {
+ PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");
+ }
+ if (fd->secret->nonblocking) {
+ if (err == kOTNoDataErr)
+ err = EINPROGRESS;
+ goto ErrorExit;
+ } else {
+ if (err != kOTNoError && err != kOTNoDataErr) {
+ me->io_pending = PR_FALSE;
+ goto ErrorExit;
+ }
+ }
WaitOnThisThread(me, timeout);
@@ -1583,7 +1592,6 @@ static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount,
PRThread *me = _PR_MD_CURRENT_THREAD();
PRInt32 bytesLeft = amount;
TUnitData dgram;
- OTResult result;
PR_ASSERT(flags == 0);
@@ -1618,13 +1626,13 @@ static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount,
fd->secret->md.write.thread = me;
fd->secret->md.writeReady = PR_FALSE; // expect the worst
err = OTSndUData(endpoint, &dgram);
- if (result != kOTFlowErr) // hope for the best
+ if (err != kOTFlowErr) // hope for the best
fd->secret->md.writeReady = PR_TRUE;
} else {
fd->secret->md.read.thread = me;
fd->secret->md.readReady = PR_FALSE; // expect the worst
err = OTRcvUData(endpoint, &dgram, NULL);
- if (result != kOTNoDataErr) // hope for the best
+ if (err != kOTNoDataErr) // hope for the best
fd->secret->md.readReady = PR_TRUE;
}
@@ -1754,83 +1762,126 @@ static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PR
}
// check to see if any of the poll descriptors have data available
+// for reading or writing, by calling their poll methods (layered IO).
+static PRInt32 CheckPollDescMethods(PRPollDesc *pds, PRIntn npds, PRInt16 *outReadFlags, PRInt16 *outWriteFlags)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+ PRInt16 *readFlag, *writeFlag;
+
+ for (pd = pds, epd = pd + npds, readFlag = outReadFlags, writeFlag = outWriteFlags;
+ pd < epd;
+ pd++, readFlag++, writeFlag++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if (NULL == pd->fd || pd->in_flags == 0) continue;
+
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+
+ if ((0 != (in_flags_read & out_flags_read)) ||
+ (0 != (in_flags_write & out_flags_write)))
+ {
+ ready += 1; /* some layer has buffer input */
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+
+ *readFlag = in_flags_read;
+ *writeFlag = in_flags_write;
+ }
+
+ return ready;
+}
+
+// check to see if any of OT endpoints of the poll descriptors have data available
// for reading or writing.
-static PRInt32 CheckPollDescs(PRPollDesc *pds, PRIntn npds)
+static PRInt32 CheckPollDescEndpoints(PRPollDesc *pds, PRIntn npds, const PRInt16 *inReadFlags, const PRInt16 *inWriteFlags)
{
PRInt32 ready = 0;
PRPollDesc *pd, *epd;
+ const PRInt16 *readFlag, *writeFlag;
- for (pd = pds, epd = pd + npds; pd < epd; pd++)
- {
- PRInt16 in_flags_read = 0, in_flags_write = 0;
- PRInt16 out_flags_read = 0, out_flags_write = 0;
+ for (pd = pds, epd = pd + npds, readFlag = inReadFlags, writeFlag = inWriteFlags;
+ pd < epd;
+ pd++, readFlag++, writeFlag++)
+ {
+ PRFileDesc *bottomFD;
+ PRBool readReady, writeReady, exceptReady;
+ PRInt16 in_flags_read = *readFlag;
+ PRInt16 in_flags_write = *writeFlag;
- if (NULL == pd->fd || pd->in_flags == 0) continue;
+ if (NULL == pd->fd || pd->in_flags == 0) continue;
- if (pd->in_flags & PR_POLL_READ)
- {
- in_flags_read = (pd->fd->methods->poll)(
- pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
- }
- if (pd->in_flags & PR_POLL_WRITE)
- {
- in_flags_write = (pd->fd->methods->poll)(
- pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
- }
- if ((0 != (in_flags_read & out_flags_read))
- || (0 != (in_flags_write & out_flags_write)))
- {
- ready += 1; /* some layer has buffer input */
- pd->out_flags = out_flags_read | out_flags_write;
- }
- else
+ bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ /* bottomFD can be NULL for pollable sockets */
+ if (bottomFD)
+ {
+ if (_PR_FILEDESC_OPEN == bottomFD->secret->state)
{
- PRFileDesc *bottomFD;
- PRBool readReady, writeReady, exceptReady;
-
pd->out_flags = 0; /* pre-condition */
- bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
- /* bottomFD can be NULL for pollable sockets */
- if (bottomFD)
+
+ if (GetState(bottomFD, &readReady, &writeReady, &exceptReady))
{
- if (_PR_FILEDESC_OPEN == bottomFD->secret->state)
+ if (readReady)
{
- if (GetState(bottomFD, &readReady, &writeReady, &exceptReady))
- {
- if (readReady)
- {
- if (in_flags_read & PR_POLL_READ)
- pd->out_flags |= PR_POLL_READ;
- if (in_flags_write & PR_POLL_READ)
- pd->out_flags |= PR_POLL_WRITE;
- }
- if (writeReady)
- {
- if (in_flags_read & PR_POLL_WRITE)
- pd->out_flags |= PR_POLL_READ;
- if (in_flags_write & PR_POLL_WRITE)
- pd->out_flags |= PR_POLL_WRITE;
- }
- if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT))
- {
- pd->out_flags |= PR_POLL_EXCEPT;
- }
- if (0 != pd->out_flags) ready++;
- }
+ if (in_flags_read & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_WRITE;
}
- else /* bad state */
+ if (writeReady)
{
- ready += 1; /* this will cause an abrupt return */
- pd->out_flags = PR_POLL_NVAL; /* bogii */
+ if (in_flags_read & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_WRITE;
}
+ if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT))
+ {
+ pd->out_flags |= PR_POLL_EXCEPT;
+ }
+ if (0 != pd->out_flags) ready++;
}
}
+ else /* bad state */
+ {
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
}
+ }
+
+ return ready;
+}
+
+
+// see how many of the poll descriptors are ready
+static PRInt32 CountReadyPollDescs(PRPollDesc *pds, PRIntn npds)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ if (pd->out_flags)
+ ready ++;
+ }
return ready;
}
-// set or clear md.poll.thread on the poll descriptors
+// set or clear the poll thread on the poll descriptors
static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread)
{
PRInt32 ready = 0;
@@ -1862,43 +1913,84 @@ static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread)
bottomFD->secret->md.write.thread = thread;
}
}
- }
+ }
}
}
+
+#define DESCRIPTOR_FLAGS_ARRAY_SIZE 32
+
PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
+ PRInt16 readFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
+ PRInt16 writeFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
+
+ PRInt16 *readFlags = readFlagsArray;
+ PRInt16 *writeFlags = writeFlagsArray;
+
+ PRInt16 *ioFlags = NULL;
+
PRThread *thread = _PR_MD_CURRENT_THREAD();
- intn is;
- PRInt32 ready;
+ PRInt32 ready;
- if (timeout == PR_INTERVAL_NO_WAIT) {
- return CheckPollDescs(pds, npds);
+ if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE)
+ {
+ // we allocate a single double-size array. The first half is used
+ // for read flags, and the second half for write flags.
+ ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2);
+ if (!ioFlags)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+
+ readFlags = ioFlags;
+ writeFlags = &ioFlags[npds];
}
-
- _PR_INTSOFF(is);
- PR_Lock(thread->md.asyncIOLock);
- // ensure that we don't miss the firing of the notifier while checking socket status
- // need to set up the thread
- PrepareForAsyncCompletion(thread, 0);
+ if (timeout != PR_INTERVAL_NO_WAIT) {
+ intn is;
+
+ // we have to be outside the lock when calling this, since
+ // it can call arbitrary user code (including other socket
+ // entry points)
+ (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
- SetDescPollThread(pds, npds, thread);
- ready = CheckPollDescs(pds, npds);
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ PrepareForAsyncCompletion(thread, 0);
- PR_Unlock(thread->md.asyncIOLock);
- _PR_FAST_INTSON(is);
+ SetDescPollThread(pds, npds, thread);
- if (ready == 0) {
- WaitOnThisThread(thread, timeout);
- ready = CheckPollDescs(pds, npds);
+ (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
- } else {
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+
+ ready = CountReadyPollDescs(pds, npds);
+
+ if (ready == 0) {
+ WaitOnThisThread(thread, timeout);
+
+ // since we may have been woken by a pollable event firing,
+ // we have to check both poll methods and endpoints.
+ (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+ (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+ ready = CountReadyPollDescs(pds, npds);
+ }
+
thread->io_pending = PR_FALSE;
+ SetDescPollThread(pds, npds, NULL);
+ }
+ else {
+ (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+ (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+ ready = CountReadyPollDescs(pds, npds);
}
- SetDescPollThread(pds, npds, NULL);
-
+ if (readFlags != readFlagsArray)
+ PR_Free(ioFlags);
+
return ready;
}
@@ -2192,25 +2284,32 @@ ErrorExit:
}
-int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd)
+int _MD_mac_get_nonblocking_connect_error(PRFileDesc* fd)
{
- OTResult resultOT;
- EndpointRef endpoint = (EndpointRef) osfd;
+ EndpointRef endpoint = (EndpointRef)fd->secret->md.osfd;
+ OTResult resultOT = OTGetEndpointState(endpoint);
- resultOT = OTGetEndpointState(endpoint);
switch (resultOT) {
case T_OUTCON:
macsock_map_error(EINPROGRESS);
return -1;
+
case T_DATAXFER:
return 0;
+
case T_IDLE:
+ macsock_map_error(fd->secret->md.disconnectError);
+ fd->secret->md.disconnectError = 0;
return -1;
+
case T_INREL:
macsock_map_error(ENOTCONN);
return -1;
+
default:
PR_ASSERT(0);
return -1;
}
+
+ return -1; // not reached
}
diff --git a/pr/src/md/mac/macthr.c b/pr/src/md/mac/macthr.c
index 0df8a590..fd3b489d 100644
--- a/pr/src/md/mac/macthr.c
+++ b/pr/src/md/mac/macthr.c
@@ -39,7 +39,7 @@
#include <MacTypes.h>
#include <Timer.h>
#include <OSUtils.h>
-
+#include <Math64.h>
#include <LowMem.h>
#include <Multiprocessing.h>
#include <Gestalt.h>
@@ -49,6 +49,8 @@
TimerUPP gTimerCallbackUPP = NULL;
PRThread * gPrimaryThread = NULL;
+ProcessSerialNumber gApplicationProcess;
+
PR_IMPLEMENT(PRThread *) PR_GetPrimaryThread()
{
return gPrimaryThread;
@@ -159,7 +161,21 @@ extern void _MD_ClearStack(PRThreadStack *ts)
#pragma mark -
#pragma mark TIME MANAGER-BASED CLOCK
-TMTask gTimeManagerTaskElem;
+// On Mac OS X, it's possible for the application to spend lots of time
+// in WaitNextEvent, yielding to other applications. Since NSPR threads are
+// cooperative here, this means that NSPR threads will also get very little
+// time to run. To kick ourselves out of a WaitNextEvent call when we have
+// determined that it's time to schedule another thread, the Timer Task
+// (which fires every 8ms, even when other apps have the CPU) calls WakeUpProcess.
+// We only want to do this on Mac OS X; the gTimeManagerTaskDoesWUP variable
+// indicates when we're running on that OS.
+//
+// Note that the TimerCallback makes use of gApplicationProcess. We need to
+// have set this up before the first possible run of the timer task; we do
+// so in _MD_EarlyInit().
+static Boolean gTimeManagerTaskDoesWUP;
+
+static TMTask gTimeManagerTaskElem;
extern void _MD_IOInterrupt(void);
_PRInterruptTable _pr_interruptTable[] = {
@@ -168,6 +184,8 @@ _PRInterruptTable _pr_interruptTable[] = {
{ 0 }
};
+#define kMacTimerInMiliSecs 8L
+
pascal void TimerCallback(TMTaskPtr tmTaskPtr)
{
_PRCPU *cpu = _PR_MD_CURRENT_CPU();
@@ -184,8 +202,20 @@ pascal void TimerCallback(TMTaskPtr tmTaskPtr)
// And tell nspr that a clock interrupt occured.
_PR_ClockInterrupt();
- if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority)))
+ if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority))) {
+ if (gTimeManagerTaskDoesWUP) {
+ // We only want to call WakeUpProcess if we know that NSPR has managed to switch threads
+ // since the last call, otherwise we end up spewing out WakeUpProcess() calls while the
+ // application is blocking somewhere. This can interfere with events loops other than
+ // our own (see bug 158927).
+ if (UnsignedWideToUInt64(cpu->md.lastThreadSwitch) > UnsignedWideToUInt64(cpu->md.lastWakeUpProcess))
+ {
+ WakeUpProcess(&gApplicationProcess);
+ cpu->md.lastWakeUpProcess = UpTime();
+ }
+ }
_PR_SET_RESCHED_FLAG();
+ }
_PR_FAST_INTSON(is);
@@ -198,8 +228,10 @@ void _MD_StartInterrupts(void)
{
gPrimaryThread = _PR_MD_CURRENT_THREAD();
+ gTimeManagerTaskDoesWUP = RunningOnOSX();
+
if ( !gTimerCallbackUPP )
- gTimerCallbackUPP = NewTimerProc(TimerCallback);
+ gTimerCallbackUPP = NewTimerUPP(TimerCallback);
// Fill in the Time Manager queue element
@@ -222,26 +254,36 @@ void _MD_StopInterrupts(void)
}
}
+
+#define MAX_PAUSE_TIMEOUT_MS 500
+
void _MD_PauseCPU(PRIntervalTime timeout)
{
if (timeout != PR_INTERVAL_NO_WAIT)
{
- EventRecord theEvent;
-
- /*
- ** Calling WaitNextEvent() here is suboptimal. This routine should
- ** pause the process until IO or the timeout occur, yielding time to
- ** other processes on operating systems that require this (Mac OS classic).
- ** WaitNextEvent() may incur too much latency, and has other problems,
- ** such as the potential to drop suspend/resume events, and to handle
- ** AppleEvents at a time at which we're not prepared to handle them.
- */
- (void) WaitNextEvent(nullEvent, &theEvent, 1, NULL);
-
+ // There is a race condition entering the critical section
+ // in AsyncIOCompletion (and probably elsewhere) that can
+ // causes deadlock for the duration of this timeout. To
+ // work around this, use a max 500ms timeout for now.
+ // See bug 99561 for details.
+ if (PR_IntervalToMilliseconds(timeout) > MAX_PAUSE_TIMEOUT_MS)
+ timeout = PR_MillisecondsToInterval(MAX_PAUSE_TIMEOUT_MS);
+
+ WaitOnIdleSemaphore(timeout);
(void) _MD_IOInterrupt();
}
}
+void _MD_InitRunningCPU(_PRCPU* cpu)
+{
+ cpu->md.trackScheduling = RunningOnOSX();
+ if (cpu->md.trackScheduling) {
+ AbsoluteTime zeroTime = {0, 0};
+ cpu->md.lastThreadSwitch = UpTime();
+ cpu->md.lastWakeUpProcess = zeroTime;
+ }
+}
+
//##############################################################################
//##############################################################################
@@ -528,19 +570,25 @@ void _MD_SetIntsOff(PRInt32 ints)
#pragma mark -
#pragma mark CRITICAL REGION SUPPORT
+
+static PRBool RunningOnOSX()
+{
+ long systemVersion;
+ OSErr err = Gestalt(gestaltSystemVersion, &systemVersion);
+ return (err == noErr) && (systemVersion >= 0x00001000);
+}
+
+
#if MAC_CRITICAL_REGIONS
MDCriticalRegionID gCriticalRegion;
void InitCriticalRegion()
{
- long systemVersion;
OSStatus err;
// we only need to do critical region stuff on Mac OS X
- err = Gestalt(gestaltSystemVersion, &systemVersion);
- gUseCriticalRegions = (err == noErr) && (systemVersion >= 0x00001000);
-
+ gUseCriticalRegions = RunningOnOSX();
if (!gUseCriticalRegions) return;
err = MD_CriticalRegionCreate(&gCriticalRegion);
@@ -586,3 +634,85 @@ void LeaveCritialRegion()
#endif // MAC_CRITICAL_REGIONS
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark IDLE SEMAPHORE SUPPORT
+
+/*
+ Since the WaitNextEvent() in _MD_PauseCPU() is causing all sorts of
+ headache under Mac OS X we're going to switch to MPWaitOnSemaphore()
+ which should do what we want
+*/
+
+#if TARGET_CARBON
+PRBool gUseIdleSemaphore = PR_FALSE;
+MPSemaphoreID gIdleSemaphore = NULL;
+#endif
+
+void InitIdleSemaphore()
+{
+ // we only need to do idle semaphore stuff on Mac OS X
+#if TARGET_CARBON
+ gUseIdleSemaphore = RunningOnOSX();
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPCreateSemaphore(1 /* max value */, 0 /* initial value */, &gIdleSemaphore);
+ PR_ASSERT(err == noErr);
+ }
+#endif
+}
+
+void TermIdleSemaphore()
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPDeleteSemaphore(gIdleSemaphore);
+ PR_ASSERT(err == noErr);
+ gUseIdleSemaphore = NULL;
+ }
+#endif
+}
+
+
+void WaitOnIdleSemaphore(PRIntervalTime timeout)
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPWaitOnSemaphore(gIdleSemaphore, kDurationMillisecond * PR_IntervalToMilliseconds(timeout));
+ PR_ASSERT(err == noErr);
+ }
+ else
+#endif
+ {
+ EventRecord theEvent;
+ /*
+ ** Calling WaitNextEvent() here is suboptimal. This routine should
+ ** pause the process until IO or the timeout occur, yielding time to
+ ** other processes on operating systems that require this (Mac OS classic).
+ ** WaitNextEvent() may incur too much latency, and has other problems,
+ ** such as the potential to drop suspend/resume events.
+ */
+ (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
+ }
+}
+
+
+void SignalIdleSemaphore()
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ // often we won't be waiting on the semaphore here, so ignore any errors
+ (void)MPSignalSemaphore(gIdleSemaphore);
+ }
+ else
+#endif
+ {
+ WakeUpProcess(&gApplicationProcess);
+ }
+}
+
+
diff --git a/pr/src/md/mac/mdcriticalregion.c b/pr/src/md/mac/mdcriticalregion.c
index 927b9246..ff035d0d 100644
--- a/pr/src/md/mac/mdcriticalregion.c
+++ b/pr/src/md/mac/mdcriticalregion.c
@@ -35,6 +35,7 @@
*/
#include "mdcriticalregion.h"
+#include <MacErrors.h>
/*
This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion,
diff --git a/pr/src/md/mac/mdmac.c b/pr/src/md/mac/mdmac.c
index f7e9a4fa..6d65e578 100644
--- a/pr/src/md/mac/mdmac.c
+++ b/pr/src/md/mac/mdmac.c
@@ -70,6 +70,7 @@
unsigned char GarbageCollectorCacheFlusher(PRUint32 size);
extern PRThread *gPrimaryThread;
+extern ProcessSerialNumber gApplicationProcess; // in macthr.c
//##############################################################################
@@ -288,7 +289,10 @@ void _MD_EarlyInit()
{
Handle environmentVariables;
+ GetCurrentProcess(&gApplicationProcess);
+
INIT_CRITICAL_REGION();
+ InitIdleSemaphore();
#if !defined(MAC_NSPR_STANDALONE)
// MacintoshInitializeMemory(); Moved to mdmacmem.c: AllocateRawMemory(Size blockSize)
@@ -376,6 +380,7 @@ void CleanupTermProc(void)
_MD_StopInterrupts(); // deactive Time Manager task
CLOSE_OPEN_TRANSPORT();
+ TermIdleSemaphore();
TERM_CRITICAL_REGION();
__NSTerminate();
diff --git a/pr/src/md/os2/os2_errors.c b/pr/src/md/os2/os2_errors.c
index f5be8391..5efd2c16 100644
--- a/pr/src/md/os2/os2_errors.c
+++ b/pr/src/md/os2/os2_errors.c
@@ -35,6 +35,44 @@
#include "prerror.h"
#include "primpl.h"
+void _MD_os2_map_default_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EMSGSIZE:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
void _MD_os2_map_opendir_error(PRInt32 err)
{
switch (err) {
@@ -92,7 +130,7 @@ void _MD_os2_map_closedir_error(PRInt32 err)
}
}
-void _MD_unix_readdir_error(PRInt32 err)
+void _MD_os2_readdir_error(PRInt32 err)
{
switch (err) {
@@ -671,73 +709,17 @@ void _MD_os2_map_send_error(PRInt32 err)
void _MD_os2_map_sendto_error(PRInt32 err)
{
- switch (err) {
- case EWOULDBLOCK:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case ENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case EMSGSIZE:
- case EINVAL:
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
- break;
- case ENOBUFS:
- PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
- break;
- case ECONNREFUSED:
- PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
- break;
- case EISCONN:
- PR_SetError(PR_IS_CONNECTED_ERROR, err);
- break;
-#ifdef SOCEFAULT
- case SOCEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
-#endif
- case ERROR_NETNAME_DELETED:
- PR_SetError(PR_CONNECT_RESET_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
+ _MD_os2_map_default_error(err);
+}
+
+void _MD_os2_map_writev_error(int err)
+{
+ _MD_os2_map_default_error(err);
}
void _MD_os2_map_accept_error(PRInt32 err)
{
- switch (err) {
- case EWOULDBLOCK:
- PR_SetError(PR_WOULD_BLOCK_ERROR, err);
- break;
- case EBADF:
- PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
- break;
- case ENOTSOCK:
- PR_SetError(PR_NOT_SOCKET_ERROR, err);
- break;
- case EOPNOTSUPP:
- PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
- break;
-#ifdef SOCEFAULT
- case SOCEFAULT:
- PR_SetError(PR_ACCESS_FAULT_ERROR, err);
- break;
-#endif
- case EMFILE:
- PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
- break;
- case ENOBUFS:
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
- break;
- default:
- PR_SetError(PR_UNKNOWN_ERROR, err);
- break;
- }
+ _MD_os2_map_default_error(err);
}
void _MD_os2_map_acceptex_error(PRInt32 err)
@@ -759,6 +741,21 @@ void _MD_os2_map_acceptex_error(PRInt32 err)
}
}
+/*
+ * An error code of 0 means that the nonblocking connect succeeded.
+ */
+
+int _MD_os2_get_nonblocking_connect_error(int osfd)
+{
+ int err;
+ int len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == -1) {
+ return sock_errno();
+ } else {
+ return err;
+ }
+}
+
void _MD_os2_map_connect_error(PRInt32 err)
{
switch (err) {
diff --git a/pr/src/md/os2/os2cv.c b/pr/src/md/os2/os2cv.c
index 1a2d9399..76c96330 100644
--- a/pr/src/md/os2/os2cv.c
+++ b/pr/src/md/os2/os2cv.c
@@ -48,6 +48,38 @@
#include "primpl.h"
+#ifdef USE_RAMSEM
+ULONG _Far16 _Pascal Dos16GetInfoSeg(PSEL pselGlobal, PSEL pselLocal);
+
+typedef struct _LINFOSEG
+{
+ USHORT pidCurrent;
+ USHORT pidParent;
+ USHORT prtyCurrent;
+ USHORT tidCurrent;
+ USHORT sgCurrent;
+ UCHAR rfProcStatus;
+ UCHAR dummy1;
+ BOOL16 fForeground;
+ UCHAR typProcess;
+ UCHAR dummy2;
+ SEL selEnvironment;
+ USHORT offCmdLine;
+ USHORT cbDataSegment;
+ USHORT cbStack;
+ USHORT cbHeap;
+ USHORT hmod;
+ SEL selDS;
+ SEL selPack;
+ SEL selPackShr;
+ SEL selPackPck;
+ ULONG ulReserved;
+} LINFOSEG;
+typedef LINFOSEG FAR *PLINFOSEG;
+
+PLINFOSEG plisCurrent = NULL;
+#endif
+
/*
* AddThreadToCVWaitQueueInternal --
*
@@ -82,7 +114,7 @@ AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv)
* This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK,
* the two places where a lock is unlocked.
*/
-static void
+void
md_UnlockAndPostNotifies(
_MDLock *lock,
PRThread *waitThred,
@@ -163,7 +195,11 @@ md_UnlockAndPostNotifies(
}
/* Release the lock before notifying */
- DosReleaseMutexSem(lock->mutex);
+#ifdef USE_RAMSEM
+ SemReleasex86(&lock->mutex, 0);
+#else
+ DosReleaseMutexSem(lock->mutex);
+#endif
notified = &post; /* this is where we start */
do {
@@ -270,7 +306,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
md_UnlockAndPostNotifies(lock, thred, cv);
} else {
AddThreadToCVWaitQueueInternal(thred, cv);
+#ifdef USE_RAMSEM
+ SemReleasex86( &lock->mutex, 0 );
+#else
DosReleaseMutexSem(lock->mutex);
+#endif
}
/* Wait for notification or timeout; don't really care which */
@@ -279,7 +319,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
DosResetEventSem(thred->md.blocked_sema, &count);
}
+#ifdef USE_RAMSEM
+ SemRequest486(&(lock->mutex), -1);
+#else
DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT);
+#endif
PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT);
@@ -336,28 +380,41 @@ _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock)
PRStatus
_PR_MD_NEW_LOCK(_MDLock *lock)
{
+#ifdef USE_RAMSEM
+ // It's better if this API traps when pCriticalSect is not a valid
+ // pointer, because we can't return an error code and if we just return
+ // the API caller will have nasty bugs that are hard to find.
+
+ PRAMSEM pramsem = (PRAMSEM)(&(lock->mutex));
+ /* First time, set up addresses of processor specific functions
+ */
+ if (plisCurrent == NULL)
+ {
+ SEL selGlobal = 0, selLocal = 0;
+
+ /* Convert 16 bit global information segment to 32 bit address
+ * by performing CRMA on the 16 bit address: "shift" operation
+ * to convert sel to flat, "and" operation to mask the address
+ * to 32-bit
+ */
+ Dos16GetInfoSeg(&selGlobal, &selLocal);
+ plisCurrent = (PLINFOSEG)(((ULONG)selLocal << 13) &
+ (ULONG)0x1fff0000);
+
+ }
+
+ memset(pramsem, 0, sizeof(pramsem));
+ DosCreateEventSem(0, &pramsem->hevSem, DC_SEM_SHARED, 0);
+
+ lock->notified.length=0;
+ lock->notified.link=NULL;
+ return PR_SUCCESS;
+#else
DosCreateMutexSem(0, &(lock->mutex), 0, 0);
(lock)->notified.length=0;
(lock)->notified.link=NULL;
return PR_SUCCESS;
-}
-
-void
-_PR_MD_FREE_LOCK(_MDLock *lock)
-{
- DosCloseMutexSem(lock->mutex);
-}
-
-void _PR_MD_LOCK(_MDLock *lock)
-{
- DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT);
-}
-
-PRIntn
-_PR_MD_TEST_AND_LOCK(_MDLock *lock)
-{
- DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT);
- return 0;
+#endif
}
void
@@ -366,14 +423,3 @@ _PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock)
md_PostNotifyToCvar(cv, lock, PR_TRUE);
return;
}
-
-void
-_PR_MD_UNLOCK(_MDLock *lock)
-{
- if (0 != lock->notified.length) {
- md_UnlockAndPostNotifies(lock, NULL, NULL);
- } else {
- DosReleaseMutexSem(lock->mutex);
- }
- return;
-}
diff --git a/pr/src/md/os2/os2inrval.c b/pr/src/md/os2/os2inrval.c
index 469da314..5c112531 100644
--- a/pr/src/md/os2/os2inrval.c
+++ b/pr/src/md/os2/os2inrval.c
@@ -39,57 +39,22 @@
#include "primpl.h"
-ULONG _os2_ticksPerSec = -1;
-PRIntn _os2_bitShift = 0;
-PRInt32 _os2_highMask = 0;
-
-
void
_PR_MD_INTERVAL_INIT()
{
- if (DosTmrQueryFreq(&_os2_ticksPerSec) == NO_ERROR)
- {
- while(_os2_ticksPerSec > PR_INTERVAL_MAX) {
- _os2_ticksPerSec >>= 1;
- _os2_bitShift++;
- _os2_highMask = (_os2_highMask << 1)+1;
- }
- }
- else
- _os2_ticksPerSec = -1;
-
- PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN && _os2_ticksPerSec < PR_INTERVAL_MAX);
}
PRIntervalTime
_PR_MD_GET_INTERVAL()
{
- QWORD count;
-
- /* Sadly; nspr requires the interval to range from 1000 ticks per second
- * to only 100000 ticks per second; Counter is too high
- * resolution...
- */
- if (DosTmrQueryTime(&count) == NO_ERROR) {
- PRInt32 top = count.ulHi & _os2_highMask;
- top = top << (32 - _os2_bitShift);
- count.ulLo = count.ulLo >> _os2_bitShift;
- count.ulHi = count.ulLo + top;
- return (PRUint32)count.ulLo;
- }
- else{
- ULONG msCount = PR_FAILURE;
- DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount));
- return msCount;
- }
+ ULONG msCount = PR_FAILURE;
+ DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount));
+ return msCount;
}
PRIntervalTime
_PR_MD_INTERVAL_PER_SEC()
{
- if(_os2_ticksPerSec != -1)
- return _os2_ticksPerSec;
- else
- return 1000;
+ return 1000;
}
diff --git a/pr/src/md/os2/os2io.c b/pr/src/md/os2/os2io.c
index 12e2f2a2..acccf6a6 100644
--- a/pr/src/md/os2/os2io.c
+++ b/pr/src/md/os2/os2io.c
@@ -253,6 +253,12 @@ _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
return -1;
}
+ if (len != bytes) {
+ rv = ERROR_DISK_FULL;
+ _PR_MD_MAP_WRITE_ERROR(rv);
+ return -1;
+ }
+
return bytes;
} /* --- end _PR_MD_WRITE() --- */
diff --git a/pr/src/md/os2/os2misc.c b/pr/src/md/os2/os2misc.c
index be597fcd..c27b0614 100644
--- a/pr/src/md/os2/os2misc.c
+++ b/pr/src/md/os2/os2misc.c
@@ -118,107 +118,28 @@ PR_Now(void)
static int assembleCmdLine(char *const *argv, char **cmdLine)
{
char *const *arg;
- char *p, *q;
int cmdLineSize;
- int numBackslashes;
- int i;
- int argNeedQuotes;
/*
* Find out how large the command line buffer should be.
*/
cmdLineSize = 0;
- for (arg = argv; *arg; arg++) {
- /*
- * \ and " need to be escaped by a \. In the worst case,
- * every character is a \ or ", so the string of length
- * may double. If we quote an argument, that needs two ".
- * Finally, we need a space between arguments, a null between
- * the EXE name and the arguments, and 2 nulls at the end
- * of command line.
- */
- cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
- + 2 /* we quote every argument */
- + 4; /* space in between, or final nulls */
- }
- p = *cmdLine = PR_MALLOC(cmdLineSize);
- if (p == NULL) {
+ for (arg = argv+1; *arg; arg++) {
+ cmdLineSize += strlen(*arg) + 1; /* space in between, or final null */
+ }
+ *cmdLine = PR_MALLOC(cmdLineSize);
+ if (*cmdLine == NULL) {
return -1;
}
- for (arg = argv; *arg; arg++) {
- /* Add a space to separates the arguments */
- if (arg > argv + 1) {
- *p++ = ' ';
- }
- q = *arg;
- numBackslashes = 0;
- argNeedQuotes = 0;
-
- /* If the argument contains white space, it needs to be quoted. */
- if (strpbrk(*arg, " \f\n\r\t\v")) {
- argNeedQuotes = 1;
- }
-
- if (argNeedQuotes) {
- *p++ = '"';
- }
- while (*q) {
- if (*q == '\\') {
- numBackslashes++;
- q++;
- } else if (*q == '"') {
- if (numBackslashes) {
- /*
- * Double the backslashes since they are followed
- * by a quote
- */
- for (i = 0; i < 2 * numBackslashes; i++) {
- *p++ = '\\';
- }
- numBackslashes = 0;
- }
- /* To escape the quote */
- *p++ = '\\';
- *p++ = *q++;
- } else {
- if (numBackslashes) {
- /*
- * Backslashes are not followed by a quote, so
- * don't need to double the backslashes.
- */
- for (i = 0; i < numBackslashes; i++) {
- *p++ = '\\';
- }
- numBackslashes = 0;
- }
- *p++ = *q++;
- }
- }
+ (*cmdLine)[0] = '\0';
- /* Now we are at the end of this argument */
- if (numBackslashes) {
- /*
- * Double the backslashes if we have a quote string
- * delimiter at the end.
- */
- if (argNeedQuotes) {
- numBackslashes *= 2;
- }
- for (i = 0; i < numBackslashes; i++) {
- *p++ = '\\';
- }
+ for (arg = argv+1; *arg; arg++) {
+ if (arg > argv +1) {
+ strcat(*cmdLine, " ");
}
- if (argNeedQuotes) {
- *p++ = '"';
- }
- if(arg == argv)
- *p++ = '\0';
+ strcat(*cmdLine, *arg);
}
-
- /* Add 2 nulls at the end */
- *p++ = '\0';
- *p = '\0';
return 0;
}
@@ -308,129 +229,154 @@ static int compare(const void *arg1, const void *arg2)
{
return stricmp(* (char**)arg1, * (char**)arg2);
}
+
PRProcess * _PR_CreateOS2Process(
const char *path,
char *const *argv,
char *const *envp,
const PRProcessAttr *attr)
{
- char szFailed[CCHMAXPATH];
- RESULTCODES procInfo;
- APIRET retVal;
- char *cmdLine = NULL;
- char *envBlock = NULL;
- char **newEnvp;
- PRProcess *proc = NULL;
- HFILE hStdIn = 0,
- hStdOut = 0,
- hStdErr = 0;
- HFILE hStdInSave = -1,
- hStdOutSave = -1,
- hStdErrSave = -1;
-
- proc = PR_NEW(PRProcess);
- if (!proc) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- goto errorExit;
- }
-
- if (assembleCmdLine(argv, &cmdLine) == -1) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- goto errorExit;
- }
-
- if (envp == NULL) {
- newEnvp = NULL;
- } else {
- int i;
- int numEnv = 0;
- while (envp[numEnv]) {
- numEnv++;
- }
- newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *));
- for (i = 0; i <= numEnv; i++) {
- newEnvp[i] = envp[i];
- }
- qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
- }
- if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- goto errorExit;
- }
-
- if (attr) {
- /* On OS/2, there is really no way to pass file handles for stdin, stdout,
- * and stderr to a new process. Instead, we can make it a child process
- * and make the given file handles a copy of our stdin, stdout, and stderr.
- * The child process then inherits ours, and we set ours back. Twisted
- * and gross I know. If you know a better way, please use it.
- */
- if (attr->stdinFd) {
- hStdIn = 0;
- DosDupHandle(hStdIn, &hStdInSave);
- DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn);
- }
- if (attr->stdoutFd) {
- hStdOut = 1;
- DosDupHandle(hStdOut, &hStdOutSave);
- DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut);
+ PRProcess *proc = NULL;
+ char *cmdLine = NULL;
+ char **newEnvp;
+ char *envBlock = NULL;
+
+ STARTDATA startData = {0};
+ APIRET rc;
+ ULONG ulAppType = 0;
+ PID pid = 0;
+ char *pEnvWPS = NULL;
+ char *pszComSpec;
+ char pszEXEName[CCHMAXPATH] = "";
+ char pszFormatString[CCHMAXPATH];
+ char pszObjectBuffer[CCHMAXPATH];
+ char *pszFormatResult = NULL;
+
+ proc = PR_NEW(PRProcess);
+ if (!proc) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (assembleCmdLine(argv, &cmdLine) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (envp == NULL) {
+ newEnvp = NULL;
+ } else {
+ int i;
+ int numEnv = 0;
+ while (envp[numEnv]) {
+ numEnv++;
}
- if (attr->stderrFd) {
- hStdErr = 2;
- DosDupHandle(hStdErr, &hStdErrSave);
- DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr);
+ newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *));
+ for (i = 0; i <= numEnv; i++) {
+ newEnvp[i] = envp[i];
}
- }
-
- retVal = DosExecPgm(szFailed,
- CCHMAXPATH,
- EXEC_ASYNCRESULT,
- cmdLine,
- envBlock,
- &procInfo,
- argv[0]);
-
- /* Restore our old values. Hope this works */
- if(hStdInSave != -1){
- DosDupHandle(hStdInSave, &hStdIn);
- DosClose(hStdInSave);
- }
- if(hStdOutSave != -1){
- DosDupHandle(hStdOutSave, &hStdOut);
- DosClose(hStdOutSave);
- }
- if(hStdErrSave != -1){
- DosDupHandle(hStdErrSave, &hStdErr);
- DosClose(hStdErrSave);
- }
+ qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
+ }
+ if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (attr) {
+ PR_ASSERT(!"Not implemented");
+ }
- if (retVal != NO_ERROR) {
- /* XXX what error code? */
- PR_SetError(PR_UNKNOWN_ERROR, retVal);
+ rc = DosQueryAppType(path, &ulAppType);
+ if (rc != NO_ERROR) {
+ char *pszDot = strrchr(path, '.');
+ if (pszDot) {
+ /* If it is a CMD file, launch the users command processor */
+ if (!stricmp(pszDot, ".cmd")) {
+ rc = DosScanEnv("COMSPEC", &pszComSpec);
+ if (!rc) {
+ strcpy(pszFormatString, "/C %s %s");
+ strcpy(pszEXEName, pszComSpec);
+ ulAppType = FAPPTYP_WINDOWCOMPAT;
+ }
+ }
+ }
+ }
+ if (ulAppType == 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
goto errorExit;
- }
-
- proc->md.pid = procInfo.codeTerminate;
+ }
+
+ if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) {
+ startData.SessionType = SSF_TYPE_PM;
+ }
+ else if (ulAppType & FAPPTYP_WINDOWCOMPAT) {
+ startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
+ }
+ else {
+ startData.SessionType = SSF_TYPE_DEFAULT;
+ }
+
+ if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL))
+ {
+ strcpy(pszEXEName, "WINOS2.COM");
+ startData.SessionType = PROG_31_STDSEAMLESSVDM;
+ strcpy(pszFormatString, "/3 %s %s");
+ }
+
+ startData.InheritOpt = SSF_INHERTOPT_PARENT;
+
+ if (pszEXEName[0]) {
+ pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine));
+ sprintf(pszFormatResult, pszFormatString, path, cmdLine);
+ startData.PgmInputs = pszFormatResult;
+ } else {
+ strcpy(pszEXEName, path);
+ startData.PgmInputs = cmdLine;
+ }
+ startData.PgmName = pszEXEName;
+
+ startData.Length = sizeof(startData);
+ startData.Related = SSF_RELATED_INDEPENDENT;
+ startData.ObjectBuffer = pszObjectBuffer;
+ startData.ObjectBuffLen = CCHMAXPATH;
+ startData.Environment = envBlock;
+
+ rc = DosStartSession(&startData, &ulAppType, &pid);
+
+ if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ }
+
+ proc->md.pid = pid;
- PR_DELETE(cmdLine);
- if (envBlock) {
- PR_DELETE(envBlock);
- }
- return proc;
+ if (pszFormatResult) {
+ PR_DELETE(pszFormatResult);
+ }
+
+ PR_DELETE(cmdLine);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+ PR_DELETE(envBlock);
+ }
+ return proc;
errorExit:
- if (cmdLine) {
- PR_DELETE(cmdLine);
- }
- if (envBlock) {
- PR_DELETE(envBlock);
- }
- if (proc) {
- PR_DELETE(proc);
- }
- return NULL;
-
-} /* _PR_CreateWindowsProcess */
+ if (cmdLine) {
+ PR_DELETE(cmdLine);
+ }
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+ PR_DELETE(envBlock);
+ }
+ if (proc) {
+ PR_DELETE(proc);
+ }
+ return NULL;
+} /* _PR_CreateOS2Process */
PRStatus _PR_DetachOS2Process(PRProcess *process)
{
diff --git a/pr/src/md/os2/os2poll.c b/pr/src/md/os2/os2poll.c
index 12f199f6..da477b1b 100644
--- a/pr/src/md/os2/os2poll.c
+++ b/pr/src/md/os2/os2poll.c
@@ -37,54 +37,64 @@
*/
#ifdef XP_OS2_EMX
- #include <sys/time.h> /* For timeval. */
+ #include <sys/time.h> /* For timeval. */
#endif
#include "primpl.h"
-PRInt32 _PR_MD_PR_POLL(
- PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+#ifndef BSD_SELECT
+/* Utility functions called when using OS/2 select */
+
+PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
+{
+ int i;
+ PRBool isSet = PR_FALSE;
+
+ for( i = start; i < start+count; i++ )
+ {
+ if( socks[i] == osfd )
+ isSet = PR_TRUE;
+ }
+
+ return isSet;
+}
+#endif
+
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
{
- PRInt32 osfd;
- int maxfd = -1;
+#ifdef BSD_SELECT
fd_set rd, wt, ex;
+#else
+ int rd, wt, ex;
+ int* socks;
+ unsigned long msecs;
+ int i, j;
+#endif
PRFileDesc *bottom;
PRPollDesc *pd, *epd;
- PRInt32 ready, err;
- PRThread *me = _PR_MD_CURRENT_THREAD();
- struct timeval tv, *tvp = NULL;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
- /*
- * For restarting _MD_SELECT() if it is interrupted by a signal.
- * We use these variables to figure out how much time has elapsed
- * and how much of the timeout still remains.
- */
- PRIntervalTime start, elapsed, remaining;
+#ifdef BSD_SELECT
+ struct timeval tv, *tvp = NULL;
- if (_PR_PENDING_INTERRUPT(me))
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+#else
+ rd = 0;
+ wt = 0;
+ ex = 0;
+ socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
+
+ if (!socks)
{
- me->flags &= ~_PR_INTERRUPT;
- PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
return -1;
}
+#endif
- /*
- ** Is it an empty set? If so, just sleep for the timeout and return
- */
- if (0 == npds)
- {
- PR_Sleep(timeout);
- return 0;
- }
-
- remaining = timeout;
- start = PR_IntervalNow();
-
- FD_ZERO(&rd);
- FD_ZERO(&wt);
- FD_ZERO(&ex);
-
- ready = 0;
+ ready = 0;
for (pd = pds, epd = pd + npds; pd < epd; pd++)
{
PRInt16 in_flags_read = 0, in_flags_write = 0;
@@ -95,19 +105,17 @@ PRInt32 _PR_MD_PR_POLL(
if (pd->in_flags & PR_POLL_READ)
{
in_flags_read = (pd->fd->methods->poll)(
- pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE),
- &out_flags_read);
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
}
if (pd->in_flags & PR_POLL_WRITE)
{
in_flags_write = (pd->fd->methods->poll)(
- pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ),
- &out_flags_write);
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
}
- if ((0 != (in_flags_read & out_flags_read))
- || (0 != (in_flags_write & out_flags_write)))
+ if ((0 != (in_flags_read & out_flags_read)) ||
+ (0 != (in_flags_write & out_flags_write)))
{
- /* this one's ready right now (buffered input) */
+ /* this one's ready right now */
if (0 == ready)
{
/*
@@ -128,37 +136,67 @@ PRInt32 _PR_MD_PR_POLL(
else
{
pd->out_flags = 0; /* pre-condition */
+
/* make sure this is an NSPR supported stack */
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottom); /* what to do about that? */
- if ((NULL != bottom)
- && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ if ((NULL != bottom) &&
+ (_PR_FILEDESC_OPEN == bottom->secret->state))
{
if (0 == ready)
{
- osfd = bottom->secret->md.osfd;
- if (osfd > maxfd) maxfd = osfd;
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd)
+ maxfd = osfd;
if (in_flags_read & PR_POLL_READ)
{
pd->out_flags |= _PR_POLL_READ_SYS_READ;
+#ifdef BSD_SELECT
FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
}
if (in_flags_read & PR_POLL_WRITE)
{
pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+#ifdef BSD_SELECT
FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
}
if (in_flags_write & PR_POLL_READ)
{
pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+#ifdef BSD_SELECT
FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
}
if (in_flags_write & PR_POLL_WRITE)
{
pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+#ifdef BSD_SELECT
FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT)
+ {
+#ifdef BSD_SELECT
+ FD_SET(osfd, &ex);
+#else
+ socks[npds*2+ex] = osfd;
+ ex++;
+#endif
}
- if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
}
}
else
@@ -178,9 +216,19 @@ PRInt32 _PR_MD_PR_POLL(
}
}
- if (0 != ready) return ready; /* no need to block */
+ if (0 != ready)
+ {
+#ifndef BSD_SELECT
+ free(socks);
+#endif
+ return ready; /* no need to block */
+ }
+
+ remaining = timeout;
+ start = PR_IntervalNow();
retry:
+#ifdef BSD_SELECT
if (timeout != PR_INTERVAL_NO_TIMEOUT)
{
PRInt32 ticksPerSecond = PR_TicksPerSecond();
@@ -191,21 +239,50 @@ retry:
}
ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
- if (ready == -1 && errno == EINTR)
+#else
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT:
+ msecs = 0;
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ msecs = -1;
+ break;
+ default:
+ msecs = PR_IntervalToMilliseconds(remaining);
+ }
+
+ /* compact array */
+ for( i = rd, j = npds; j < npds+wt; i++,j++ )
+ socks[i] = socks[j];
+ for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
+ socks[i] = socks[j];
+
+ ready = _MD_SELECT(socks, rd, wt, ex, msecs);
+#endif
+
+ if (ready == -1 && errno == SOCEINTR)
{
- if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
- else
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ goto retry;
+ else
{
- elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
- if (elapsed > timeout) ready = 0; /* timed out */
- else
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout)
+ ready = 0; /* timed out */
+ else
{
- remaining = timeout - elapsed;
- goto retry;
+ remaining = timeout - elapsed;
+ goto retry;
}
- }
+ }
}
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
if (ready > 0)
{
ready = 0;
@@ -214,26 +291,44 @@ retry:
PRInt16 out_flags = 0;
if ((NULL != pd->fd) && (0 != pd->in_flags))
{
+ PRInt32 osfd;
bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottom);
osfd = bottom->secret->md.osfd;
+#ifdef BSD_SELECT
if (FD_ISSET(osfd, &rd))
+#else
+ if( IsSocketSet(osfd, socks, 0, rd) )
+#endif
{
if (pd->out_flags & _PR_POLL_READ_SYS_READ)
out_flags |= PR_POLL_READ;
if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
out_flags |= PR_POLL_WRITE;
- }
+ }
+
+#ifdef BSD_SELECT
if (FD_ISSET(osfd, &wt))
+#else
+ if( IsSocketSet(osfd, socks, rd, wt) )
+#endif
{
if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
out_flags |= PR_POLL_READ;
if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
out_flags |= PR_POLL_WRITE;
+ }
+
+#ifdef BSD_SELECT
+ if (FD_ISSET(osfd, &ex))
+#else
+ if( IsSocketSet(osfd, socks, rd+wt, ex) )
+#endif
+ {
+ out_flags |= PR_POLL_EXCEPT;
}
- if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
}
pd->out_flags = out_flags;
if (out_flags) ready++;
@@ -242,39 +337,42 @@ retry:
}
else if (ready < 0)
{
- err = _MD_ERRNO();
- if (err == EBADF)
+ err = _MD_ERRNO();
+ if (err == EBADF)
{
- /* Find the bad fds */
- ready = 0;
- for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ /* Find the bad fds */
+ int optval;
+ int optlen = sizeof(optval);
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
{
- int optval;
- int optlen = sizeof(optval);
- pd->out_flags = 0;
- if ((NULL == pd->fd) || (pd->in_flags == 0)) continue;
- bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
- if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
- SO_TYPE, (char *) &optval, &optlen) == -1)
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
{
- PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
- if (_MD_ERRNO() == ENOTSOCK)
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
{
- pd->out_flags = PR_POLL_NVAL;
- ready++;
+ PR_ASSERT(sock_errno() == SOCENOTSOCK);
+ if (sock_errno() == SOCENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
}
}
- }
- PR_ASSERT(ready > 0);
- }
- else
- {
- PR_ASSERT(err != EINTR); /* should have been handled above */
- _PR_MD_MAP_SELECT_ERROR(err);
+ }
+ PR_ASSERT(ready > 0);
}
- }
- return ready;
- }
+ else
+ _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+#ifndef BSD_SELECT
+ free(socks);
+#endif
+ return ready;
+}
#ifdef XP_OS2_EMX
HMTX thread_select_mutex = 0; /* because EMX's select is not thread safe - duh! */
diff --git a/pr/src/md/os2/os2sock.c b/pr/src/md/os2/os2sock.c
index 529e0e5a..ecdb31ff 100644
--- a/pr/src/md/os2/os2sock.c
+++ b/pr/src/md/os2/os2sock.c
@@ -46,9 +46,13 @@
#include "primpl.h"
#ifdef XP_OS2_EMX
- #include <sys/time.h> /* For timeval. */
+ #include <sys/time.h> /* For timeval. */
#endif
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+#define READ_FD 1
+#define WRITE_FD 2
+
void
_PR_MD_INIT_IO()
{
@@ -59,34 +63,19 @@ _PR_MD_INIT_IO()
PRInt32
-_PR_MD_SOCKET(int af, int type, int flags)
+_PR_MD_SOCKET(int domain, int type, int flags)
{
- int sock;
- PRUint32 one = 1;
- PRInt32 rv;
- PRInt32 err;
+ PRInt32 osfd, err;
- sock = socket(af, type, flags);
-
- if (sock == -1 )
- {
- int rv = sock_errno();
- soclose(sock);
- _PR_MD_MAP_SOCKET_ERROR(rv);
- return (PRInt32) -1;
- }
+ osfd = socket(domain, type, flags);
- /*
- ** Make the socket Non-Blocking
- */
- rv = ioctl( sock, FIONBIO, (char *) &one, sizeof(one));
- if ( rv != 0 )
+ if (osfd == -1)
{
err = sock_errno();
- return -1;
+ _PR_MD_MAP_SOCKET_ERROR(err);
}
- return (PRInt32)sock;
+ return(osfd);
}
/*
@@ -96,12 +85,13 @@ _PR_MD_SOCKET(int af, int type, int flags)
PRInt32
_MD_CloseSocket(PRInt32 osfd)
{
- PRInt32 rv = -1;
-
- rv = soclose((int) osfd );
- if (rv < 0)
- _PR_MD_MAP_SOCKET_ERROR(sock_errno());
+ PRInt32 rv, err;
+ rv = soclose(osfd);
+ if (rv == -1) {
+ err = sock_errno();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
return rv;
}
@@ -117,256 +107,276 @@ _MD_SocketAvailable(PRFileDesc *fd)
return result;
}
-PRInt32
-_MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
- PRIntervalTime timeout )
+static PRInt32
+socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
{
- PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv, err;
+ PRInt32 rv = -1;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
#ifdef BSD_SELECT
- fd_set rd;
- struct timeval tv, *tvp;
-
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
+ struct timeval tv;
+ fd_set rd_wr;
#else
int socks[1];
- socks[0] = osfd;
+ long lTimeout;
#endif
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- while ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
#ifdef BSD_SELECT
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
#else
- if ((rv = _MD_SELECT(socks, 1, 0, 0, -1)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ do {
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ else
+ rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
+#endif
+ if (rv == -1 && (syserror = sock_errno()) != SOCEINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
break;
- }
- }
- else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- break;
- }
- }
- return(rv);
- }
- else if (timeout == PR_INTERVAL_NO_WAIT)
- {
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- }
- else
- {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
- }
- return(rv);
- }
- else
- {
-retry:
- if ((rv = accept(osfd, (struct sockaddr *) raddr, (int *) rlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
#ifdef BSD_SELECT
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp);
+ FD_ZERO(&rd_wr);
+#endif
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+#ifdef BSD_SELECT
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
#else
- long lTimeout = PR_IntervalToMilliseconds(timeout);
- rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ wait_for_remaining = PR_TRUE;
+ lTimeout = PR_IntervalToMilliseconds(remaining);
+ if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+ wait_for_remaining = PR_FALSE;
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ }
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(socks, 1, 0, 0, lTimeout);
+ else
+ rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
#endif
- if (rv > 0) {
- goto retry;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = sock_errno()) != SOCEINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
rv = -1;
- } else {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ break;
}
- } else {
- _PR_MD_MAP_ACCEPT_ERROR(err);
- }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == SOCEINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+#ifdef BSD_SELECT
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+#else
+ now += PR_MillisecondsToInterval(lTimeout);
+#endif
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == SOCEINTR));
+ break;
}
- }
return(rv);
-} /* end _MD_Accept() */
+}
+PRInt32
+_MD_Accept(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1)
+ {
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK) || (err == SOCECONNABORTED))
+ {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+ return(rv);
+}
PRInt32
_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
PRIntervalTime timeout)
{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
PRInt32 osfd = fd->secret->md.osfd;
- PRInt32 rv;
- int err, len;
-#ifdef BSD_SELECT
-#ifdef XP_OS2//_VACPP
- fd_set wd;
-#else
- fd_set wd, ex;
-#endif #vacpp
- struct timeval tv, *tvp;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
+ /*
+ * We initiate the connection setup by making a nonblocking connect()
+ * call. If the connect() call fails, there are two cases we handle
+ * specially:
+ * 1. The connect() call was interrupted by a signal. In this case
+ * we simply retry connect().
+ * 2. The NSPR socket is nonblocking and connect() fails with
+ * EINPROGRESS. We first wait until the socket becomes writable.
+ * Then we try to find out whether the connection setup succeeded
+ * or failed.
+ */
+
+retry:
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1)
{
err = sock_errno();
- if ((!fd->secret->nonblocking) && ((err == EINPROGRESS) || (err == EWOULDBLOCK)))
- {
-#ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- tvp = NULL;
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
+
+ if (err == SOCEINTR) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
}
+ goto retry;
+ }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
-#ifdef XP_OS2//_VACPP
- rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp);
-#else
- FD_ZERO(&ex);
- FD_SET(osfd, &ex);
- rv = _MD_SELECT(osfd + 1, NULL, &wd, &ex, tvp);
-#endif #vacpp
-#else #!bsd_select
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- lTimeout = -1;
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
+ if (!fd->secret->nonblocking && (err == SOCEINPROGRESS))
+ {
+ /*
+ * socket_io_wait() may return -1 or 1.
+ */
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
}
-
- socks[0] = osfd;
-#ifdef XP_OS2//_VACPP
- rv = _MD_SELECT(socks, 0, 1, 0, lTimeout);
-#else
- rv = _MD_SELECT(socks, 0, 1, 1, lTimeout);
-#endif #vacpp
-#endif
- if (rv > 0)
- {
-#ifdef BSD_SELECT
-#ifdef XP_OS2//_VACPP
- if (FD_ISSET(osfd, &wd))
- {
- //DosSleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- if (err != 0)
- {
- _PR_MD_MAP_CONNECT_ERROR(err);
- return -1;
- }
- else
- return 0; /* it's connected */
- }
- else
- return -1;
-#else
- if (FD_ISSET(osfd, &ex))
- {
- DosSleep(0);
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
- if (err != 0)
- _PR_MD_MAP_CONNECT_ERROR(err);
- else
- PR_SetError(PR_UNKNOWN_ERROR, 0);
- return -1;
- }
- if (FD_ISSET(osfd, &wd))
- {
- /* it's connected */
- return 0;
- }
-#endif #vacpp
-#else #!bsd_select
- if (socks[0] == osfd)
- {
- len = sizeof(err);
- if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
- (char *) &err, &len) < 0)
- {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return -1;
- }
-
- if (err != 0)
- {
- _PR_MD_MAP_CONNECT_ERROR(err);
- return -1;
- }
- else
- return 0; /* it's connected */
- }
- else
- return -1;
-#endif
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
}
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return(-1);
- } else if (rv < 0)
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return(-1);
+ err = _MD_os2_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
}
- }
+ return 0;
+ }
+
_PR_MD_MAP_CONNECT_ERROR(err);
}
- return rv;
-}
+ return rv;
+} /* _MD_connect */
PRInt32
_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
{
- PRInt32 rv;
-
- rv = bind(fd->secret->md.osfd, (struct sockaddr*) &(addr->inet), addrlen);
+ PRInt32 rv, err;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+ return(rv);
+}
- if (rv == -1) {
- _PR_MD_MAP_BIND_ERROR(sock_errno());
- return -1;
- }
- return 0;
+PRInt32
+_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv, err;
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_DEFAULT_ERROR(err);
+ }
+ return(rv);
}
@@ -376,70 +386,27 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- int osflags;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- if (0 == flags) {
- osflags = 0;
- } else {
- PR_ASSERT(PR_MSG_PEEK == flags);
- osflags = MSG_PEEK;
- }
- while ((rv = recv( osfd, buf, amount, osflags)) == -1)
+ while ((rv = recv(osfd,buf,amount,flags)) == -1)
{
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
-#else
- socks[0] = osfd;
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1)
-#endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- }
- else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
break;
}
- }
- else
- {
- _PR_MD_MAP_RECV_ERROR(err);
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
- } /* end while() */
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+done:
return(rv);
}
@@ -449,108 +416,42 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
- PRInt32 bytesSent = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while(bytesSent < amount )
+ while ((rv = send(osfd,buf,amount,flags)) == -1)
{
- while ((rv = send( osfd, (char *) buf, amount, 0 )) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SEND_ERROR(err);
- return -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
}
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
- if ((rv >= 0) && (bytesSent < amount ))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 0, 1, 0,lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
+ }
+
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next send() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT))
+ {
+ if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
+ rv = -1;
+ goto done;
}
}
- return bytesSent;
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -559,109 +460,29 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- PRInt32 bytesSent = 0;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set wd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
-
- while(bytesSent < amount)
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1)
{
- while ((rv = sendto( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- addrlen)) == -1)
- {
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- break;
- }
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
- }
- else {
- _PR_MD_MAP_SENDTO_ERROR(err);
- return -1;
- }
- }
- bytesSent += rv;
- if (fd->secret->nonblocking)
- {
- break;
- }
- if ((rv >= 0) && (bytesSent < amount ))
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK))
{
-#ifdef BSD_SELECT
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&wd);
- FD_SET(osfd, &wd);
- if ((rv = _MD_SELECT( osfd + 1, NULL, &wd, NULL, tvp)) == -1) {
-#else
- if ( timeout == PR_INTERVAL_NO_TIMEOUT )
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT( socks, 0, 1, 0, lTimeout)) == -1) {
-#endif
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
+ if (fd->secret->nonblocking) {
break;
}
- if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- return -1;
- }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
}
}
- return bytesSent;
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -670,103 +491,86 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
{
PRInt32 osfd = fd->secret->md.osfd;
PRInt32 rv, err;
- PRUint32 addrlen_temp = *addrlen;
-#ifdef BSD_SELECT
- struct timeval tv, *tvp;
- fd_set rd;
-#else
- int socks[1];
- long lTimeout = -1;
-#endif
+ PRThread *me = _PR_MD_CURRENT_THREAD();
- while ((rv = recvfrom( osfd, (char *) buf, amount, 0, (struct sockaddr *) addr,
- (int *) addrlen)) == -1)
+ while( (*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, (int *)addrlen)) == -1))
{
- if (((err = sock_errno()) == EWOULDBLOCK)
- && (!fd->secret->nonblocking))
- {
-#ifdef BSD_SELECT
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- tvp = NULL;
- }
- else
- {
- tv.tv_sec = PR_IntervalToSeconds(timeout);
- tv.tv_usec = PR_IntervalToMicroseconds(
- timeout - PR_SecondsToInterval(tv.tv_sec));
- tvp = &tv;
- }
- FD_ZERO(&rd);
- FD_SET(osfd, &rd);
- if ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, tvp)) == -1)
-#else
- if (timeout == PR_INTERVAL_NO_TIMEOUT)
- {
- lTimeout = -1;
- }
- else
- {
- lTimeout = PR_IntervalToMilliseconds(timeout);
- }
- socks[0] = osfd;
- if ((rv = _MD_SELECT(socks, 1, 0, 0, lTimeout)) == -1)
-#endif
- {
- _PR_MD_MAP_SELECT_ERROR(sock_errno());
- return -1;
- } else if (rv == 0)
- {
- PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
- rv = -1;
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
break;
}
-
- /* recvfrom blows this value away if it fails first time */
- *addrlen = addrlen_temp;
- }
- else
- {
- _PR_MD_MAP_RECVFROM_ERROR(err);
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == SOCEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
break;
}
}
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+done:
return(rv);
}
PRInt32
-_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout)
{
- int index;
- int sent = 0;
- int rv;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
- for (index=0; index < iov_size; index++)
- {
- rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
- if (rv > 0)
- sent += rv;
- if ( rv != iov[index].iov_len )
- {
- if (rv < 0)
- {
- if (fd->secret->nonblocking
- && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
- && (sent > 0))
- {
- return sent;
- }
- else
- {
- return -1;
- }
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
+ err = sock_errno();
+ if ((err == SOCEWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
}
- /* Only a nonblocking socket can have partial sends */
- PR_ASSERT(fd->secret->nonblocking);
- return sent;
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
}
}
- return sent;
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
+ return(rv);
}
PRInt32
@@ -781,63 +585,77 @@ _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
}
PRStatus
-_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getsockname((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKNAME_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getpeername((int)fd->secret->md.osfd, (struct sockaddr *)addr, (int *) len);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETPEERNAME_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ char* optval, PRInt32* optlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = getsockopt((int)fd->secret->md.osfd, level, optname, optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_GETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
PRStatus
-_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ const char* optval, PRInt32 optlen)
{
- PRInt32 rv;
+ PRInt32 rv, err;
- rv = setsockopt((int)fd->secret->md.osfd, level, optname, (char *) optval, optlen);
- if (rv==0)
- return PR_SUCCESS;
- else {
- _PR_MD_MAP_SETSOCKOPT_ERROR(sock_errno());
- return PR_FAILURE;
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
}
+ return rv==0?PR_SUCCESS:PR_FAILURE;
}
void
-_MD_MakeNonblock(PRFileDesc *f)
+_MD_MakeNonblock(PRFileDesc *fd)
{
- return; /* do nothing! */
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 err;
+ PRUint32 one = 1;
+
+ if (osfd <= 2) {
+ /* Don't mess around with stdin, stdout or stderr */
+ return;
+ }
+
+ err = ioctl( osfd, FIONBIO, (char *) &one, sizeof(one));
+ if ( err != 0 )
+ {
+ err = sock_errno();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
}
diff --git a/pr/src/md/os2/os2thred.c b/pr/src/md/os2/os2thred.c
index d64ae0b9..f05be463 100644
--- a/pr/src/md/os2/os2thred.c
+++ b/pr/src/md/os2/os2thred.c
@@ -127,7 +127,15 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
if(thread->md.handle == -1) {
return PR_FAILURE;
}
- _PR_MD_SET_PRIORITY(&(thread->md), priority);
+
+ /*
+ * On OS/2, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL
+ */
+
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
return PR_SUCCESS;
}
diff --git a/pr/src/md/os2/os2vacpp.asm b/pr/src/md/os2/os2vacpp.asm
index 2581323b..6b49e407 100644
--- a/pr/src/md/os2/os2vacpp.asm
+++ b/pr/src/md/os2/os2vacpp.asm
@@ -30,59 +30,230 @@ COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
GPL.
Windows uses inline assembly for their atomic functions, so we have
- created an assembly file for VACPP on OS/2
+ created an assembly file for VACPP on OS/2.
+
+ This assembly file also contains an implementation of RAM semaphores.
+
+ Notes:
+ The ulTIDPID element of the RAMSEM structure is overloaded in the 386
+ implementation to hold the TID:PID in the lower 31 bits and the lock
+ bit in the high bit
|
+ page ,132
.486P
- .MODEL FLAT, OPTLINK
- .STACK
+ ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT
+
+ EXTRN Dos32PostEventSem:PROC
+ EXTRN Dos32WaitEventSem:PROC
+ EXTRN Dos32ResetEventSem:PROC
+
+ramsem STRUC
+ ramsem_ulTIDPID DD ?
+ ramsem_hevSem DD ?
+ ramsem_cLocks DD ?
+ ramsem_cWaiting DW ?
+ ramsem_cPosts DW ?
+ramsem ENDS
+
+ERROR_SEM_TIMEOUT equ 121
+ERROR_NOT_OWNER equ 288
+SEM_RELEASE_UNOWNED equ 1
+SEM_RELEASE_ALL equ 2
+TS_LOCKBIT equ 31
+
+
+DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
+
+ EXTRN plisCurrent:DWORD
+
+DATA ENDS
+
+CODE32 SEGMENT USE32 PUBLIC 'CODE'
+
+ PUBLIC SemRequest486
+ PUBLIC SemReleasex86
+
+ PUBLIC _PR_MD_ATOMIC_SET
+ PUBLIC _PR_MD_ATOMIC_ADD
+ PUBLIC _PR_MD_ATOMIC_INCREMENT
+ PUBLIC _PR_MD_ATOMIC_DECREMENT
+
+;;;---------------------------------------------------------------------------
+;;; APIRET _Optlink SemRequest(PRAMSEM pramsem, ULONG ulTimeout);
+;;;
+;;; Registers:
+;;; EAX - packed TID:PID word
+;;; ECX - address of RAMSEM structure
+;;; EDX - length of timeout in milli-seconds
+;;;---------------------------------------------------------------------------
+
+ ALIGN 10H
+SemRequest486 PROC
+ push ebx ; Save ebx (volatile)
+ mov ecx, eax ; PRAMSEM must be in ecx,
+ ; not eax, for cmpxchg
+
+ mov ebx, dword ptr [plisCurrent]
+ mov eax, dword ptr [ebx+4] ; Place thread id in high
+ ; word, process id in low
+ mov ax, word ptr [ebx] ; word
+ mov ebx,eax
+
+req486_test:
+ xor eax,eax
+ cmp (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx ; If we own the sem, just
+ jz short req486_inc_exit ; increment the use count
+
+ lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag
+
+; lock ; Uncomment for SMP
+ DB 0F0h
+; cmpxchg (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx
+; (byte 3 is the offset of ulProcessThread into the RAMSEM structure)
+ DB 00Fh
+ DB 0B1h
+ DB 019h
+ jnz short req486_sleep
+
+req486_inc_exit:
+ lock inc (ramsem PTR [ecx]).ramsem_cLocks
+
+req486_exit:
+ pop ebx ; Restore ebx
+ ret
+
+req486_sleep:
+ push ecx ; Save ecx (volatile)
+ push edx ; Save edx (volatile)
+ push edx ; timeout
+ push (ramsem PTR [ecx]).ramsem_hevSem
+ call Dos32WaitEventSem
+ add esp, 8
+ pop edx ; restore edx
+ pop ecx ; restore ecx
+ or eax, eax
+ jne req486_exit ; Exit, if error
- .CODE
+ push ecx ; Save ecx (volatile)
+ push edx ; Save edx (volatile)
+ sub esp, 4 ; Use stack space for
+ push esp ; dummy pulPostCt
+ push (ramsem PTR [ecx]).ramsem_hevSem
+ call Dos32ResetEventSem
+ add esp, 12
+ pop edx ; restore edx
+ pop ecx ; restore ecx
+ jmp req486_test ; Retry the semaphore
+
+SemRequest486 ENDP
+
+;;;---------------------------------------------------------------------
+;;; APIRET _Optlink SemReleasex86(PRAMSEM pramsem, ULONG flFlags);
+;;;
+;;; Registers:
+;;; EAX - address of RAMSEM structure
+;;; ECX - temporary variable
+;;; EDX - flags
+;;;---------------------------------------------------------------------
+
+ ALIGN 10H
+SemReleasex86 PROC
+ test edx, SEM_RELEASE_UNOWNED ; If set, don't bother
+ jnz short rel_ownerok ; getting/checking PID/TID
+
+ push ebx ; Save ebx (volatile)
+ mov ebx, dword ptr [plisCurrent]
+ mov ecx, dword ptr [ebx+4] ; Place thread id in high
+ ; word, process id in low
+ mov cx, word ptr [ebx] ; word
+ pop ebx ; Restore ebx
+
+ sub ecx, (ramsem PTR [eax]).ramsem_ulTIDPID ; This thread the owner?
+ shl ecx,1 ; Don't compare top bit
+ jnz short rel_notowner
+
+rel_ownerok:
+ test edx, SEM_RELEASE_ALL
+ jnz short rel_clear
+
+ lock dec (ramsem PTR [eax]).ramsem_cLocks
+ jnz short rel_exit
+
+rel_disown:
+ mov (ramsem PTR [eax]).ramsem_ulTIDPID, 0
+
+ lock inc (ramsem PTR [eax]).ramsem_cPosts
+ mov cx, (ramsem PTR [eax]).ramsem_cWaiting
+ cmp (ramsem PTR [eax]).ramsem_cPosts, cx
+ jne short rel_post
+
+rel_exit:
+ xor eax, eax
+ ret
+
+rel_clear:
+ lock mov (ramsem PTR [eax]).ramsem_cLocks,0
+ jmp rel_disown
+
+rel_notowner:
+ mov eax, ERROR_NOT_OWNER
+ ret
+
+rel_post:
+ mov (ramsem PTR [eax]).ramsem_cPosts, cx
+ push (ramsem PTR [eax]).ramsem_hevSem
+ call Dos32PostEventSem
+ add esp,4
+ xor eax,eax
+ ret
+SemReleasex86 ENDP
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval)
;;;---------------------------------------------------------------------
-_PR_MD_ATOMIC_SET PROC OPTLINK EXPORT
- lock xchg dword ptr [eax],edx
+ ALIGN 10H
+_PR_MD_ATOMIC_SET proc
+ lock xchg dword ptr [eax],edx
mov eax, edx;
-
ret
_PR_MD_ATOMIC_SET endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val)
;;;---------------------------------------------------------------------
-_PR_MD_ATOMIC_ADD PROC OPTLINK EXPORT
+ ALIGN 10H
+_PR_MD_ATOMIC_ADD proc
mov ecx, edx
lock xadd dword ptr [eax], edx
mov eax, edx
add eax, ecx
-
ret
_PR_MD_ATOMIC_ADD endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val)
;;;---------------------------------------------------------------------
-_PR_MD_ATOMIC_INCREMENT PROC OPTLINK EXPORT
+ ALIGN 10H
+_PR_MD_ATOMIC_INCREMENT proc
mov edx, 1
lock xadd dword ptr [eax], edx
mov eax, edx
inc eax
-
ret
_PR_MD_ATOMIC_INCREMENT endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val)
;;;---------------------------------------------------------------------
-_PR_MD_ATOMIC_DECREMENT PROC OPTLINK EXPORT
+ ALIGN 10H
+_PR_MD_ATOMIC_DECREMENT proc
mov edx, 0ffffffffh
lock xadd dword ptr [eax], edx
mov eax, edx
dec eax
-
ret
_PR_MD_ATOMIC_DECREMENT endp
- END
+CODE32 ENDS
+END
diff --git a/pr/src/md/unix/darwin.c b/pr/src/md/unix/darwin.c
index 43988b8d..90179feb 100644
--- a/pr/src/md/unix/darwin.c
+++ b/pr/src/md/unix/darwin.c
@@ -103,32 +103,5 @@ _MD_CREATE_THREAD(
}
#endif /* ! _PR_PTHREADS */
-#if defined(_PR_PTHREADS)
-
-/*
-** Stubs for unimplemented functions
-*/
-
-int pthread_condattr_init(pthread_condattr_t *attr)
-{
- return 0;
-}
-
-int pthread_kill(pthread_t thread, int sig)
-{
- return ENOSYS;
-}
-
-typedef struct siginfo_t siginfo_t;
-
-int sigtimedwait(const sigset_t *set, siginfo_t *info,
- const struct timespec *timeout)
-{
- errno = ENOSYS;
- return -1;
-}
-
-#endif /* _PR_PTHREADS */
-
/* darwin.c */
diff --git a/pr/src/md/unix/irix.c b/pr/src/md/unix/irix.c
index 7ba079f8..f3d52f01 100644
--- a/pr/src/md/unix/irix.c
+++ b/pr/src/md/unix/irix.c
@@ -1451,7 +1451,7 @@ void _MD_EarlyInit(void)
_MD_IrixIntervalInit();
} /* _MD_EarlyInit */
-void _MD_IrixInit()
+void _MD_IrixInit(void)
{
#if !defined(_PR_PTHREADS)
struct sigaction sigact;
@@ -1567,7 +1567,7 @@ static PRUint32 pr_ticks_per_second = 0;
extern PRIntervalTime _PR_UNIX_GetInterval(void);
extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
-static void _MD_IrixIntervalInit()
+static void _MD_IrixIntervalInit(void)
{
/*
* As much as I would like, the service available through this
@@ -1634,12 +1634,12 @@ static void _MD_IrixIntervalInit()
}
} /* _MD_IrixIntervalInit */
-PRIntervalTime _MD_IrixIntervalPerSec()
+PRIntervalTime _MD_IrixIntervalPerSec(void)
{
return pr_ticks_per_second;
}
-PRIntervalTime _MD_IrixGetInterval()
+PRIntervalTime _MD_IrixGetInterval(void)
{
if (mmem_fd != -1)
{
diff --git a/pr/src/md/unix/unix.c b/pr/src/md/unix/unix.c
index 69153f27..704fa11a 100644
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -514,6 +514,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
struct timeval tv;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRInt32 syserror;
fd_set rd_wr;
@@ -558,8 +559,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* so that there is an upper limit on the delay
* before the interrupt bit is checked.
*/
+ wait_for_remaining = PR_TRUE;
tv.tv_sec = PR_IntervalToSeconds(remaining);
if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
tv.tv_usec = 0;
} else {
@@ -596,8 +599,12 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* PR_IntervalNow() call.
*/
if (rv == 0) {
- now += PR_SecondsToInterval(tv.tv_sec)
- + PR_MicrosecondsToInterval(tv.tv_usec);
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
} else {
now = PR_IntervalNow();
}
@@ -625,6 +632,7 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
int msecs;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRInt32 syserror;
struct pollfd pfd;
@@ -682,8 +690,10 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* so that there is an upper limit on the delay
* before the interrupt bit is checked.
*/
+ wait_for_remaining = PR_TRUE;
msecs = PR_IntervalToMilliseconds(remaining);
if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+ wait_for_remaining = PR_FALSE;
msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
}
rv = _MD_POLL(&pfd, 1, msecs);
@@ -719,7 +729,11 @@ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
* PR_IntervalNow() call.
*/
if (rv == 0) {
- now += PR_MillisecondsToInterval(msecs);
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_MillisecondsToInterval(msecs);
+ }
} else {
now = PR_IntervalNow();
}
@@ -2713,6 +2727,28 @@ static void* _MD_Unix_mmap64(
} /* _MD_Unix_mmap64 */
#endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */
+#if defined(OSF1) && defined(__GNUC__)
+
+/*
+ * On OSF1 V5.0A, <sys/stat.h> defines stat and fstat as
+ * macros when compiled under gcc, so it is rather tricky to
+ * take the addresses of the real functions the macros expend
+ * to. A simple solution is to define forwarder functions
+ * and take the addresses of the forwarder functions instead.
+ */
+
+static int stat_forwarder(const char *path, struct stat *buffer)
+{
+ return stat(path, buffer);
+}
+
+static int fstat_forwarder(int filedes, struct stat *buffer)
+{
+ return fstat(filedes, buffer);
+}
+
+#endif
+
static void _PR_InitIOV(void)
{
#if defined(SOLARIS2_5)
@@ -2757,8 +2793,13 @@ static void _PR_InitIOV(void)
#elif defined(_PR_HAVE_LARGE_OFF_T)
_md_iovector._open64 = open;
_md_iovector._mmap64 = mmap;
+#if defined(OSF1) && defined(__GNUC__)
+ _md_iovector._fstat64 = fstat_forwarder;
+ _md_iovector._stat64 = stat_forwarder;
+#else
_md_iovector._fstat64 = fstat;
_md_iovector._stat64 = stat;
+#endif
_md_iovector._lseek64 = lseek;
#else
#error "I don't know yet"
@@ -3221,9 +3262,6 @@ int _MD_unix_get_nonblocking_connect_error(int osfd)
int err;
_PRSockLen_t optlen = sizeof(err);
- printf("_MD_unix_get_nonblocking_connect_error: "
- "Assuming Large TCP/IP Stack -REVISIT- Never Tested!\n");
-
if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
(char *) &err, &optlen) == -1) {
return errno;
diff --git a/pr/src/md/unix/unix_errors.c b/pr/src/md/unix/unix_errors.c
index 1ce52e68..15b423cb 100644
--- a/pr/src/md/unix/unix_errors.c
+++ b/pr/src/md/unix/unix_errors.c
@@ -847,3 +847,10 @@ void _MD_solaris_map_sendfile_error(int err)
_MD_unix_map_default_error(err) ;
}
#endif /* SOLARIS */
+
+#ifdef LINUX
+void _MD_linux_map_sendfile_error(int err)
+{
+ _MD_unix_map_default_error(err) ;
+}
+#endif /* LINUX */
diff --git a/pr/src/md/unix/uxproces.c b/pr/src/md/unix/uxproces.c
index 58b5ab8a..d469f1c4 100644
--- a/pr/src/md/unix/uxproces.c
+++ b/pr/src/md/unix/uxproces.c
@@ -802,7 +802,7 @@ static void pr_InstallSigchldHandler()
#endif /* !defined(_PR_NATIVE_THREADS) */
-static PRStatus _MD_InitProcesses()
+static PRStatus _MD_InitProcesses(void)
{
#if !defined(_PR_NATIVE_THREADS)
int rv;
diff --git a/pr/src/md/unix/uxrng.c b/pr/src/md/unix/uxrng.c
index 64358289..6add3bf1 100644
--- a/pr/src/md/unix/uxrng.c
+++ b/pr/src/md/unix/uxrng.c
@@ -64,6 +64,18 @@ GetHighResClock(void *buf, size_t maxbytes)
#elif defined(HPUX)
+#ifdef __ia64
+#include <ia64/sys/inline.h>
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ PRUint64 t;
+
+ t = _Asm_mov_from_ar(_AREG44);
+ return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+#else
static size_t
GetHighResClock(void *buf, size_t maxbytes)
{
@@ -73,6 +85,7 @@ GetHighResClock(void *buf, size_t maxbytes)
cr16val = ret_cr16();
return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)));
}
+#endif
#elif defined(OSF1)
@@ -88,7 +101,11 @@ GetHighResClock(void *buf, size_t maxbytes)
{
unsigned long t;
+#ifdef __GNUC__
+ __asm__("rpcc %0" : "=r" (t));
+#else
t = asm("rpcc %v0");
+#endif
return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
}
@@ -210,7 +227,7 @@ static size_t GetHighResClock(void *buf, size_t maxbuf)
}
iotimer_addr = (unsigned *)
mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
- if (iotimer_addr == (void*)-1) {
+ if (iotimer_addr == (unsigned*)-1) {
close(mfd);
iotimer_addr = NULL;
return 0;
diff --git a/pr/src/md/unix/uxshm.c b/pr/src/md/unix/uxshm.c
index 888cbe04..81aa7487 100644
--- a/pr/src/md/unix/uxshm.c
+++ b/pr/src/md/unix/uxshm.c
@@ -118,7 +118,7 @@ extern PRSharedMemory * _MD_OpenSharedMemory(
PR_DELETE( shm );
return( NULL );
}
- if ( close(osfd == -1 )) {
+ if ( close(osfd) == -1 ) {
_PR_MD_MAP_CLOSE_ERROR( errno );
PR_FREEIF( shm->ipcname );
PR_DELETE( shm );
@@ -243,7 +243,7 @@ extern PRStatus _MD_DeleteSharedMemory( const char *name )
_PR_MD_MAP_OPEN_ERROR( errno );
return( PR_FAILURE );
}
- if ( close(osfd == -1 )) {
+ if ( close(osfd) == -1 ) {
_PR_MD_MAP_CLOSE_ERROR( errno );
return( PR_FAILURE );
}
@@ -311,7 +311,6 @@ extern PRSharedMemory * _MD_OpenSharedMemory(
)
{
PRStatus rc = PR_SUCCESS;
- PRIntn id;
PRInt32 end;
PRSharedMemory *shm;
char ipcname[PR_IPC_NAME_SIZE];
diff --git a/pr/src/md/windows/Makefile.in b/pr/src/md/windows/Makefile.in
index 283fa4a4..d9dce1d0 100644
--- a/pr/src/md/windows/Makefile.in
+++ b/pr/src/md/windows/Makefile.in
@@ -105,3 +105,11 @@ include $(topsrcdir)/config/rules.mk
export:: $(TARGETS)
+# Bug 122433 workaround: disable global optimization (-Og-) on ntio.c.
+ifdef BUILD_OPT
+ifeq ($(OS_TARGET), WINNT)
+$(OBJDIR)/ntio.$(OBJ_SUFFIX): ntio.c
+ @$(MAKE_OBJDIR)
+ $(CC) -Fo$@ -c $(CFLAGS) -Og- $<
+endif
+endif
diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c
index 9c3e2baf..1c3fb531 100644
--- a/pr/src/md/windows/ntthread.c
+++ b/pr/src/md/windows/ntthread.c
@@ -238,6 +238,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
}
thread->md.id = thread->id;
+ /*
+ * On windows, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL.
+ */
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
/* Activate the thread */
if ( ResumeThread( thread->md.handle ) != -1)
diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c
index d36ffdcd..58944703 100644
--- a/pr/src/md/windows/w95sock.c
+++ b/pr/src/md/windows/w95sock.c
@@ -168,7 +168,6 @@ PRInt32
_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
{
PRInt32 rv;
- int one = 1;
rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
@@ -180,6 +179,20 @@ _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
return 0;
}
+PRInt32
+_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+
+ if (rv == SOCKET_ERROR) {
+ _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
PRInt32
_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
@@ -461,6 +474,7 @@ static PRInt32 socket_io_wait(
struct timeval tv;
PRThread *me = _PR_MD_CURRENT_THREAD();
PRIntervalTime elapsed, remaining;
+ PRBool wait_for_remaining;
fd_set rd_wr, ex;
int err, len;
@@ -547,8 +561,10 @@ static PRInt32 socket_io_wait(
* so that there is an upper limit on the delay
* before the interrupt bit is checked.
*/
+ wait_for_remaining = PR_TRUE;
tv.tv_sec = PR_IntervalToSeconds(remaining);
if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
tv.tv_usec = 0;
} else {
@@ -618,8 +634,12 @@ static PRInt32 socket_io_wait(
*/
if (rv == 0 )
{
- elapsed = PR_SecondsToInterval(tv.tv_sec)
- + PR_MicrosecondsToInterval(tv.tv_usec);
+ if (wait_for_remaining) {
+ elapsed = remaining;
+ } else {
+ elapsed = PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
if (elapsed >= remaining) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
rv = -1;
diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c
index a70f1620..f8a70043 100644
--- a/pr/src/md/windows/w95thred.c
+++ b/pr/src/md/windows/w95thred.c
@@ -131,7 +131,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
}
thread->md.id = thread->id;
- _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ /*
+ * On windows, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL.
+ */
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
/* Activate the thread */
if ( ResumeThread( thread->md.handle ) != -1)
diff --git a/pr/src/misc/pralarm.c b/pr/src/misc/pralarm.c
index 488ce5a4..90c06442 100644
--- a/pr/src/misc/pralarm.c
+++ b/pr/src/misc/pralarm.c
@@ -180,7 +180,7 @@ static void PR_CALLBACK pr_alarmNotifier(void *arg)
} /* pr_alarm_notifier */
-PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm()
+PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm(void)
{
PRAlarm *alarm = PR_NEWZAP(PRAlarm);
if (alarm != NULL)
diff --git a/pr/src/misc/prdtoa.c b/pr/src/misc/prdtoa.c
index e2e715fe..7f0b9cf6 100644
--- a/pr/src/misc/prdtoa.c
+++ b/pr/src/misc/prdtoa.c
@@ -1180,6 +1180,16 @@ void _PR_InitDtoa(void)
p5s_lock = PR_NewLock();
}
+void _PR_CleanupDtoa(void)
+{
+ PR_DestroyLock(freelist_lock);
+ freelist_lock = NULL;
+ PR_DestroyLock(p5s_lock);
+ p5s_lock = NULL;
+
+ /* FIXME: deal with freelist and p5s. */
+}
+
#if defined(HAVE_WATCOM_BUG_1)
PRFloat64 __pascal __loadds __export
#else
diff --git a/pr/src/misc/prenv.c b/pr/src/misc/prenv.c
index 75af10fb..fdcfb017 100644
--- a/pr/src/misc/prenv.c
+++ b/pr/src/misc/prenv.c
@@ -59,7 +59,7 @@ static PRLock *_pr_envLock = NULL;
/************************************************************************/
-void _PR_InitEnv()
+void _PR_InitEnv(void)
{
_PR_NEW_LOCK_ENV();
}
diff --git a/pr/src/misc/prerr.c b/pr/src/misc/prerr.c
index 68bcc6ce..be24aff7 100644
--- a/pr/src/misc/prerr.c
+++ b/pr/src/misc/prerr.c
@@ -119,6 +119,6 @@ static const struct PRErrorMessage text[] = {
static const struct PRErrorTable et = { text, "prerr", -6000L, 75 };
-void nspr_InitializePRErrorTable() {
+void nspr_InitializePRErrorTable(void) {
PR_ErrorInstallTable(&et);
}
diff --git a/pr/src/misc/prerror.c b/pr/src/misc/prerror.c
index 8456d9d2..6e0d5f19 100644
--- a/pr/src/misc/prerror.c
+++ b/pr/src/misc/prerror.c
@@ -37,13 +37,13 @@
#include <string.h>
#include <stdlib.h>
-PR_IMPLEMENT(PRErrorCode) PR_GetError()
+PR_IMPLEMENT(PRErrorCode) PR_GetError(void)
{
PRThread *thread = PR_GetCurrentThread();
return thread->errorCode;
}
-PR_IMPLEMENT(PRInt32) PR_GetOSError()
+PR_IMPLEMENT(PRInt32) PR_GetOSError(void)
{
PRThread *thread = PR_GetCurrentThread();
return thread->osErrorCode;
diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c
index 6da27fa0..e512f1e0 100644
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -161,7 +161,7 @@ static void _pr_SetNativeThreadsOnlyMode(void)
#endif
#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
-extern PRStatus _pr_init_ipv6();
+extern PRStatus _pr_init_ipv6(void);
#endif
static void _PR_InitStuff(void)
@@ -169,6 +169,9 @@ static void _PR_InitStuff(void)
if (_pr_initialized) return;
_pr_initialized = PR_TRUE;
+#ifdef _PR_ZONE_ALLOCATOR
+ _PR_InitZones();
+#endif
#ifdef WINNT
_pr_SetNativeThreadsOnlyMode();
#endif
@@ -220,10 +223,6 @@ static void _PR_InitStuff(void)
_PR_InitCPUs();
#endif
-#ifdef _PR_ZONE_ALLOCATOR
- _PR_InitZones();
-#endif
-
/*
* XXX: call _PR_InitMem only on those platforms for which nspr implements
* malloc, for now.
@@ -251,7 +250,7 @@ static void _PR_InitStuff(void)
_PR_MD_FINAL_INIT();
}
-void _PR_ImplicitInitialization()
+void _PR_ImplicitInitialization(void)
{
_PR_InitStuff();
@@ -417,9 +416,10 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0));
#endif
-#if defined(WIN16)
+ _PR_CleanupMW();
+ _PR_CleanupDtoa();
+ _PR_CleanupCallOnce();
_PR_ShutdownLinker();
-#endif
/* Release the primordial thread's private data, etc. */
_PR_CleanupThread(me);
@@ -449,6 +449,7 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
* Ideally, for each _PR_InitXXX(), there should be a corresponding
* _PR_XXXCleanup() that we can call here.
*/
+ _PR_CleanupNet();
_PR_CleanupIO();
_PR_CleanupThreads();
PR_DestroyLock(_pr_sleeplock);
@@ -776,13 +777,20 @@ static struct {
PRCondVar *cv;
} mod_init;
-static void _PR_InitCallOnce() {
+static void _PR_InitCallOnce(void) {
mod_init.ml = PR_NewLock();
PR_ASSERT(NULL != mod_init.ml);
mod_init.cv = PR_NewCondVar(mod_init.ml);
PR_ASSERT(NULL != mod_init.cv);
}
+void _PR_CleanupCallOnce()
+{
+ PR_DestroyLock(mod_init.ml);
+ mod_init.ml = NULL;
+ PR_DestroyCondVar(mod_init.cv);
+ mod_init.cv = NULL;
+}
PR_IMPLEMENT(PRStatus) PR_CallOnce(
PRCallOnceType *once,
diff --git a/pr/src/misc/prinrval.c b/pr/src/misc/prinrval.c
index d0af3977..a319e8cb 100644
--- a/pr/src/misc/prinrval.c
+++ b/pr/src/misc/prinrval.c
@@ -68,13 +68,13 @@ void _PR_InitClock(void)
* 2) The units here are milliseconds. That's not appropriate for our use.
*/
-PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow()
+PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
return _PR_MD_GET_INTERVAL();
} /* PR_IntervalNow */
-PR_EXTERN(PRUint32) PR_TicksPerSecond()
+PR_EXTERN(PRUint32) PR_TicksPerSecond(void)
{
if (!_pr_initialized) _PR_ImplicitInitialization();
return _PR_MD_INTERVAL_PER_SEC();
diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c
index b40ca804..58342292 100644
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -83,6 +83,12 @@ PRLock *_pr_dnsLock = NULL;
* Some return a pointer to struct protoent, others return
* an int.
*/
+#if defined(XP_BEOS) && defined(BONE_VERSION)
+#include <arpa/inet.h> /* pick up define for inet_addr */
+#include <sys/socket.h>
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_GETPROTO_R_POINTER
+#endif
#if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \
|| (defined(LINUX) && defined(_REENTRANT) \
@@ -157,6 +163,175 @@ const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0,
#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3])
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+
+/*
+ * The _pr_QueryNetIfs() function finds out if the system has
+ * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if
+ * and _pr_have_inet6_if accordingly.
+ *
+ * We have an implementation using SIOCGIFCONF ioctl and a
+ * default implementation that simply sets _pr_have_inet_if
+ * and _pr_have_inet6_if to true. A better implementation
+ * would be to use the routing sockets (see Chapter 17 of
+ * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.)
+ */
+
+static PRBool _pr_have_inet_if = PR_FALSE;
+static PRBool _pr_have_inet6_if = PR_FALSE;
+
+#undef DEBUG_QUERY_IFS
+
+#if defined(AIX)
+
+/*
+ * Use SIOCGIFCONF ioctl on platforms that don't have routing
+ * sockets. Warning: whether SIOCGIFCONF ioctl returns AF_INET6
+ * network interfaces is not portable.
+ *
+ * The _pr_QueryNetIfs() function is derived from the code in
+ * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in
+ * Section 16.6 of W. Richard Stevens' Unix Network Programming,
+ * Vol. 1, 2nd. Ed.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#ifdef DEBUG_QUERY_IFS
+static void
+_pr_PrintIfreq(struct ifreq *ifr)
+{
+ PRNetAddr addr;
+ struct sockaddr *sa;
+ const char* family;
+ char addrstr[64];
+
+ sa = &ifr->ifr_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ family = "inet";
+ memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr));
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ family = "inet6";
+ memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
+ } else {
+ return; /* skip if not AF_INET or AF_INET6 */
+ }
+ addr.raw.family = sa->sa_family;
+ PR_NetAddrToString(&addr, addrstr, sizeof(addrstr));
+ printf("%s: %s %s\n", ifr->ifr_name, family, addrstr);
+}
+#endif
+
+static void
+_pr_QueryNetIfs(void)
+{
+ int sock;
+ int rv;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ struct ifreq *lifr;
+ PRUint32 len, lastlen;
+ char *buf;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ return;
+ }
+
+ /* Issue SIOCGIFCONF request in a loop. */
+ lastlen = 0;
+ len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
+ for (;;) {
+ buf = PR_Malloc(len);
+ if (NULL == buf) {
+ close(sock);
+ return;
+ }
+ ifc.ifc_buf = buf;
+ ifc.ifc_len = len;
+ rv = ioctl(sock, SIOCGIFCONF, &ifc);
+ if (rv < 0) {
+ if (errno != EINVAL || lastlen != 0) {
+ close(sock);
+ PR_Free(buf);
+ return;
+ }
+ } else {
+ if (ifc.ifc_len == lastlen)
+ break; /* success, len has not changed */
+ lastlen = ifc.ifc_len;
+ }
+ len += 10 * sizeof(struct ifreq); /* increment */
+ PR_Free(buf);
+ }
+ close(sock);
+
+ ifr = ifc.ifc_req;
+ lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+ while (ifr < lifr) {
+ struct sockaddr *sa;
+ int sa_len;
+
+#ifdef DEBUG_QUERY_IFS
+ _pr_PrintIfreq(ifr);
+#endif
+ sa = &ifr->ifr_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ _pr_have_inet_if = PR_TRUE;
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) {
+ _pr_have_inet6_if = PR_TRUE;
+ }
+ }
+
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr));
+#else
+ switch (sa->sa_family) {
+#ifdef AF_LINK
+ case AF_LINK:
+ sa_len = sizeof(struct sockaddr_dl);
+ break;
+#endif
+ case AF_INET6:
+ sa_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ sa_len = sizeof(struct sockaddr);
+ break;
+ }
+#endif
+ ifr = (struct ifreq *)(((char *)sa) + sa_len);
+ }
+ PR_Free(buf);
+}
+
+#else /* default */
+
+/*
+ * Emulate the code in NSPR 4.2 or older. PR_GetIPNodeByName behaves
+ * as if the system had both IPv4 and IPv6 source addresses configured.
+ */
+static void
+_pr_QueryNetIfs(void)
+{
+ _pr_have_inet_if = PR_TRUE;
+ _pr_have_inet6_if = PR_TRUE;
+}
+
+#endif
+
+#endif /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */
+
void _PR_InitNet(void)
{
#if defined(XP_UNIX)
@@ -174,6 +349,31 @@ void _PR_InitNet(void)
#if !defined(_PR_HAVE_GETPROTO_R)
_getproto_lock = PR_NewLock();
#endif
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+ _pr_QueryNetIfs();
+#ifdef DEBUG_QUERY_IFS
+ if (_pr_have_inet_if)
+ printf("Have IPv4 source address\n");
+ if (_pr_have_inet6_if)
+ printf("Have IPv6 source address\n");
+#endif
+#endif
+}
+
+void _PR_CleanupNet(void)
+{
+#if !defined(_PR_NO_DNS_LOCK)
+ if (_pr_dnsLock) {
+ PR_DestroyLock(_pr_dnsLock);
+ _pr_dnsLock = NULL;
+ }
+#endif
+#if !defined(_PR_HAVE_GETPROTO_R)
+ if (_getproto_lock) {
+ PR_DestroyLock(_getproto_lock);
+ _getproto_lock = NULL;
+ }
+#endif
}
/*
@@ -215,7 +415,6 @@ static void MakeIPv4MappedAddr(const char *v4, char *v6)
memset(v6, 0, 10);
memset(v6 + 10, 0xff, 2);
memcpy(v6 + 12, v4, 4);
- PR_ASSERT(_PR_IN6_IS_ADDR_V4MAPPED(((PRIPv6Addr *) v6)));
}
/*
@@ -225,7 +424,6 @@ static void MakeIPv4CompatAddr(const char *v4, char *v6)
{
memset(v6, 0, 12);
memcpy(v6 + 12, v4, 4);
- PR_ASSERT(_PR_IN6_IS_ADDR_V4COMPAT(((PRIPv6Addr *) v6)));
}
/*
@@ -553,11 +751,15 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName(
LOCK_DNS();
if (af == PR_AF_INET6)
{
+ if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet6_if)
+ {
#ifdef _PR_INET6_PROBE
- if (_pr_ipv6_is_present == PR_TRUE)
+ if (_pr_ipv6_is_present == PR_TRUE)
#endif
- h = GETHOSTBYNAME2(name, AF_INET6);
- if ((NULL == h) && (flags & PR_AI_V4MAPPED))
+ h = GETHOSTBYNAME2(name, AF_INET6);
+ }
+ if ((NULL == h) && (flags & PR_AI_V4MAPPED)
+ && ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if))
{
did_af_inet = PR_TRUE;
h = GETHOSTBYNAME2(name, AF_INET);
@@ -565,8 +767,11 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName(
}
else
{
- did_af_inet = PR_TRUE;
- h = GETHOSTBYNAME2(name, af);
+ if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if)
+ {
+ did_af_inet = PR_TRUE;
+ h = GETHOSTBYNAME2(name, af);
+ }
}
#elif defined(_PR_HAVE_GETIPNODEBYNAME)
h = getipnodebyname(name, md_af, tmp_flags, &error_num);
@@ -619,7 +824,8 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName(
#endif
#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED)
- && (flags & (PR_AI_ALL|PR_AI_ADDRCONFIG))
+ && ((flags & PR_AI_ALL)
+ || ((flags & PR_AI_ADDRCONFIG) && _pr_have_inet_if))
&& !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)) != 0) {
rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp);
if (PR_SUCCESS != rv)
diff --git a/pr/src/misc/prsystem.c b/pr/src/misc/prsystem.c
index bb786766..5c84e5e7 100644
--- a/pr/src/misc/prsystem.c
+++ b/pr/src/misc/prsystem.c
@@ -58,7 +58,7 @@
#endif
#if defined(HPUX)
-#include <sys/mp.h>
+#include <sys/mpctl.h>
#endif
#if defined(XP_UNIX)
@@ -66,7 +66,7 @@
#include <sys/utsname.h>
#endif
-PR_IMPLEMENT(char) PR_GetDirectorySeparator()
+PR_IMPLEMENT(char) PR_GetDirectorySeparator(void)
{
return PR_DIRECTORY_SEPARATOR;
} /* PR_GetDirectorySeparator */
@@ -74,7 +74,7 @@ PR_IMPLEMENT(char) PR_GetDirectorySeparator()
/*
** OBSOLETE -- the function name is misspelled.
*/
-PR_IMPLEMENT(char) PR_GetDirectorySepartor()
+PR_IMPLEMENT(char) PR_GetDirectorySepartor(void)
{
#if defined(DEBUG)
static PRBool warn = PR_TRUE;
@@ -97,6 +97,12 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle
case PR_SI_HOSTNAME:
if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen))
return PR_FAILURE;
+ /*
+ * On some platforms a system does not have a hostname and
+ * its IP address is returned instead. The following code
+ * should be skipped on those platforms.
+ */
+#ifndef _PR_GET_HOST_ADDR_AS_NAME
/* Return the unqualified hostname */
while (buf[len] && (len < buflen)) {
if (buf[len] == '.') {
@@ -105,6 +111,7 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle
}
len += 1;
}
+#endif
break;
case PR_SI_SYSNAME:
@@ -150,7 +157,6 @@ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 bufle
default:
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
- break;
}
return PR_SUCCESS;
}
diff --git a/pr/src/misc/prtime.c b/pr/src/misc/prtime.c
index 0aa6e46c..a107d1d4 100644
--- a/pr/src/misc/prtime.c
+++ b/pr/src/misc/prtime.c
@@ -774,7 +774,7 @@ PR_IMPLEMENT(PRTimeParameters)
PR_USPacificTimeParameters(const PRExplodedTime *gmt)
{
PRTimeParameters retVal;
- PRExplodedTime std;
+ PRExplodedTime st;
/*
* Based on geographic location and GMT, figure out offset of
@@ -789,32 +789,32 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
* is ignored.
*/
- std.tm_usec = gmt->tm_usec;
- std.tm_sec = gmt->tm_sec;
- std.tm_min = gmt->tm_min;
- std.tm_hour = gmt->tm_hour;
- std.tm_mday = gmt->tm_mday;
- std.tm_month = gmt->tm_month;
- std.tm_year = gmt->tm_year;
- std.tm_wday = gmt->tm_wday;
- std.tm_yday = gmt->tm_yday;
+ st.tm_usec = gmt->tm_usec;
+ st.tm_sec = gmt->tm_sec;
+ st.tm_min = gmt->tm_min;
+ st.tm_hour = gmt->tm_hour;
+ st.tm_mday = gmt->tm_mday;
+ st.tm_month = gmt->tm_month;
+ st.tm_year = gmt->tm_year;
+ st.tm_wday = gmt->tm_wday;
+ st.tm_yday = gmt->tm_yday;
/* Apply the offset to GMT to obtain the local standard time */
- ApplySecOffset(&std, retVal.tp_gmt_offset);
+ ApplySecOffset(&st, retVal.tp_gmt_offset);
/*
* Apply the rules on standard time or GMT to obtain daylight saving
* time offset. In this implementation, we use the US DST rule.
*/
- if (std.tm_month < 3) {
+ if (st.tm_month < 3) {
retVal.tp_dst_offset = 0L;
- } else if (std.tm_month == 3) {
- if (std.tm_wday == 0) {
+ } else if (st.tm_month == 3) {
+ if (st.tm_wday == 0) {
/* A Sunday */
- if (std.tm_mday <= 7) {
+ if (st.tm_mday <= 7) {
/* First Sunday */
/* 01:59:59 PST -> 03:00:00 PDT */
- if (std.tm_hour < 2) {
+ if (st.tm_hour < 2) {
retVal.tp_dst_offset = 0L;
} else {
retVal.tp_dst_offset = 3600L;
@@ -825,7 +825,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
}
} else {
/* Not a Sunday. See if before first Sunday or after */
- if (std.tm_wday + 1 <= std.tm_mday) {
+ if (st.tm_wday + 1 <= st.tm_mday) {
/* After first Sunday */
retVal.tp_dst_offset = 3600L;
} else {
@@ -833,14 +833,14 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
retVal.tp_dst_offset = 0L;
}
}
- } else if (std.tm_month < 9) {
+ } else if (st.tm_month < 9) {
retVal.tp_dst_offset = 3600L;
- } else if (std.tm_month == 9) {
- if (std.tm_wday == 0) {
- if (31 - std.tm_mday < 7) {
+ } else if (st.tm_month == 9) {
+ if (st.tm_wday == 0) {
+ if (31 - st.tm_mday < 7) {
/* Last Sunday */
/* 01:59:59 PDT -> 01:00:00 PST */
- if (std.tm_hour < 1) {
+ if (st.tm_hour < 1) {
retVal.tp_dst_offset = 3600L;
} else {
retVal.tp_dst_offset = 0L;
@@ -851,7 +851,7 @@ PR_USPacificTimeParameters(const PRExplodedTime *gmt)
}
} else {
/* See if before or after last Sunday */
- if (7 - std.tm_wday <= 31 - std.tm_mday) {
+ if (7 - st.tm_wday <= 31 - st.tm_mday) {
/* before last Sunday */
retVal.tp_dst_offset = 3600L;
} else {
diff --git a/pr/src/misc/prtpool.c b/pr/src/misc/prtpool.c
index 2f43c676..acf6ec77 100644
--- a/pr/src/misc/prtpool.c
+++ b/pr/src/misc/prtpool.c
@@ -166,7 +166,7 @@ struct PRJob {
PR_END_MACRO
static void delete_job(PRJob *jobp);
-static PRThreadPool * alloc_threadpool();
+static PRThreadPool * alloc_threadpool(void);
static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp);
static void notify_ioq(PRThreadPool *tp);
static void notify_timerq(PRThreadPool *tp);
@@ -599,7 +599,7 @@ delete_threadpool(PRThreadPool *tp)
}
static PRThreadPool *
-alloc_threadpool()
+alloc_threadpool(void)
{
PRThreadPool *tp;
diff --git a/pr/src/pthreads/Makefile.in b/pr/src/pthreads/Makefile.in
index a43fd6ac..8eb237d4 100644
--- a/pr/src/pthreads/Makefile.in
+++ b/pr/src/pthreads/Makefile.in
@@ -63,6 +63,11 @@ INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/incl
DEFINES += -D_NSPR_BUILD_
+ifeq ($(OS_ARCH),Linux)
+# for pthread_mutexattr_settype
+DEFINES += -D_XOPEN_SOURCE=500
+endif
+
include $(topsrcdir)/config/rules.mk
export:: $(TARGETS)
diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c
index ce263217..29344491 100644
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -173,11 +173,18 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL;
#endif /* HAVE_SEND_FILE */
#endif /* AIX */
+#ifdef LINUX
+#include <sys/sendfile.h>
+#endif
+
#include "primpl.h"
-/* On Alpha Linux, these are already defined in sys/socket.h */
-#if !(defined(LINUX) && defined(__alpha))
#include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */
+#ifdef LINUX
+/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */
+#ifndef TCP_CORK
+#define TCP_CORK 3
+#endif
#endif
#if defined(SOLARIS)
@@ -281,11 +288,9 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
* most current systems.
*/
#if defined(HAVE_SOCKLEN_T) \
- || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2 \
- && !defined(__alpha))
+ || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)
typedef socklen_t pt_SockLen;
#elif (defined(AIX) && !defined(AIX4_1)) \
- || (defined(LINUX) && defined(__alpha)) \
|| defined(VMS)
typedef PRSize pt_SockLen;
#else
@@ -338,6 +343,15 @@ struct pt_Continuation
*/
int nbytes_to_send; /* size of header and file */
#endif /* SOLARIS */
+
+#ifdef LINUX
+ /*
+ * For sendfile()
+ */
+ int in_fd; /* descriptor of file to send */
+ off_t offset;
+ size_t count;
+#endif /* LINUX */
PRIntervalTime timeout; /* client (relative) timeout */
@@ -406,6 +420,7 @@ static void pt_poll_now_with_select(pt_Continuation *op)
fd_set rd, wr, *rdp, *wrp;
struct timeval tv;
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRThread *self = PR_GetCurrentThread();
PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
@@ -485,9 +500,12 @@ static void pt_poll_now_with_select(pt_Continuation *op)
} else
wrp = NULL;
+ wait_for_remaining = PR_TRUE;
msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
- if (msecs > PT_DEFAULT_POLL_MSEC)
+ if (msecs > PT_DEFAULT_POLL_MSEC) {
+ wait_for_remaining = PR_FALSE;
msecs = PT_DEFAULT_POLL_MSEC;
+ }
tv.tv_sec = msecs/PR_MSEC_PER_SEC;
tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
@@ -514,9 +532,12 @@ static void pt_poll_now_with_select(pt_Continuation *op)
} else if ((rv == 0) ||
((errno == EINTR) || (errno == EAGAIN))) {
- if (rv == 0) /* select timed out */
- now += PR_MillisecondsToInterval(msecs);
- else
+ if (rv == 0) { /* select timed out */
+ if (wait_for_remaining)
+ now += remaining;
+ else
+ now += PR_MillisecondsToInterval(msecs);
+ } else
now = PR_IntervalNow();
elapsed = (PRIntervalTime) (now - epoch);
if (elapsed >= op->timeout) {
@@ -542,6 +563,7 @@ static void pt_poll_now(pt_Continuation *op)
{
PRInt32 msecs;
PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
PRThread *self = PR_GetCurrentThread();
PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
@@ -618,9 +640,13 @@ static void pt_poll_now(pt_Continuation *op)
tmp_pfd.fd = op->arg1.osfd;
tmp_pfd.events = op->event;
+ wait_for_remaining = PR_TRUE;
msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
if (msecs > PT_DEFAULT_POLL_MSEC)
+ {
+ wait_for_remaining = PR_FALSE;
msecs = PT_DEFAULT_POLL_MSEC;
+ }
rv = poll(&tmp_pfd, 1, msecs);
if (self->state & PT_THREAD_ABORTED)
@@ -654,7 +680,12 @@ static void pt_poll_now(pt_Continuation *op)
} else if ((rv == 0) ||
((errno == EINTR) || (errno == EAGAIN))) {
if (rv == 0) /* poll timed out */
- now += PR_MillisecondsToInterval(msecs);
+ {
+ if (wait_for_remaining)
+ now += remaining;
+ else
+ now += PR_MillisecondsToInterval(msecs);
+ }
else
now = PR_IntervalNow();
elapsed = (PRIntervalTime) (now - epoch);
@@ -1024,17 +1055,18 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
ssize_t count;
count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred);
- PR_ASSERT((count == -1) || (count == xferred));
- PR_ASSERT(xferred <= op->nbytes_to_send);
op->syserrno = errno;
+ PR_ASSERT((count == -1) || (count == xferred));
if (count == -1) {
- if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+ if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN
+ && op->syserrno != EINTR) {
op->result.code = -1;
return PR_TRUE;
}
count = xferred;
}
+ PR_ASSERT(count <= op->nbytes_to_send);
op->result.code += count;
if (count < op->nbytes_to_send) {
@@ -1059,7 +1091,34 @@ static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
}
#endif /* SOLARIS */
-void _PR_InitIO()
+#ifdef LINUX
+static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+ ssize_t rv;
+ off_t oldoffset;
+
+ oldoffset = op->offset;
+ rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count);
+ op->syserrno = errno;
+
+ if (rv == -1) {
+ if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ rv = 0;
+ }
+ PR_ASSERT(rv == op->offset - oldoffset);
+ op->result.code += rv;
+ if (rv < op->count) {
+ op->count -= rv;
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+#endif /* LINUX */
+
+void _PR_InitIO(void)
{
#if defined(DEBUG)
memset(&pt_debug, 0, sizeof(PTDebug));
@@ -1569,6 +1628,18 @@ static PRFileDesc* pt_Accept(
if (pt_TestAbort()) return newfd;
+#ifdef _PR_STRICT_ADDR_LEN
+ if (addr)
+ {
+ /*
+ * Set addr->raw.family just so that we can use the
+ * PR_NETADDR_SIZE macro.
+ */
+ addr->raw.family = fd->secret->af;
+ addr_len = PR_NETADDR_SIZE(addr);
+ }
+#endif
+
osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
syserrno = errno;
@@ -1614,6 +1685,14 @@ static PRFileDesc* pt_Accept(
{
PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
+#ifdef LINUX
+ /*
+ * On Linux, experiments showed that the accepted sockets
+ * inherit the TCP_NODELAY socket option of the listening
+ * socket.
+ */
+ newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;
+#endif
}
return newfd;
@@ -2107,7 +2186,7 @@ static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
}
if (count == -1) {
- _MD_aix_map_sendfile_error(syserrno);
+ pt_MapError(_MD_aix_map_sendfile_error, syserrno);
return -1;
}
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
@@ -2146,14 +2225,16 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
PRInt32 count;
int syserrno;
- /* Get file size */
- if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
- _PR_MD_MAP_FSTAT_ERROR(errno);
- return -1;
+ if (sfd->file_nbytes == 0) {
+ /* Get file size */
+ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+ file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+ } else {
+ file_nbytes_to_send = sfd->file_nbytes;
}
- file_nbytes_to_send = (sfd->file_nbytes == 0) ?
- statbuf.st_size - sfd->file_offset :
- sfd->file_nbytes;
nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;
hdtrl[0].iov_base = (void *) sfd->header; /* cast away the 'const' */
@@ -2228,7 +2309,7 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
}
if (count == -1) {
- _MD_hpux_map_sendfile_error(syserrno);
+ pt_MapError(_MD_hpux_map_sendfile_error, syserrno);
return -1;
}
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
@@ -2358,7 +2439,7 @@ static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd,
done:
if (count == -1) {
- _MD_solaris_map_sendfile_error(syserrno);
+ pt_MapError(_MD_solaris_map_sendfile_error, syserrno);
return -1;
}
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
@@ -2425,6 +2506,140 @@ static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
#endif /* SOLARIS */
+#ifdef LINUX
+/*
+ * pt_LinuxSendFile
+ *
+ * Send file sfd->fd across socket sd. If specified, header and trailer
+ * buffers are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ * This implementation takes advantage of the sendfile() system
+ * call available in Linux kernel 2.2 or higher.
+ */
+
+static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ struct stat statbuf;
+ size_t file_nbytes_to_send;
+ PRInt32 count = 0;
+ ssize_t rv;
+ int syserrno;
+ off_t offset;
+ PRBool tcp_cork_enabled = PR_FALSE;
+ int tcp_cork;
+
+ if (sfd->file_nbytes == 0) {
+ /* Get file size */
+ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+ file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+ } else {
+ file_nbytes_to_send = sfd->file_nbytes;
+ }
+
+ if ((sfd->hlen != 0 || sfd->tlen != 0)
+ && sd->secret->md.tcp_nodelay == 0) {
+ tcp_cork = 1;
+ if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+ &tcp_cork, sizeof tcp_cork) == 0) {
+ tcp_cork_enabled = PR_TRUE;
+ } else {
+ syserrno = errno;
+ if (syserrno != EINVAL) {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);
+ return -1;
+ }
+ /*
+ * The most likely reason for the EINVAL error is that
+ * TCP_NODELAY is set (with a function other than
+ * PR_SetSocketOption). This is not fatal, so we keep
+ * on going.
+ */
+ PR_LOG(_pr_io_lm, PR_LOG_WARNING,
+ ("pt_LinuxSendFile: "
+ "setsockopt(TCP_CORK) failed with EINVAL\n"));
+ }
+ }
+
+ if (sfd->hlen != 0) {
+ count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout);
+ if (count == -1) {
+ goto failed;
+ }
+ }
+
+ if (file_nbytes_to_send != 0) {
+ offset = sfd->file_offset;
+ do {
+ rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
+ &offset, file_nbytes_to_send);
+ } while (rv == -1 && (syserrno = errno) == EINTR);
+ if (rv == -1) {
+ if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) {
+ _MD_linux_map_sendfile_error(syserrno);
+ count = -1;
+ goto failed;
+ }
+ rv = 0;
+ }
+ PR_ASSERT(rv == offset - sfd->file_offset);
+ count += rv;
+
+ if (rv < file_nbytes_to_send) {
+ pt_Continuation op;
+
+ op.arg1.osfd = sd->secret->md.osfd;
+ op.in_fd = sfd->fd->secret->md.osfd;
+ op.offset = offset;
+ op.count = file_nbytes_to_send - rv;
+ op.result.code = count;
+ op.timeout = timeout;
+ op.function = pt_linux_sendfile_cont;
+ op.event = POLLOUT | POLLPRI;
+ count = pt_Continue(&op);
+ syserrno = op.syserrno;
+ if (count == -1) {
+ pt_MapError(_MD_linux_map_sendfile_error, syserrno);
+ goto failed;
+ }
+ }
+ }
+
+ if (sfd->tlen != 0) {
+ rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
+ if (rv == -1) {
+ count = -1;
+ goto failed;
+ }
+ count += rv;
+ }
+
+failed:
+ if (tcp_cork_enabled) {
+ tcp_cork = 0;
+ if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+ &tcp_cork, sizeof tcp_cork) == -1 && count != -1) {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
+ count = -1;
+ }
+ }
+ if (count != -1) {
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ PR_Close(sd);
+ }
+ PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send);
+ }
+ return count;
+}
+#endif /* LINUX */
+
#ifdef AIX
extern int _pr_aix_send_file_use_disabled;
#endif
@@ -2465,6 +2680,8 @@ static PRInt32 pt_SendFile(
#else
return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout));
#endif /* HAVE_SENDFILEV */
+#elif defined(LINUX)
+ return(pt_LinuxSendFile(sd, sfd, flags, timeout));
#else
return(PR_EmulateSendFile(sd, sfd, flags, timeout));
#endif
@@ -2728,6 +2945,12 @@ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *dat
rv = setsockopt(
fd->secret->md.osfd, level, name,
(char*)&value, sizeof(PRIntn));
+#ifdef LINUX
+ /* for pt_LinuxSendFile */
+ if (name == TCP_NODELAY && rv == 0) {
+ fd->secret->md.tcp_nodelay = value;
+ }
+#endif
break;
}
case PR_SockOpt_McastLoopback:
@@ -3086,27 +3309,27 @@ static PRFileDesc *pt_SetMethods(
return fd;
} /* pt_SetMethods */
-PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
{
return &_pr_file_methods;
} /* PR_GetFileMethods */
-PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
{
return &_pr_pipe_methods;
} /* PR_GetPipeMethods */
-PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void)
{
return &_pr_tcp_methods;
} /* PR_GetTCPMethods */
-PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
+PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods(void)
{
return &_pr_udp_methods;
} /* PR_GetUDPMethods */
-static const PRIOMethods* PR_GetSocketPollFdMethods()
+static const PRIOMethods* PR_GetSocketPollFdMethods(void)
{
return &_pr_socketpollfd_methods;
} /* PR_GetSocketPollFdMethods */
@@ -3206,6 +3429,9 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE);
if (fd == NULL) close(osfd);
}
+#ifdef _PR_STRICT_ADDR_LEN
+ if (fd != NULL) fd->secret->af = domain;
+#endif
#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
if (fd != NULL) {
/*
@@ -4017,14 +4243,14 @@ PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags)
return &dir->d;
} /* PR_ReadDir */
-PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket()
+PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
{
PRIntn domain = PF_INET;
return PR_Socket(domain, SOCK_DGRAM, 0);
} /* PR_NewUDPSocket */
-PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket()
+PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket(void)
{
PRIntn domain = PF_INET;
@@ -4122,7 +4348,7 @@ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
{
return PR_FAILURE;
}
- fd->secret->inheritable = inheritable;
+ fd->secret->inheritable = (_PRTriStateBool) inheritable;
}
return PR_SUCCESS;
}
@@ -4158,6 +4384,9 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd)
if (!_pr_initialized) _PR_ImplicitInitialization();
fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE);
if (NULL == fd) close(osfd);
+#ifdef _PR_STRICT_ADDR_LEN
+ if (NULL != fd) fd->secret->af = PF_INET;
+#endif
return fd;
} /* PR_ImportTCPSocket */
diff --git a/pr/src/pthreads/ptsynch.c b/pr/src/pthreads/ptsynch.c
index 4400e8df..17334af3 100644
--- a/pr/src/pthreads/ptsynch.c
+++ b/pr/src/pthreads/ptsynch.c
@@ -71,6 +71,13 @@ void _PR_InitLocks(void)
rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr);
PR_ASSERT(0 == rv);
+#ifdef LINUX
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+ rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
+ PR_ASSERT(0 == rv);
+#endif
+#endif
+
rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
PR_ASSERT(0 == rv);
}
@@ -1041,7 +1048,7 @@ PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
} /* PRP_TryLock */
-PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar()
+PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
{
PRCondVar *cv;
diff --git a/pr/src/pthreads/ptthread.c b/pr/src/pthreads/ptthread.c
index dc8cc127..070a887c 100644
--- a/pr/src/pthreads/ptthread.c
+++ b/pr/src/pthreads/ptthread.c
@@ -607,9 +607,9 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
} /* PR_JoinThread */
-PR_IMPLEMENT(void) PR_DetachThread() { } /* PR_DetachThread */
+PR_IMPLEMENT(void) PR_DetachThread(void) { } /* PR_DetachThread */
-PR_IMPLEMENT(PRThread*) PR_GetCurrentThread()
+PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void)
{
void *thred;
@@ -724,25 +724,25 @@ PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred)
return PR_SUCCESS;
} /* PR_Interrupt */
-PR_IMPLEMENT(void) PR_ClearInterrupt()
+PR_IMPLEMENT(void) PR_ClearInterrupt(void)
{
PRThread *me = PR_CurrentThread();
me->state &= ~PT_THREAD_ABORTED;
} /* PR_ClearInterrupt */
-PR_IMPLEMENT(void) PR_BlockInterrupt()
+PR_IMPLEMENT(void) PR_BlockInterrupt(void)
{
PRThread *me = PR_CurrentThread();
_PT_THREAD_BLOCK_INTERRUPT(me);
} /* PR_BlockInterrupt */
-PR_IMPLEMENT(void) PR_UnblockInterrupt()
+PR_IMPLEMENT(void) PR_UnblockInterrupt(void)
{
PRThread *me = PR_CurrentThread();
_PT_THREAD_UNBLOCK_INTERRUPT(me);
} /* PR_UnblockInterrupt */
-PR_IMPLEMENT(PRStatus) PR_Yield()
+PR_IMPLEMENT(PRStatus) PR_Yield(void)
{
static PRBool warning = PR_TRUE;
if (warning) warning = _PR_Obsolete(
@@ -908,7 +908,7 @@ void _PR_InitThreads(
PR_SetThreadPriority(thred, priority);
} /* _PR_InitThreads */
-PR_IMPLEMENT(PRStatus) PR_Cleanup()
+PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
{
PRThread *me = PR_CurrentThread();
PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
@@ -920,7 +920,12 @@ PR_IMPLEMENT(PRStatus) PR_Cleanup()
PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
PR_Unlock(pt_book.ml);
+ _PR_CleanupMW();
+ _PR_CleanupDtoa();
+ _PR_CleanupCallOnce();
+ _PR_ShutdownLinker();
_PR_LogCleanup();
+ _PR_CleanupNet();
/* Close all the fd's before calling _PR_CleanupIO */
_PR_CleanupIO();
@@ -1026,7 +1031,7 @@ static void null_signal_handler(PRIntn sig);
* conflict with the use of these two signals in our GC support.
* So we don't know how to support GC on Linux pthreads.
*/
-static void init_pthread_gc_support()
+static void init_pthread_gc_support(void)
{
PRIntn rv;
@@ -1066,14 +1071,14 @@ static void init_pthread_gc_support()
#endif /* defined(_PR_DCETHREADS) */
}
-PR_IMPLEMENT(void) PR_SetThreadGCAble()
+PR_IMPLEMENT(void) PR_SetThreadGCAble(void)
{
PR_Lock(pt_book.ml);
PR_CurrentThread()->state |= PT_THREAD_GCABLE;
PR_Unlock(pt_book.ml);
}
-PR_IMPLEMENT(void) PR_ClearThreadGCAble()
+PR_IMPLEMENT(void) PR_ClearThreadGCAble(void)
{
PR_Lock(pt_book.ml);
PR_CurrentThread()->state &= (~PT_THREAD_GCABLE);
@@ -1215,7 +1220,7 @@ static void suspend_signal_handler(PRIntn sig)
while (me->suspend & PT_THREAD_SUSPENDED)
{
#if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
- && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) /*XXX*/
+ && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) && !defined(DARWIN) /*XXX*/
PRIntn rv;
sigwait(&sigwait_set, &rv);
#endif
@@ -1356,7 +1361,7 @@ PR_IMPLEMENT(void) PR_ResumeTest(PRThread *thred)
static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT;
-PR_IMPLEMENT(void) PR_SuspendAll()
+PR_IMPLEMENT(void) PR_SuspendAll(void)
{
#ifdef DEBUG
PRIntervalTime stime, etime;
@@ -1402,7 +1407,7 @@ PR_IMPLEMENT(void) PR_SuspendAll()
#endif
} /* PR_SuspendAll */
-PR_IMPLEMENT(void) PR_ResumeAll()
+PR_IMPLEMENT(void) PR_ResumeAll(void)
{
#ifdef DEBUG
PRIntervalTime stime, etime;
diff --git a/pr/src/threads/combined/prucpu.c b/pr/src/threads/combined/prucpu.c
index d9159b52..be4203d6 100644
--- a/pr/src/threads/combined/prucpu.c
+++ b/pr/src/threads/combined/prucpu.c
@@ -59,7 +59,8 @@ static PRUintn _pr_cpuID;
static void PR_CALLBACK _PR_CPU_Idle(void *);
-static _PRCPU *_PR_CreateCPU(PRThread *thread, PRBool needQueue);
+static _PRCPU *_PR_CreateCPU(void);
+static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread);
#if !defined(_PR_LOCAL_THREADS_ONLY)
static void _PR_RunCPU(void *arg);
@@ -69,6 +70,9 @@ void _PR_InitCPUs()
{
PRThread *me = _PR_MD_CURRENT_THREAD();
+ if (_native_threads_only)
+ return;
+
_pr_cpuID = 0;
_MD_NEW_LOCK( &_pr_cpuLock);
#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
@@ -80,13 +84,13 @@ void _PR_InitCPUs()
#ifdef _PR_LOCAL_THREADS_ONLY
#ifdef HAVE_CUSTOM_USER_THREADS
- if (!_native_threads_only)
- _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
+ _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
#endif
/* Now start the first CPU. */
- _pr_primordialCPU = _PR_CreateCPU(me, PR_TRUE);
+ _pr_primordialCPU = _PR_CreateCPU();
_pr_numCPU = 1;
+ _PR_StartCPU(_pr_primordialCPU, me);
_PR_MD_SET_CURRENT_CPU(_pr_primordialCPU);
@@ -97,15 +101,16 @@ void _PR_InitCPUs()
#else /* Combined MxN model */
+ _pr_primordialCPU = _PR_CreateCPU();
+ _pr_numCPU = 1;
_PR_CreateThread(PR_SYSTEM_THREAD,
_PR_RunCPU,
- me,
+ _pr_primordialCPU,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
0,
_PR_IDLE_THREAD);
- _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
#endif /* _PR_LOCAL_THREADS_ONLY */
@@ -137,89 +142,113 @@ static _PRCPUQueue *_PR_CreateCPUQueue(void)
/*
* Create a new CPU.
+ *
+ * This function initializes enough of the _PRCPU structure so
+ * that it can be accessed safely by a global thread or another
+ * CPU. This function does not create the native thread that
+ * will run the CPU nor does it initialize the parts of _PRCPU
+ * that must be initialized by that native thread.
+ *
+ * The reason we cannot simply have the native thread create
+ * and fully initialize a new CPU is that we need to be able to
+ * create a usable _pr_primordialCPU in _PR_InitCPUs without
+ * assuming that the primordial CPU thread we created can run
+ * during NSPR initialization. For example, on Windows while
+ * new threads can be created by DllMain, they won't be able
+ * to run during DLL initialization. If NSPR is initialized
+ * by DllMain, the primordial CPU thread won't run until DLL
+ * initialization is finished.
*/
-static _PRCPU *_PR_CreateCPU(PRThread *thread, PRBool needQueue)
+static _PRCPU *_PR_CreateCPU(void)
{
_PRCPU *cpu;
- /*
- ** Create a new cpu. The assumption this code makes is that the
- ** underlying operating system creates a stack to go with the new
- ** native thread. That stack will be used by the cpu when pausing.
- */
cpu = PR_NEWZAP(_PRCPU);
if (cpu) {
- cpu->last_clock = PR_IntervalNow();
-
- if (needQueue == PR_TRUE)
- cpu->queue = _PR_CreateCPUQueue();
- else
- cpu->queue = _PR_MD_CURRENT_CPU()->queue;
-
+ cpu->queue = _PR_CreateCPUQueue();
if (!cpu->queue) {
PR_DELETE(cpu);
return NULL;
}
-
- /* Before we create any threads on this CPU we have to
- * set the current CPU
- */
- _PR_MD_SET_CURRENT_CPU(cpu);
- _PR_MD_INIT_RUNNING_CPU(cpu);
- thread->cpu = cpu;
-
- if (!_native_threads_only) {
-
- cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD,
- _PR_CPU_Idle,
- (void *)cpu,
- PR_PRIORITY_NORMAL,
- PR_LOCAL_THREAD,
- PR_UNJOINABLE_THREAD,
- 0,
- _PR_IDLE_THREAD);
-
- if (!cpu->idle_thread) {
- /* didn't clean up CPU queue XXXMB */
- PR_DELETE(cpu);
- return NULL;
- }
- cpu->idle_thread->cpu = cpu;
-
- cpu->idle_thread->no_sched = 0;
- }
-
- cpu->thread = thread;
-
- if (_pr_cpu_affinity_mask)
- PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask);
-
- /* Created a new CPU */
- _PR_CPU_LIST_LOCK();
- cpu->id = _pr_cpuID++;
- PR_APPEND_LINK(&cpu->links, &_PR_CPUQ());
- _PR_CPU_LIST_UNLOCK();
- }
+ }
return cpu;
}
+/*
+ * Start a new CPU.
+ *
+ * 'cpu' is a _PRCPU structure created by _PR_CreateCPU().
+ * 'thread' is the native thread that will run the CPU.
+ *
+ * If this function fails, 'cpu' is destroyed.
+ */
+static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread)
+{
+ /*
+ ** Start a new cpu. The assumption this code makes is that the
+ ** underlying operating system creates a stack to go with the new
+ ** native thread. That stack will be used by the cpu when pausing.
+ */
+
+ PR_ASSERT(!_native_threads_only);
+
+ cpu->last_clock = PR_IntervalNow();
+
+ /* Before we create any threads on this CPU we have to
+ * set the current CPU
+ */
+ _PR_MD_SET_CURRENT_CPU(cpu);
+ _PR_MD_INIT_RUNNING_CPU(cpu);
+ thread->cpu = cpu;
+
+ cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD,
+ _PR_CPU_Idle,
+ (void *)cpu,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0,
+ _PR_IDLE_THREAD);
+
+ if (!cpu->idle_thread) {
+ /* didn't clean up CPU queue XXXMB */
+ PR_DELETE(cpu);
+ return PR_FAILURE;
+ }
+ PR_ASSERT(cpu->idle_thread->cpu == cpu);
+
+ cpu->idle_thread->no_sched = 0;
+
+ cpu->thread = thread;
+
+ if (_pr_cpu_affinity_mask)
+ PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask);
+
+ /* Created and started a new CPU */
+ _PR_CPU_LIST_LOCK();
+ cpu->id = _pr_cpuID++;
+ PR_APPEND_LINK(&cpu->links, &_PR_CPUQ());
+ _PR_CPU_LIST_UNLOCK();
+
+ return PR_SUCCESS;
+}
+
#if !defined(_PR_GLOBAL_THREADS_ONLY) && !defined(_PR_LOCAL_THREADS_ONLY)
/*
** This code is used during a cpu's initial creation.
*/
static void _PR_RunCPU(void *arg)
{
- _PRCPU *cpu;
+ _PRCPU *cpu = (_PRCPU *)arg;
PRThread *me = _PR_MD_CURRENT_THREAD();
- PRThread *waiter = (PRThread *) arg;
PR_ASSERT(NULL != me);
/*
- * _PR_CreateCPU calls _PR_CreateThread to create the
+ * _PR_StartCPU calls _PR_CreateThread to create the
* idle thread. Because _PR_CreateThread calls PR_Lock,
* the current thread has to remain a global thread
- * during the _PR_CreateCPU call so that it can wait for
+ * during the _PR_StartCPU call so that it can wait for
* the lock if the lock is held by another thread. If
* we clear the _PR_GLOBAL_SCOPE flag in
* _PR_MD_CREATE_PRIMORDIAL_THREAD, the current thread
@@ -227,7 +256,7 @@ static void _PR_RunCPU(void *arg)
* waiting for the lock because the CPU is not fully
* constructed yet.
*
- * After the CPU is created, it is safe to mark the
+ * After the CPU is started, it is safe to mark the
* current thread as a local thread.
*/
@@ -236,7 +265,7 @@ static void _PR_RunCPU(void *arg)
#endif
me->no_sched = 1;
- cpu = _PR_CreateCPU(me, PR_TRUE);
+ _PR_StartCPU(cpu, me);
#ifdef HAVE_CUSTOM_USER_THREADS
me->flags &= (~_PR_GLOBAL_SCOPE);
@@ -246,12 +275,6 @@ static void _PR_RunCPU(void *arg)
_PR_MD_SET_CURRENT_THREAD(cpu->thread);
me->cpu = cpu;
- if (waiter) {
- _pr_primordialCPU = cpu;
- _pr_numCPU = 1;
- _PR_MD_WAKEUP_WAITER(waiter);
- }
-
while(1) {
PRInt32 is;
if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
@@ -344,7 +367,8 @@ PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
#else /* combined, MxN thread model */
PRUintn newCPU;
- PRThread *cpu;
+ _PRCPU *cpu;
+ PRThread *thr;
if (!_pr_initialized) _PR_ImplicitInitialization();
@@ -360,9 +384,10 @@ PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
_PR_CPU_LIST_UNLOCK();
for (; newCPU; newCPU--) {
- cpu = _PR_CreateThread(PR_SYSTEM_THREAD,
+ cpu = _PR_CreateCPU();
+ thr = _PR_CreateThread(PR_SYSTEM_THREAD,
_PR_RunCPU,
- NULL,
+ cpu,
PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD,
diff --git a/pr/src/threads/combined/pruthr.c b/pr/src/threads/combined/pruthr.c
index 77236df1..1329bb66 100644
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -85,7 +85,6 @@ PRThread *suspendAllThread = NULL;
extern PRCList _pr_active_global_threadQ;
extern PRCList _pr_active_local_threadQ;
-extern _PRCPU *_pr_primordialCPU;
static void _PR_DecrActiveThreadCount(PRThread *thread);
static PRThread *_PR_AttachThread(PRThreadType, PRThreadPriority, PRThreadStack *);
diff --git a/pr/src/threads/prtpd.c b/pr/src/threads/prtpd.c
index 42139329..6d8fd416 100644
--- a/pr/src/threads/prtpd.c
+++ b/pr/src/threads/prtpd.c
@@ -88,7 +88,7 @@ static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
/*
** Initialize the thread private data manipulation
*/
-void _PR_InitTPD()
+void _PR_InitTPD(void)
{
_pr_tpd_destructors = (PRThreadPrivateDTOR*)
PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));