Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
w32poll.c File Reference
#include "primpl.h"

Go to the source code of this file.

Classes

struct  select_data_s

Defines

#define FD_SETSIZE   1024

Functions

static void _PR_MD_select_thread (void *cdata)
int _PR_NTFiberSafeSelect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)
PRInt32 _PR_MD_PR_POLL (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)

Class Documentation

struct select_data_s

Definition at line 49 of file w32poll.c.

Collaboration diagram for select_data_s:
Class Members
PRInt32 error
fd_set * ex
fd_set * rd
PRInt32 status
struct timeval * tv
fd_set * wt

Define Documentation

#define FD_SETSIZE   1024

Definition at line 43 of file w32poll.c.


Function Documentation

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

Definition at line 110 of file w32poll.c.

{
    int ready, err;
    fd_set rd, wt, ex;
    fd_set *rdp, *wtp, *exp;
    int nrd, nwt, nex;
    PRFileDesc *bottom;
    PRPollDesc *pd, *epd;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    struct timeval tv, *tvp = NULL;

    if (_PR_PENDING_INTERRUPT(me))
    {
        me->flags &= ~_PR_INTERRUPT;
        PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
        return -1;
    }

    /*
    ** Is it an empty set? If so, just sleep for the timeout and return
    */
    if (0 == npds)
    {
        PR_Sleep(timeout);
        return 0;
    }

    nrd = nwt = nex = 0;
    FD_ZERO(&rd);
    FD_ZERO(&wt);
    FD_ZERO(&ex);

    ready = 0;
    for (pd = pds, epd = pd + npds; pd < epd; pd++)
    {
        SOCKET osfd;
        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, (PRInt16)(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);
            }
            if ((0 != (in_flags_read & out_flags_read))
            || (0 != (in_flags_write & out_flags_write)))
            {
                /* this one's ready right now (buffered input) */
                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)
                    {
                        osfd = (SOCKET) bottom->secret->md.osfd;
                        if (in_flags_read & PR_POLL_READ)
                        {
                            pd->out_flags |= _PR_POLL_READ_SYS_READ;
                            FD_SET(osfd, &rd);
                            nrd++;
                        }
                        if (in_flags_read & PR_POLL_WRITE)
                        {
                            pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
                            FD_SET(osfd, &wt);
                            nwt++;
                        }
                        if (in_flags_write & PR_POLL_READ)
                        {
                            pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
                            FD_SET(osfd, &rd);
                            nrd++;
                        }
                        if (in_flags_write & PR_POLL_WRITE)
                        {
                            pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
                            FD_SET(osfd, &wt);
                            nwt++;
                        }
                        if (pd->in_flags & PR_POLL_EXCEPT) {
                            FD_SET(osfd, &ex);
                            nex++;
                        }
                    }
                }
                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 */

    if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) {
        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
        return -1;
    }

    rdp = (0 == nrd) ? NULL : &rd;
    wtp = (0 == nwt) ? NULL : &wt;
    exp = (0 == nex) ? NULL : &ex;

    if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) {
        PR_Sleep(timeout);
        return 0;
    }

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

#if defined(_PR_GLOBAL_THREADS_ONLY)
    ready = _MD_SELECT(0, rdp, wtp, exp, tvp);
#else
    ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp);
#endif

    /*
    ** 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))
            {
                SOCKET osfd;
                bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
                PR_ASSERT(NULL != bottom);

                osfd = (SOCKET) 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 == SOCKET_ERROR)
    {
        err = WSAGetLastError();
        if (err == WSAENOTSOCK)
        {
            /* Find the bad fds */
            int optval;
            int optlen = sizeof(optval);
            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 (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
                        SO_TYPE, (char *) &optval, &optlen) == -1)
                    {
                        PR_ASSERT(WSAGetLastError() == WSAENOTSOCK);
                        if (WSAGetLastError() == WSAENOTSOCK)
                        {
                            pd->out_flags = PR_POLL_NVAL;
                            ready++;
                        }
                    }
                }
            }
            PR_ASSERT(ready > 0);
        }
        else _PR_MD_MAP_SELECT_ERROR(err);
    }

    return ready;
}

Here is the call graph for this function:

static void _PR_MD_select_thread ( void cdata) [static]

Definition at line 57 of file w32poll.c.

{
    struct select_data_s *cd = (struct select_data_s *)cdata;

    cd->status = select(0, cd->rd, cd->wt, cd->ex, cd->tv);

    if (cd->status == SOCKET_ERROR) {
        cd->error = WSAGetLastError();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _PR_NTFiberSafeSelect ( int  nfds,
fd_set readfds,
fd_set writefds,
fd_set exceptfds,
const struct timeval timeout 
)

Definition at line 68 of file w32poll.c.

{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    int ready;

    if (_PR_IS_NATIVE_THREAD(me)) {
        ready = _MD_SELECT(nfds, readfds, writefds, exceptfds, timeout);
    }
    else
    {
        /*
        ** Creating a new thread on each call!!
        ** I guess web server doesn't use non-block I/O.
        */
        PRThread *selectThread;
        struct select_data_s data;
        data.status = 0;
        data.error = 0;
        data.rd = readfds;
        data.wt = writefds;
        data.ex = exceptfds;
        data.tv = timeout;

        selectThread = PR_CreateThread(
            PR_USER_THREAD, _PR_MD_select_thread, &data,
            PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
        if (selectThread == NULL) return -1;

        PR_JoinThread(selectThread);
        ready = data.status;
        if (ready == SOCKET_ERROR) WSASetLastError(data.error);
    }
    return ready;
}

Here is the call graph for this function:

Here is the caller graph for this function: