Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions
uxpoll.c File Reference
#include "primpl.h"
#include <sys/time.h>
#include <fcntl.h>

Go to the source code of this file.

Defines

#define NativeThreads   NativeThreadSelect

Functions

static PRInt32 NativeThreadSelect (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
static PRInt32 LocalThreads (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
PRInt32 _MD_pr_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)

Define Documentation

Definition at line 683 of file uxpoll.c.


Function Documentation

PRInt32 _MD_pr_poll ( PRPollDesc pds,
PRIntn  npds,
PRIntervalTime  timeout 
)

Definition at line 686 of file uxpoll.c.

{
    PRInt32 rv = 0;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (_PR_PENDING_INTERRUPT(me))
    {
        me->flags &= ~_PR_INTERRUPT;
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        return -1;
    }
    if (0 == npds) PR_Sleep(timeout);
    else if (_PR_IS_NATIVE_THREAD(me))
        rv = NativeThreads(pds, npds, timeout);
    else rv = LocalThreads(pds, npds, timeout);

    return rv;
}  /* _MD_pr_poll */

Here is the call graph for this function:

static PRInt32 LocalThreads ( PRPollDesc pds,
PRIntn  npds,
PRIntervalTime  timeout 
) [static]

Definition at line 498 of file uxpoll.c.

{
    PRPollDesc *pd, *epd;
    PRInt32 ready, pdcnt;
    _PRUnixPollDesc *unixpds, *unixpd;

    /*
     * XXX
     *        PRPollDesc has a PRFileDesc field, fd, while the IOQ
     *        is a list of PRPollQueue structures, each of which contains
     *        a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
     *        the OS file descriptor, osfd, and not a PRFileDesc.
     *        So, we have allocate memory for _PRUnixPollDesc structures,
     *        copy the flags information from the pds list and have pq
     *        point to this list of _PRUnixPollDesc structures.
     *
     *        It would be better if the memory allocation can be avoided.
     */

    unixpd = unixpds = (_PRUnixPollDesc*)
        PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
    if (NULL == unixpds)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return -1;
    }

    ready = 0;
    for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++)
    {
        PRFileDesc *bottom;
        PRInt16 in_flags_read = 0, in_flags_write = 0;
        PRInt16 out_flags_read = 0, out_flags_write = 0;

        if ((NULL != pd->fd) && (0 != pd->in_flags))
        {
            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)))
            {
                /* 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 */
                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)
                    {
                        unixpd->osfd = bottom->secret->md.osfd;
                        unixpd->in_flags = 0;
                        if (in_flags_read & PR_POLL_READ)
                        {
                            unixpd->in_flags |= _PR_UNIX_POLL_READ;
                            pd->out_flags |= _PR_POLL_READ_SYS_READ;
                        }
                        if (in_flags_read & PR_POLL_WRITE)
                        {
                            unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
                            pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
                        }
                        if (in_flags_write & PR_POLL_READ)
                        {
                            unixpd->in_flags |= _PR_UNIX_POLL_READ;
                            pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
                        }
                        if (in_flags_write & PR_POLL_WRITE)
                        {
                            unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
                            pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
                        }
                        if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT)
                        {
                            unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
                        }
                        unixpd++; pdcnt++;
                    }
                }
                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)
    {
        /* no need to block */
        PR_DELETE(unixpds);
        return ready;
    }

    ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);

    /*
     * Copy the out_flags from the _PRUnixPollDesc structures to the
     * user's PRPollDesc structures and free the allocated memory
     */
    unixpd = unixpds;
    for (pd = pds, epd = pd + npds; pd < epd; pd++)
    {
        PRInt16 out_flags = 0;
        if ((NULL != pd->fd) && (0 != pd->in_flags))
        {
            /*
             * take errors from the poll operation,
             * the R/W bits from the request
             */
            if (0 != unixpd->out_flags)
            {
                if (unixpd->out_flags & _PR_UNIX_POLL_READ)
                {
                    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;
                }
                if (unixpd->out_flags & _PR_UNIX_POLL_WRITE)
                {
                    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 (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT)
                    out_flags |= PR_POLL_EXCEPT;
                if (unixpd->out_flags & _PR_UNIX_POLL_ERR)
                    out_flags |= PR_POLL_ERR;
                if (unixpd->out_flags & _PR_UNIX_POLL_NVAL)
                    out_flags |= PR_POLL_NVAL;
                if (unixpd->out_flags & _PR_UNIX_POLL_HUP)
                    out_flags |= PR_POLL_HUP;
            }
            unixpd++;
        }
        pd->out_flags = out_flags;
    }

    PR_DELETE(unixpds);

    return ready;
}  /* LocalThreads */

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 NativeThreadSelect ( PRPollDesc pds,
PRIntn  npds,
PRIntervalTime  timeout 
) [static]

Definition at line 283 of file uxpoll.c.

{
    /*
     * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
     */
    fd_set rd, wt, ex;
    PRFileDesc *bottom;
    PRPollDesc *pd, *epd;
    PRInt32 maxfd = -1, ready, err;
    PRIntervalTime remaining, elapsed, start;

    struct timeval tv, *tvp = NULL;

    FD_ZERO(&rd);
    FD_ZERO(&wt);
    FD_ZERO(&ex);

    ready = 0;
    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;

        if ((NULL != pd->fd) && (0 != pd->in_flags))
        {
            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)))
            {
                /* 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 */
                }
            }
        }
        else
        {
            pd->out_flags = 0;
        }
    }

    if (0 != ready) return ready;  /* no need to block */

    remaining = timeout;
    start = PR_IntervalNow();

retry:
    if (timeout != PR_INTERVAL_NO_TIMEOUT)
    {
        PRInt32 ticksPerSecond = PR_TicksPerSecond();
        tv.tv_sec = remaining / ticksPerSecond;
        tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
        tvp = &tv;
    }

    ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);

    if (ready == -1 && errno == EINTR)
    {
        if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
        else
        {
            elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
            if (elapsed > timeout) ready = 0;  /* timed out */
            else
            {
                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;
        for (pd = pds, epd = pd + npds; pd < epd; pd++)
        {
            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;

                if (FD_ISSET(osfd, &rd))
                {
                    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;
                } 
                if (FD_ISSET(osfd, &wt))
                {
                    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;
            }
            pd->out_flags = out_flags;
            if (out_flags) ready++;
        }
        PR_ASSERT(ready > 0);
    }
    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;
}  /* NativeThreadSelect */

Here is the call graph for this function: