PRUintn count, count_ready;
PRInt32 count, count_ready;
static PRStatus _MW_PollInternal(PRWaitGroup *group){    PRRecvWait **waiter;    PRStatus rv = PR_FAILURE;    PRUintn count, count_ready;    PRIntervalTime polling_interval;    group->poller = PR_GetCurrentThread();    while (PR_TRUE)    {        PRIntervalTime now, since_last_poll;        PRPollDesc *poll_list;        while (0 == group->waiter->count)        {            PRStatus st;            st = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT);            if (_prmw_running != group->state)            {                PR_SetError(PR_INVALID_STATE_ERROR, 0);                goto aborted;            }            if (_MW_ABORTED(st)) goto aborted;        }        /*        ** There's something to do. See if our existing polling list        ** is large enough for what we have to do?        */        while (group->polling_count < group->waiter->count)        {            PRUint32 old_count = group->waiter->count;            PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE);            PRSize new_size = sizeof(PRPollDesc) * new_count;            PRPollDesc *old_polling_list = group->polling_list;            PR_Unlock(group->ml);            poll_list = (PRPollDesc*)PR_CALLOC(new_size);            if (NULL == poll_list)            {                PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);                PR_Lock(group->ml);                goto failed_alloc;            }            if (NULL != old_polling_list)                PR_DELETE(old_polling_list);            PR_Lock(group->ml);            if (_prmw_running != group->state)            {                PR_SetError(PR_INVALID_STATE_ERROR, 0);                goto aborted;            }            group->polling_list = poll_list;            group->polling_count = new_count;        }        now = PR_IntervalNow();        polling_interval = max_polling_interval;        since_last_poll = now - group->last_poll;        waiter = &group->waiter->recv_wait;        poll_list = group->polling_list;        for (count = 0; count < group->waiter->count; ++waiter)        {            PR_ASSERT(waiter < &group->waiter->recv_wait                + group->waiter->length);            if (NULL != *waiter)  /* a live one! */            {                if ((PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout)                && (since_last_poll >= (*waiter)->timeout))                    _MW_DoneInternal(group, waiter, PR_MW_TIMEOUT);                else                {                    if (PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout)                    {                        (*waiter)->timeout -= since_last_poll;                        if ((*waiter)->timeout < polling_interval)                            polling_interval = (*waiter)->timeout;                    }                    PR_ASSERT(poll_list < group->polling_list                        + group->polling_count);                    poll_list->fd = (*waiter)->fd;                    poll_list->in_flags = PR_POLL_READ;                    poll_list->out_flags = 0;#if 0                    printf(                        "Polling 0x%x[%d]: [fd: 0x%x, tmo: %u]\n",                        poll_list, count, poll_list->fd, (*waiter)->timeout);#endif                    poll_list += 1;                    count += 1;                }            }        }         PR_ASSERT(count == group->waiter->count);        /*        ** If there are no more threads waiting for completion,        ** we need to return.        */        if ((!PR_CLIST_IS_EMPTY(&group->io_ready))        && (1 == group->waiting_threads)) break;        if (0 == count) continue;  /* wait for new business */        group->last_poll = now;        PR_Unlock(group->ml);        count_ready = PR_Poll(group->polling_list, count, polling_interval);        PR_Lock(group->ml);        if (_prmw_running != group->state)        {            PR_SetError(PR_INVALID_STATE_ERROR, 0);            goto aborted;        }        if (-1 == count_ready)        {            goto failed_poll;  /* that's a shame */        }        else if (0 < count_ready)        {            for (poll_list = group->polling_list; count > 0;            poll_list++, count--)            {                PR_ASSERT(                    poll_list < group->polling_list + group->polling_count);                if (poll_list->out_flags != 0)                {                    waiter = _MW_LookupInternal(group, poll_list->fd);                    /*                    ** If 'waiter' is NULL, that means the wait receive                    ** descriptor has been canceled.                    */                    if (NULL != waiter)                        _MW_DoneInternal(group, waiter, PR_MW_SUCCESS);                }            }        }        /*        ** If there are no more threads waiting for completion,        ** we need to return.        ** This thread was "borrowed" to do the polling, but it really        ** belongs to the client.        */        if ((!PR_CLIST_IS_EMPTY(&group->io_ready))        && (1 == group->waiting_threads)) break;    }    rv = PR_SUCCESS;aborted:failed_poll:failed_alloc:    group->poller = NULL;  /* we were that, not we ain't */    if ((_prmw_running == group->state) && (group->waiting_threads > 1))    {        /* Wake up one thread to become the new poller. */        PR_NotifyCondVar(group->io_complete);    }    return rv;  /* we return with the lock held */}  /* _MW_PollInternal */