nsprpub/pr/src/md/os2/os2poll.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * This file implements _PR_MD_PR_POLL for OS/2.
     8  */
    10 #include <sys/time.h> /* For timeval. */
    12 #include "primpl.h"
    14 #ifndef BSD_SELECT
    15 /* Utility functions called when using OS/2 select */
    17 PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
    18 {
    19   int i;
    20   PRBool isSet = PR_FALSE;
    22   for( i = start; i < start+count; i++ )
    23   {
    24     if( socks[i] == osfd )
    25       isSet = PR_TRUE;
    26   }
    28   return isSet; 
    29 }
    30 #endif
    32 PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
    33 {
    34 #ifdef BSD_SELECT
    35     fd_set rd, wt, ex;
    36 #else
    37     int rd, wt, ex;
    38     int* socks;
    39     unsigned long msecs;
    40     int i, j;
    41 #endif
    42     PRFileDesc *bottom;
    43     PRPollDesc *pd, *epd;
    44     PRInt32 maxfd = -1, ready, err;
    45     PRIntervalTime remaining, elapsed, start;
    47 #ifdef BSD_SELECT
    48     struct timeval tv, *tvp = NULL;
    50     FD_ZERO(&rd);
    51     FD_ZERO(&wt);
    52     FD_ZERO(&ex);
    53 #else
    54     rd = 0;
    55     wt = 0;
    56     ex = 0;
    57     socks = (int) PR_MALLOC( npds * 3 * sizeof(int) );
    59     if (!socks)
    60     {
    61         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    62         return -1;
    63     }
    64 #endif
    66     ready = 0;
    67     for (pd = pds, epd = pd + npds; pd < epd; pd++)
    68     {
    69         PRInt16 in_flags_read = 0, in_flags_write = 0;
    70         PRInt16 out_flags_read = 0, out_flags_write = 0;
    72         if ((NULL != pd->fd) && (0 != pd->in_flags))
    73         {
    74             if (pd->in_flags & PR_POLL_READ)
    75             {
    76                 in_flags_read = (pd->fd->methods->poll)(
    77                     pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
    78             }
    79             if (pd->in_flags & PR_POLL_WRITE)
    80             {
    81                 in_flags_write = (pd->fd->methods->poll)(
    82                     pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
    83             }
    84             if ((0 != (in_flags_read & out_flags_read)) ||
    85                 (0 != (in_flags_write & out_flags_write)))
    86             {
    87                 /* this one's ready right now */
    88                 if (0 == ready)
    89                 {
    90                     /*
    91                      * We will have to return without calling the
    92                      * system poll/select function.  So zero the
    93                      * out_flags fields of all the poll descriptors
    94                      * before this one.
    95                      */
    96                     PRPollDesc *prev;
    97                     for (prev = pds; prev < pd; prev++)
    98                     {
    99                         prev->out_flags = 0;
   100                     }
   101                 }
   102                 ready += 1;
   103                 pd->out_flags = out_flags_read | out_flags_write;
   104             }
   105             else
   106             {
   107                 pd->out_flags = 0;  /* pre-condition */
   109                 /* make sure this is an NSPR supported stack */
   110                 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   111                 PR_ASSERT(NULL != bottom);  /* what to do about that? */
   112                 if ((NULL != bottom) &&
   113                     (_PR_FILEDESC_OPEN == bottom->secret->state))
   114                 {
   115                     if (0 == ready)
   116                     {
   117                         PRInt32 osfd = bottom->secret->md.osfd;
   118                         if (osfd > maxfd) 
   119                             maxfd = osfd;
   120                         if (in_flags_read & PR_POLL_READ)
   121                         {
   122                             pd->out_flags |= _PR_POLL_READ_SYS_READ;
   123 #ifdef BSD_SELECT
   124                             FD_SET(osfd, &rd);
   125 #else
   126                             socks[rd] = osfd;
   127                             rd++;              
   128 #endif
   129                         }
   130                         if (in_flags_read & PR_POLL_WRITE)
   131                         {
   132                             pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
   133 #ifdef BSD_SELECT
   134                             FD_SET(osfd, &wt);
   135 #else
   136                             socks[npds+wt] = osfd;
   137                             wt++;              
   138 #endif
   139                         }
   140                         if (in_flags_write & PR_POLL_READ)
   141                         {
   142                             pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
   143 #ifdef BSD_SELECT
   144                             FD_SET(osfd, &rd);
   145 #else
   146                             socks[rd] = osfd;
   147                             rd++;              
   148 #endif
   149                         }
   150                         if (in_flags_write & PR_POLL_WRITE)
   151                         {
   152                             pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
   153 #ifdef BSD_SELECT
   154                             FD_SET(osfd, &wt);
   155 #else
   156                             socks[npds+wt] = osfd;
   157                             wt++;              
   158 #endif
   159                         }
   160                         if (pd->in_flags & PR_POLL_EXCEPT)
   161                         {
   162 #ifdef BSD_SELECT
   163                             FD_SET(osfd, &ex);
   164 #else
   165                             socks[npds*2+ex] = osfd;
   166                             ex++;
   167 #endif
   168                         }
   169                     }
   170                 }
   171                 else
   172                 {
   173                     if (0 == ready)
   174                     {
   175                         PRPollDesc *prev;
   176                         for (prev = pds; prev < pd; prev++)
   177                         {
   178                             prev->out_flags = 0;
   179                         }
   180                     }
   181                     ready += 1;  /* this will cause an abrupt return */
   182                     pd->out_flags = PR_POLL_NVAL;  /* bogii */
   183                 }
   184             }
   185         }
   186         else
   187         {
   188             pd->out_flags = 0;
   189         }
   190     }
   192     if (0 != ready)
   193     {
   194 #ifndef BSD_SELECT
   195         PR_Free(socks);
   196 #endif
   197         return ready;  /* no need to block */
   198     }
   200     remaining = timeout;
   201     start = PR_IntervalNow();
   203 retry:
   204 #ifdef BSD_SELECT
   205     if (timeout != PR_INTERVAL_NO_TIMEOUT)
   206     {
   207         PRInt32 ticksPerSecond = PR_TicksPerSecond();
   208         tv.tv_sec = remaining / ticksPerSecond;
   209         tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
   210         tvp = &tv;
   211     }
   213     ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
   214 #else
   215     switch (timeout)
   216     {
   217         case PR_INTERVAL_NO_WAIT:
   218             msecs = 0;
   219             break;
   220         case PR_INTERVAL_NO_TIMEOUT:
   221             msecs = -1;
   222             break;
   223         default:
   224             msecs = PR_IntervalToMilliseconds(remaining);
   225     }
   227      /* compact array */
   228     for( i = rd, j = npds; j < npds+wt; i++,j++ )
   229         socks[i] = socks[j];
   230     for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
   231         socks[i] = socks[j];
   233     ready = os2_select(socks, rd, wt, ex, msecs);
   234 #endif
   236     if (ready == -1 && errno == EINTR)
   237     {
   238         if (timeout == PR_INTERVAL_NO_TIMEOUT)
   239             goto retry;
   240         else
   241         {
   242             elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
   243             if (elapsed > timeout)
   244                 ready = 0;  /* timed out */
   245             else
   246             {
   247                 remaining = timeout - elapsed;
   248                 goto retry;
   249             }
   250         }
   251     }
   253     /*
   254     ** Now to unravel the select sets back into the client's poll
   255     ** descriptor list. Is this possibly an area for pissing away
   256     ** a few cycles or what?
   257     */
   258     if (ready > 0)
   259     {
   260         ready = 0;
   261         for (pd = pds, epd = pd + npds; pd < epd; pd++)
   262         {
   263             PRInt16 out_flags = 0;
   264             if ((NULL != pd->fd) && (0 != pd->in_flags))
   265             {
   266                 PRInt32 osfd;
   267                 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   268                 PR_ASSERT(NULL != bottom);
   270                 osfd = bottom->secret->md.osfd;
   272 #ifdef BSD_SELECT
   273                 if (FD_ISSET(osfd, &rd))
   274 #else
   275                 if( IsSocketSet(osfd, socks, 0, rd) )        
   276 #endif
   277                 {
   278                     if (pd->out_flags & _PR_POLL_READ_SYS_READ)
   279                         out_flags |= PR_POLL_READ;
   280                     if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
   281                         out_flags |= PR_POLL_WRITE;
   282                 } 
   284 #ifdef BSD_SELECT
   285                 if (FD_ISSET(osfd, &wt))
   286 #else
   287                 if( IsSocketSet(osfd, socks, rd, wt) )        
   288 #endif
   289                 {
   290                     if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
   291                         out_flags |= PR_POLL_READ;
   292                     if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
   293                         out_flags |= PR_POLL_WRITE;
   294                 } 
   296 #ifdef BSD_SELECT
   297                 if (FD_ISSET(osfd, &ex))
   298 #else
   299                 if( IsSocketSet(osfd, socks, rd+wt, ex) )        
   300 #endif
   301                 {
   302                     out_flags |= PR_POLL_EXCEPT;
   303                 }
   304             }
   305             pd->out_flags = out_flags;
   306             if (out_flags) ready++;
   307         }
   308         PR_ASSERT(ready > 0);
   309     }
   310     else if (ready < 0)
   311     {
   312         err = _MD_ERRNO();
   313         if (err == EBADF)
   314         {
   315             /* Find the bad fds */
   316             int optval;
   317             int optlen = sizeof(optval);
   318             ready = 0;
   319             for (pd = pds, epd = pd + npds; pd < epd; pd++)
   320             {
   321                 pd->out_flags = 0;
   322                 if ((NULL != pd->fd) && (0 != pd->in_flags))
   323                 {
   324                     bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   325                     if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
   326                         SO_TYPE, (char *) &optval, &optlen) == -1)
   327                     {
   328                         PR_ASSERT(sock_errno() == ENOTSOCK);
   329                         if (sock_errno() == ENOTSOCK)
   330                         {
   331                             pd->out_flags = PR_POLL_NVAL;
   332                             ready++;
   333                         }
   334                     }
   335                 }
   336             }
   337             PR_ASSERT(ready > 0);
   338         }
   339         else
   340             _PR_MD_MAP_SELECT_ERROR(err);
   341     }
   343 #ifndef BSD_SELECT
   344     PR_Free(socks);
   345 #endif
   346     return ready;
   347 }

mercurial