Back to index

lightning-sunbird  0.9+nobinonly
uxpoll.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #if defined(_PR_PTHREADS)
00039 
00040 #error "This file should not be compiled"
00041 
00042 #else  /* defined(_PR_PTHREADS) */
00043 
00044 #include "primpl.h"
00045 
00046 #include <sys/time.h>
00047 
00048 #include <fcntl.h>
00049 #ifdef _PR_USE_POLL
00050 #include <poll.h>
00051 #endif
00052 
00053 #if defined(_PR_USE_POLL)
00054 static PRInt32 NativeThreadPoll(
00055     PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
00056 {
00057     /*
00058      * This function is mostly duplicated from ptio.s's PR_Poll().
00059      */
00060     PRInt32 ready = 0;
00061     /*
00062      * For restarting poll() if it is interrupted by a signal.
00063      * We use these variables to figure out how much time has
00064      * elapsed and how much of the timeout still remains.
00065      */
00066     PRIntn index, msecs;
00067     struct pollfd *syspoll = NULL;
00068     PRIntervalTime start, elapsed, remaining;
00069 
00070     syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
00071     if (NULL == syspoll)
00072     {
00073         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
00074         return -1;
00075     }
00076     for (index = 0; index < npds; ++index)
00077     {
00078         PRFileDesc *bottom;
00079         PRInt16 in_flags_read = 0, in_flags_write = 0;
00080         PRInt16 out_flags_read = 0, out_flags_write = 0;
00081 
00082         if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
00083         {
00084             if (pds[index].in_flags & PR_POLL_READ)
00085             {
00086                 in_flags_read = (pds[index].fd->methods->poll)(
00087                     pds[index].fd,
00088                     pds[index].in_flags & ~PR_POLL_WRITE,
00089                     &out_flags_read);
00090             }
00091             if (pds[index].in_flags & PR_POLL_WRITE)
00092             {
00093                 in_flags_write = (pds[index].fd->methods->poll)(
00094                     pds[index].fd,
00095                     pds[index].in_flags & ~PR_POLL_READ,
00096                     &out_flags_write);
00097             }
00098             if ((0 != (in_flags_read & out_flags_read))
00099             || (0 != (in_flags_write & out_flags_write)))
00100             {
00101                 /* this one is ready right now */
00102                 if (0 == ready)
00103                 {
00104                     /*
00105                      * We will return without calling the system
00106                      * poll function.  So zero the out_flags
00107                      * fields of all the poll descriptors before
00108                      * this one.
00109                      */
00110                     int i;
00111                     for (i = 0; i < index; i++)
00112                     {
00113                         pds[i].out_flags = 0;
00114                     }
00115                 }
00116                 ready += 1;
00117                 pds[index].out_flags = out_flags_read | out_flags_write;
00118             }
00119             else
00120             {
00121                 pds[index].out_flags = 0;  /* pre-condition */
00122                 /* now locate the NSPR layer at the bottom of the stack */
00123                 bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER);
00124                 PR_ASSERT(NULL != bottom);  /* what to do about that? */
00125                 if ((NULL != bottom)
00126                 && (_PR_FILEDESC_OPEN == bottom->secret->state))
00127                 {
00128                     if (0 == ready)
00129                     {
00130                         syspoll[index].fd = bottom->secret->md.osfd;
00131                         syspoll[index].events = 0;  /* pre-condition */
00132                         if (in_flags_read & PR_POLL_READ)
00133                         {
00134                             pds[index].out_flags |=
00135                                 _PR_POLL_READ_SYS_READ;
00136                             syspoll[index].events |= POLLIN;
00137                         }
00138                         if (in_flags_read & PR_POLL_WRITE)
00139                         {
00140                             pds[index].out_flags |=
00141                                 _PR_POLL_READ_SYS_WRITE;
00142                             syspoll[index].events |= POLLOUT;
00143                         }
00144                         if (in_flags_write & PR_POLL_READ)
00145                         {
00146                             pds[index].out_flags |=
00147                                 _PR_POLL_WRITE_SYS_READ;
00148                             syspoll[index].events |= POLLIN;
00149                         }
00150                         if (in_flags_write & PR_POLL_WRITE)
00151                         {
00152                             pds[index].out_flags |=
00153                                 _PR_POLL_WRITE_SYS_WRITE;
00154                             syspoll[index].events |= POLLOUT;
00155                         }
00156                         if (pds[index].in_flags & PR_POLL_EXCEPT)
00157                             syspoll[index].events |= POLLPRI;
00158                     }
00159                 }
00160                 else
00161                 {
00162                     if (0 == ready)
00163                     {
00164                         int i;
00165                         for (i = 0; i < index; i++)
00166                         {
00167                             pds[i].out_flags = 0;
00168                         }
00169                     }
00170                     ready += 1;  /* this will cause an abrupt return */
00171                     pds[index].out_flags = PR_POLL_NVAL;  /* bogii */
00172                 }
00173             }
00174         }
00175         else
00176         {
00177             /* make poll() ignore this entry */
00178             syspoll[index].fd = -1;
00179             syspoll[index].events = 0;
00180             pds[index].out_flags = 0;
00181         }
00182     }
00183 
00184     if (0 == ready)
00185     {
00186         switch (timeout)
00187         {
00188             case PR_INTERVAL_NO_WAIT: msecs = 0; break;
00189             case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
00190             default:
00191                 msecs = PR_IntervalToMilliseconds(timeout);
00192                 start = PR_IntervalNow();
00193         }
00194 
00195 retry:
00196         ready = _MD_POLL(syspoll, npds, msecs);
00197         if (-1 == ready)
00198         {
00199             PRIntn oserror = errno;
00200 
00201             if (EINTR == oserror)
00202             {
00203                 if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
00204                 else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0;
00205                 else
00206                 {
00207                     elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
00208                     if (elapsed > timeout) ready = 0;  /* timed out */
00209                     else
00210                     {
00211                         remaining = timeout - elapsed;
00212                         msecs = PR_IntervalToMilliseconds(remaining);
00213                         goto retry;
00214                     }
00215                 }
00216             }
00217             else _PR_MD_MAP_POLL_ERROR(oserror);
00218         }
00219         else if (ready > 0)
00220         {
00221             for (index = 0; index < npds; ++index)
00222             {
00223                 PRInt16 out_flags = 0;
00224                 if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
00225                 {
00226                     if (0 != syspoll[index].revents)
00227                     {
00228                         /*
00229                         ** Set up the out_flags so that it contains the
00230                         ** bits that the highest layer thinks are nice
00231                         ** to have. Then the client of that layer will
00232                         ** call the appropriate I/O function and maybe
00233                         ** the protocol will make progress.
00234                         */
00235                         if (syspoll[index].revents & POLLIN)
00236                         {
00237                             if (pds[index].out_flags
00238                             & _PR_POLL_READ_SYS_READ)
00239                             {
00240                                 out_flags |= PR_POLL_READ;
00241                             }
00242                             if (pds[index].out_flags
00243                             & _PR_POLL_WRITE_SYS_READ)
00244                             {
00245                                 out_flags |= PR_POLL_WRITE;
00246                             }
00247                         }
00248                         if (syspoll[index].revents & POLLOUT)
00249                         {
00250                             if (pds[index].out_flags
00251                             & _PR_POLL_READ_SYS_WRITE)
00252                             {
00253                                 out_flags |= PR_POLL_READ;
00254                             }
00255                             if (pds[index].out_flags
00256                             & _PR_POLL_WRITE_SYS_WRITE)
00257                             {
00258                                 out_flags |= PR_POLL_WRITE;
00259                             }
00260                         }
00261                         if (syspoll[index].revents & POLLPRI)
00262                             out_flags |= PR_POLL_EXCEPT;
00263                         if (syspoll[index].revents & POLLERR)
00264                             out_flags |= PR_POLL_ERR;
00265                         if (syspoll[index].revents & POLLNVAL)
00266                             out_flags |= PR_POLL_NVAL;
00267                         if (syspoll[index].revents & POLLHUP)
00268                             out_flags |= PR_POLL_HUP;
00269                     }
00270                 }
00271                 pds[index].out_flags = out_flags;
00272             }
00273         }
00274     }
00275 
00276     PR_DELETE(syspoll);
00277     return ready;
00278 
00279 }  /* NativeThreadPoll */
00280 #endif  /* defined(_PR_USE_POLL) */
00281 
00282 #if !defined(_PR_USE_POLL)
00283 static PRInt32 NativeThreadSelect(
00284     PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
00285 {
00286     /*
00287      * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
00288      */
00289     fd_set rd, wt, ex;
00290     PRFileDesc *bottom;
00291     PRPollDesc *pd, *epd;
00292     PRInt32 maxfd = -1, ready, err;
00293     PRIntervalTime remaining, elapsed, start;
00294 
00295     struct timeval tv, *tvp = NULL;
00296 
00297     FD_ZERO(&rd);
00298     FD_ZERO(&wt);
00299     FD_ZERO(&ex);
00300 
00301     ready = 0;
00302     for (pd = pds, epd = pd + npds; pd < epd; pd++)
00303     {
00304         PRInt16 in_flags_read = 0, in_flags_write = 0;
00305         PRInt16 out_flags_read = 0, out_flags_write = 0;
00306 
00307         if ((NULL != pd->fd) && (0 != pd->in_flags))
00308         {
00309             if (pd->in_flags & PR_POLL_READ)
00310             {
00311                 in_flags_read = (pd->fd->methods->poll)(
00312                     pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
00313             }
00314             if (pd->in_flags & PR_POLL_WRITE)
00315             {
00316                 in_flags_write = (pd->fd->methods->poll)(
00317                     pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
00318             }
00319             if ((0 != (in_flags_read & out_flags_read))
00320             || (0 != (in_flags_write & out_flags_write)))
00321             {
00322                 /* this one's ready right now */
00323                 if (0 == ready)
00324                 {
00325                     /*
00326                      * We will have to return without calling the
00327                      * system poll/select function.  So zero the
00328                      * out_flags fields of all the poll descriptors
00329                      * before this one.
00330                      */
00331                     PRPollDesc *prev;
00332                     for (prev = pds; prev < pd; prev++)
00333                     {
00334                         prev->out_flags = 0;
00335                     }
00336                 }
00337                 ready += 1;
00338                 pd->out_flags = out_flags_read | out_flags_write;
00339             }
00340             else
00341             {
00342                 pd->out_flags = 0;  /* pre-condition */
00343 
00344                 /* make sure this is an NSPR supported stack */
00345                 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00346                 PR_ASSERT(NULL != bottom);  /* what to do about that? */
00347                 if ((NULL != bottom)
00348                 && (_PR_FILEDESC_OPEN == bottom->secret->state))
00349                 {
00350                     if (0 == ready)
00351                     {
00352                         PRInt32 osfd = bottom->secret->md.osfd;
00353                         if (osfd > maxfd) maxfd = osfd;
00354                         if (in_flags_read & PR_POLL_READ)
00355                         {
00356                             pd->out_flags |= _PR_POLL_READ_SYS_READ;
00357                             FD_SET(osfd, &rd);
00358                         }
00359                         if (in_flags_read & PR_POLL_WRITE)
00360                         {
00361                             pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
00362                             FD_SET(osfd, &wt);
00363                         }
00364                         if (in_flags_write & PR_POLL_READ)
00365                         {
00366                             pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
00367                             FD_SET(osfd, &rd);
00368                         }
00369                         if (in_flags_write & PR_POLL_WRITE)
00370                         {
00371                             pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
00372                             FD_SET(osfd, &wt);
00373                         }
00374                         if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
00375                     }
00376                 }
00377                 else
00378                 {
00379                     if (0 == ready)
00380                     {
00381                         PRPollDesc *prev;
00382                         for (prev = pds; prev < pd; prev++)
00383                         {
00384                             prev->out_flags = 0;
00385                         }
00386                     }
00387                     ready += 1;  /* this will cause an abrupt return */
00388                     pd->out_flags = PR_POLL_NVAL;  /* bogii */
00389                 }
00390             }
00391         }
00392         else
00393         {
00394             pd->out_flags = 0;
00395         }
00396     }
00397 
00398     if (0 != ready) return ready;  /* no need to block */
00399 
00400     remaining = timeout;
00401     start = PR_IntervalNow();
00402 
00403 retry:
00404     if (timeout != PR_INTERVAL_NO_TIMEOUT)
00405     {
00406         PRInt32 ticksPerSecond = PR_TicksPerSecond();
00407         tv.tv_sec = remaining / ticksPerSecond;
00408         tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
00409         tvp = &tv;
00410     }
00411 
00412     ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
00413 
00414     if (ready == -1 && errno == EINTR)
00415     {
00416         if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
00417         else
00418         {
00419             elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
00420             if (elapsed > timeout) ready = 0;  /* timed out */
00421             else
00422             {
00423                 remaining = timeout - elapsed;
00424                 goto retry;
00425             }
00426         }
00427     }
00428 
00429     /*
00430     ** Now to unravel the select sets back into the client's poll
00431     ** descriptor list. Is this possibly an area for pissing away
00432     ** a few cycles or what?
00433     */
00434     if (ready > 0)
00435     {
00436         ready = 0;
00437         for (pd = pds, epd = pd + npds; pd < epd; pd++)
00438         {
00439             PRInt16 out_flags = 0;
00440             if ((NULL != pd->fd) && (0 != pd->in_flags))
00441             {
00442                 PRInt32 osfd;
00443                 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00444                 PR_ASSERT(NULL != bottom);
00445 
00446                 osfd = bottom->secret->md.osfd;
00447 
00448                 if (FD_ISSET(osfd, &rd))
00449                 {
00450                     if (pd->out_flags & _PR_POLL_READ_SYS_READ)
00451                         out_flags |= PR_POLL_READ;
00452                     if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
00453                         out_flags |= PR_POLL_WRITE;
00454                 } 
00455                 if (FD_ISSET(osfd, &wt))
00456                 {
00457                     if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
00458                         out_flags |= PR_POLL_READ;
00459                     if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
00460                         out_flags |= PR_POLL_WRITE;
00461                 } 
00462                 if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
00463             }
00464             pd->out_flags = out_flags;
00465             if (out_flags) ready++;
00466         }
00467         PR_ASSERT(ready > 0);
00468     }
00469     else if (ready < 0)
00470     {
00471         err = _MD_ERRNO();
00472         if (err == EBADF)
00473         {
00474             /* Find the bad fds */
00475             ready = 0;
00476             for (pd = pds, epd = pd + npds; pd < epd; pd++)
00477             {
00478                 pd->out_flags = 0;
00479                 if ((NULL != pd->fd) && (0 != pd->in_flags))
00480                 {
00481                     bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00482                     if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
00483                     {
00484                         pd->out_flags = PR_POLL_NVAL;
00485                         ready++;
00486                     }
00487                 }
00488             }
00489             PR_ASSERT(ready > 0);
00490         }
00491         else _PR_MD_MAP_SELECT_ERROR(err);
00492     }
00493 
00494     return ready;
00495 }  /* NativeThreadSelect */
00496 #endif  /* !defined(_PR_USE_POLL) */
00497 
00498 static PRInt32 LocalThreads(
00499     PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
00500 {
00501     PRPollDesc *pd, *epd;
00502     PRInt32 ready, pdcnt;
00503     _PRUnixPollDesc *unixpds, *unixpd;
00504 
00505     /*
00506      * XXX
00507      *        PRPollDesc has a PRFileDesc field, fd, while the IOQ
00508      *        is a list of PRPollQueue structures, each of which contains
00509      *        a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
00510      *        the OS file descriptor, osfd, and not a PRFileDesc.
00511      *        So, we have allocate memory for _PRUnixPollDesc structures,
00512      *        copy the flags information from the pds list and have pq
00513      *        point to this list of _PRUnixPollDesc structures.
00514      *
00515      *        It would be better if the memory allocation can be avoided.
00516      */
00517 
00518     unixpd = unixpds = (_PRUnixPollDesc*)
00519         PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
00520     if (NULL == unixpds)
00521     {
00522         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
00523         return -1;
00524     }
00525 
00526     ready = 0;
00527     for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++)
00528     {
00529         PRFileDesc *bottom;
00530         PRInt16 in_flags_read = 0, in_flags_write = 0;
00531         PRInt16 out_flags_read = 0, out_flags_write = 0;
00532 
00533         if ((NULL != pd->fd) && (0 != pd->in_flags))
00534         {
00535             if (pd->in_flags & PR_POLL_READ)
00536             {
00537                 in_flags_read = (pd->fd->methods->poll)(
00538                     pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
00539             }
00540             if (pd->in_flags & PR_POLL_WRITE)
00541             {
00542                 in_flags_write = (pd->fd->methods->poll)(
00543                     pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
00544             }
00545             if ((0 != (in_flags_read & out_flags_read))
00546             || (0 != (in_flags_write & out_flags_write)))
00547             {
00548                 /* this one's ready right now */
00549                 if (0 == ready)
00550                 {
00551                     /*
00552                      * We will have to return without calling the
00553                      * system poll/select function.  So zero the
00554                      * out_flags fields of all the poll descriptors
00555                      * before this one.
00556                      */
00557                     PRPollDesc *prev;
00558                     for (prev = pds; prev < pd; prev++)
00559                     {
00560                         prev->out_flags = 0;
00561                     }
00562                 }
00563                 ready += 1;
00564                 pd->out_flags = out_flags_read | out_flags_write;
00565             }
00566             else
00567             {
00568                 pd->out_flags = 0;  /* pre-condition */
00569                 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00570                 PR_ASSERT(NULL != bottom);  /* what to do about that? */
00571                 if ((NULL != bottom)
00572                 && (_PR_FILEDESC_OPEN == bottom->secret->state))
00573                 {
00574                     if (0 == ready)
00575                     {
00576                         unixpd->osfd = bottom->secret->md.osfd;
00577                         unixpd->in_flags = 0;
00578                         if (in_flags_read & PR_POLL_READ)
00579                         {
00580                             unixpd->in_flags |= _PR_UNIX_POLL_READ;
00581                             pd->out_flags |= _PR_POLL_READ_SYS_READ;
00582                         }
00583                         if (in_flags_read & PR_POLL_WRITE)
00584                         {
00585                             unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
00586                             pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
00587                         }
00588                         if (in_flags_write & PR_POLL_READ)
00589                         {
00590                             unixpd->in_flags |= _PR_UNIX_POLL_READ;
00591                             pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
00592                         }
00593                         if (in_flags_write & PR_POLL_WRITE)
00594                         {
00595                             unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
00596                             pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
00597                         }
00598                         if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT)
00599                         {
00600                             unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
00601                         }
00602                         unixpd++; pdcnt++;
00603                     }
00604                 }
00605                 else
00606                 {
00607                     if (0 == ready)
00608                     {
00609                         PRPollDesc *prev;
00610                         for (prev = pds; prev < pd; prev++)
00611                         {
00612                             prev->out_flags = 0;
00613                         }
00614                     }
00615                     ready += 1;  /* this will cause an abrupt return */
00616                     pd->out_flags = PR_POLL_NVAL;  /* bogii */
00617                 }
00618             }
00619         }
00620     }
00621 
00622     if (0 != ready)
00623     {
00624         /* no need to block */
00625         PR_DELETE(unixpds);
00626         return ready;
00627     }
00628 
00629     ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
00630 
00631     /*
00632      * Copy the out_flags from the _PRUnixPollDesc structures to the
00633      * user's PRPollDesc structures and free the allocated memory
00634      */
00635     unixpd = unixpds;
00636     for (pd = pds, epd = pd + npds; pd < epd; pd++)
00637     {
00638         PRInt16 out_flags = 0;
00639         if ((NULL != pd->fd) && (0 != pd->in_flags))
00640         {
00641             /*
00642              * take errors from the poll operation,
00643              * the R/W bits from the request
00644              */
00645             if (0 != unixpd->out_flags)
00646             {
00647                 if (unixpd->out_flags & _PR_UNIX_POLL_READ)
00648                 {
00649                     if (pd->out_flags & _PR_POLL_READ_SYS_READ)
00650                         out_flags |= PR_POLL_READ;
00651                     if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
00652                         out_flags |= PR_POLL_WRITE;
00653                 }
00654                 if (unixpd->out_flags & _PR_UNIX_POLL_WRITE)
00655                 {
00656                     if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
00657                         out_flags |= PR_POLL_READ;
00658                     if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
00659                         out_flags |= PR_POLL_WRITE;
00660                 }
00661                 if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT)
00662                     out_flags |= PR_POLL_EXCEPT;
00663                 if (unixpd->out_flags & _PR_UNIX_POLL_ERR)
00664                     out_flags |= PR_POLL_ERR;
00665                 if (unixpd->out_flags & _PR_UNIX_POLL_NVAL)
00666                     out_flags |= PR_POLL_NVAL;
00667                 if (unixpd->out_flags & _PR_UNIX_POLL_HUP)
00668                     out_flags |= PR_POLL_HUP;
00669             }
00670             unixpd++;
00671         }
00672         pd->out_flags = out_flags;
00673     }
00674 
00675     PR_DELETE(unixpds);
00676 
00677     return ready;
00678 }  /* LocalThreads */
00679 
00680 #if defined(_PR_USE_POLL)
00681 #define NativeThreads NativeThreadPoll
00682 #else
00683 #define NativeThreads NativeThreadSelect
00684 #endif
00685 
00686 PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
00687 {
00688     PRInt32 rv = 0;
00689     PRThread *me = _PR_MD_CURRENT_THREAD();
00690 
00691     if (_PR_PENDING_INTERRUPT(me))
00692     {
00693         me->flags &= ~_PR_INTERRUPT;
00694         PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00695         return -1;
00696     }
00697     if (0 == npds) PR_Sleep(timeout);
00698     else if (_PR_IS_NATIVE_THREAD(me))
00699         rv = NativeThreads(pds, npds, timeout);
00700     else rv = LocalThreads(pds, npds, timeout);
00701 
00702     return rv;
00703 }  /* _MD_pr_poll */
00704 
00705 #endif  /* defined(_PR_PTHREADS) */               
00706 
00707 /* uxpoll.c */
00708