diff nspr/pr/src/md/windows/w32poll.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nspr/pr/src/md/windows/w32poll.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * This file implements _PR_MD_PR_POLL for Win32.
+ */
+
+/* The default value of FD_SETSIZE is 64. */
+#define FD_SETSIZE 1024
+
+#include "primpl.h"
+
+#if !defined(_PR_GLOBAL_THREADS_ONLY)
+
+struct select_data_s {
+    PRInt32 status;
+    PRInt32 error;
+    fd_set *rd, *wt, *ex;
+    const struct timeval *tv;
+};
+
+static void
+_PR_MD_select_thread(void *cdata)
+{
+    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();
+    }
+}
+
+int _PR_NTFiberSafeSelect(
+    int nfds,
+    fd_set *readfds,
+    fd_set *writefds,
+    fd_set *exceptfds,
+    const struct timeval *timeout)
+{
+    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;
+}
+
+#endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */
+
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+    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 */
+
+    /*
+     * FD_SET does nothing if the fd_set's internal fd_array is full.  If
+     * nrd, nwt, or nex is greater than FD_SETSIZE, we know FD_SET must
+     * have failed to insert an osfd into the corresponding fd_set, and
+     * therefore we should fail.
+     */
+    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;
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)