Fix for bug 69285 "Mozilla is unresponsive after sleep", patch=sfraser, gordon, r=wtc.

This commit is contained in:
gordon%netscape.com 2001-06-08 23:19:29 +00:00
Родитель dc62e0708c
Коммит bc75f6605c
2 изменённых файлов: 223 добавлений и 32 удалений

Просмотреть файл

@ -132,6 +132,193 @@ PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
return PR_SUCCESS;
}
#elif defined (XP_MAC)
#include "primpl.h"
/*
* On Mac, local sockets cannot be used, because the networking stack
* closes them when the machine goes to sleep. Instead, we'll use a simple
* flag.
*/
/*
* PRFilePrivate structure for the NSPR pollable events layer
*/
typedef struct PRPollableDesc {
PRBool gotEvent;
PRThread *pollingThread;
} PRPollableDesc;
static PRStatus PR_CALLBACK _pr_MacPolEvtClose(PRFileDesc *fd);
static PRInt16 PR_CALLBACK _pr_MacPolEvtPoll(
PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
static PRIOMethods _pr_mac_polevt_methods = {
PR_DESC_LAYERED,
_pr_MacPolEvtClose,
(PRReadFN)_PR_InvalidInt,
(PRWriteFN)_PR_InvalidInt,
(PRAvailableFN)_PR_InvalidInt,
(PRAvailable64FN)_PR_InvalidInt64,
(PRFsyncFN)_PR_InvalidStatus,
(PRSeekFN)_PR_InvalidInt,
(PRSeek64FN)_PR_InvalidInt64,
(PRFileInfoFN)_PR_InvalidStatus,
(PRFileInfo64FN)_PR_InvalidStatus,
(PRWritevFN)_PR_InvalidInt,
(PRConnectFN)_PR_InvalidStatus,
(PRAcceptFN)_PR_InvalidDesc,
(PRBindFN)_PR_InvalidStatus,
(PRListenFN)_PR_InvalidStatus,
(PRShutdownFN)_PR_InvalidStatus,
(PRRecvFN)_PR_InvalidInt,
(PRSendFN)_PR_InvalidInt,
(PRRecvfromFN)_PR_InvalidInt,
(PRSendtoFN)_PR_InvalidInt,
_pr_MacPolEvtPoll,
(PRAcceptreadFN)_PR_InvalidInt,
(PRTransmitfileFN)_PR_InvalidInt,
(PRGetsocknameFN)_PR_InvalidStatus,
(PRGetpeernameFN)_PR_InvalidStatus,
(PRReservedFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt,
(PRGetsocketoptionFN)_PR_InvalidStatus,
(PRSetsocketoptionFN)_PR_InvalidStatus,
(PRSendfileFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt,
(PRReservedFN)_PR_InvalidInt
};
static PRDescIdentity _pr_mac_polevt_id;
static PRCallOnceType _pr_mac_polevt_once_control;
static PRStatus PR_CALLBACK _pr_MacPolEvtInit(void);
static PRInt16 PR_CALLBACK _pr_MacPolEvtPoll(
PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
{
PRPollableDesc *pollDesc = (PRPollableDesc *)fd->secret;
PR_ASSERT(pollDesc);
// set the current thread so that we can wake up the poll thread
pollDesc->pollingThread = PR_GetCurrentThread();
if ((in_flags & PR_POLL_READ) && pollDesc->gotEvent)
*out_flags = PR_POLL_READ;
else
*out_flags = 0;
return pollDesc->gotEvent ? 1 : 0;
}
static PRStatus PR_CALLBACK _pr_MacPolEvtInit(void)
{
_pr_mac_polevt_id = PR_GetUniqueIdentity("NSPR pollable events");
if (PR_INVALID_IO_LAYER == _pr_mac_polevt_id) {
return PR_FAILURE;
}
return PR_SUCCESS;
}
static PRStatus PR_CALLBACK _pr_MacPolEvtClose(PRFileDesc *fd)
{
PRPollableDesc *pollDesc = (PRPollableDesc *)fd->secret;
PR_ASSERT(NULL == fd->higher && NULL == fd->lower);
PR_ASSERT(pollDesc);
PR_DELETE(pollDesc);
fd->dtor(fd);
return PR_SUCCESS;
}
PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
{
PRFileDesc *event;
PRPollableDesc *pollDesc;
if (PR_CallOnce(&_pr_mac_polevt_once_control, _pr_MacPolEvtInit) == PR_FAILURE) {
return NULL;
}
event = PR_CreateIOLayerStub(_pr_mac_polevt_id, &_pr_mac_polevt_methods);
if (NULL == event) {
return NULL;
}
/*
** Allocate an event flag and clear it.
*/
pollDesc = PR_NEW(PRPollableDesc);
if (!pollDesc) {
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
goto errorExit;
}
pollDesc->gotEvent = PR_FALSE;
pollDesc->pollingThread = NULL;
event->secret = (PRFilePrivate*)pollDesc;
return event;
errorExit:
if (event) {
PR_DELETE(event->secret);
event->dtor(event);
}
return NULL;
}
PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
{
return PR_Close(event);
}
/* from macsockotpt.c. I wish there was a cleaner way */
extern void WakeUpNotifiedThread(PRThread *thread, OTResult result);
PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
{
PRPollableDesc *pollDesc = (PRPollableDesc *)event->secret;
PR_ASSERT(pollDesc);
PR_ASSERT(pollDesc->pollingThread->state != _PR_DEAD_STATE);
if (pollDesc->pollingThread->state == _PR_DEAD_STATE)
return PR_FAILURE;
pollDesc->gotEvent = PR_TRUE;
if (pollDesc->pollingThread)
WakeUpNotifiedThread(pollDesc->pollingThread, noErr);
return PR_SUCCESS;
}
PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
{
PRPollableDesc *pollDesc = (PRPollableDesc *)event->secret;
PRStatus status;
PR_ASSERT(pollDesc);
/*
FIXME: Danger Will Robinson!
The current implementation of PR_WaitForPollableEvent is somewhat
bogus; it makes the assumption that, in Mozilla, this will only
ever be called when PR_Poll has returned, telling us that an
event has been set.
*/
PR_ASSERT(pollDesc->gotEvent);
status = (pollDesc->gotEvent) ? PR_SUCCESS : PR_FAILURE;
pollDesc->gotEvent = PR_FALSE;
return status;
}
#else /* VMS */
/*

Просмотреть файл

@ -74,6 +74,9 @@ static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode co
static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
void
WakeUpNotifiedThread(PRThread *thread, OTResult result);
extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
extern void DoneWaitingOnThisThread(PRThread *thread);
@ -283,7 +286,7 @@ static void PrepareForAsyncCompletion(PRThread * thread, PRInt32 osfd)
}
static void
void
WakeUpNotifiedThread(PRThread *thread, OTResult result)
{
_PRCPU * cpu = _PR_MD_CURRENT_CPU();
@ -1739,37 +1742,39 @@ static PRInt32 CheckPollDescs(PRPollDesc *pds, PRIntn npds)
pd->out_flags = 0; /* pre-condition */
bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottomFD);
if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
{
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++;
}
}
else /* bad state */
/* bottomFD can be NULL for pollable sockets */
if (bottomFD)
{
ready += 1; /* this will cause an abrupt return */
pd->out_flags = PR_POLL_NVAL; /* bogii */
if (_PR_FILEDESC_OPEN == bottomFD->secret->state)
{
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++;
}
}
else /* bad state */
{
ready += 1; /* this will cause an abrupt return */
pd->out_flags = PR_POLL_NVAL; /* bogii */
}
}
}
}
@ -1788,7 +1793,6 @@ static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread)
if (pd->fd)
{
PRFileDesc *bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
PR_ASSERT(NULL != bottomFD);
if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
{
bottomFD->secret->md.poll.thread = thread;