Home | History | Annotate | Download | only in arch-mips
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <portability.h>
     18 #include <poll.h>
     19 #include <poll_portable.h>
     20 
     21 /*
     22  *_XOPEN_SOURCE added the ability to not only poll for data coming in or out
     23  * but now also the ability to poll for high priority input and output. Though
     24  * the normal priority is equivalent to the original I/O it was assigned new bits:
     25  *       POLLIN  Equivalent to POLLRDNORM
     26  *       POLLOUT Equivalent to POLLWRNORM
     27  *
     28  * The Linux kernel sets both POLLIN and POLLRDNORM when data is available and sets
     29  * both POLLOUT and POLLWRNORM when data can be written; so the new priority BAND bits
     30  * just supplement the meaning of the prior POLLIN and POLLOUT bits as well as the
     31  * new POLLRDNORM and POLLWRNORM bits.
     32  *
     33  * The DECNet Protocol can set the poll in  priority flag, POLLRDBAND.
     34  * ATM as well as a whole bunch of other protocols can set the poll out priority flag,
     35  * POLLWRBAND.
     36  *
     37  * MIPS and SPARC likely assigned the new XOPEN poll out event flags in UNIX well before
     38  * UNIX was ported to X86.  It appears that Intel chose different bits and that was
     39  * established by Linus as the the generic case and later also chosen by ARM.
     40  *
     41  *     POLLWRNORM:0x100 -  MIPS used POLLOUT:0x0004, which is equivalent in meaning.
     42  *
     43  *     POLLWRBAND:0x200 -  MIPS used 0x0100. which is POLLWRNORM:0x100.
     44  *
     45  * Summary:
     46  * ========
     47  *    Both Normal and Priority flags can be mapped to MIPS flags (left to right below).
     48  *    Only the Priority poll out flag can be mapped back to portable because MIPS
     49  *    is using the same number as POLLOUT for POLLWRNORM (right to left below).
     50  *
     51  *                    ARM/GENERIC/PORTABLE           MIPS
     52  *                    ====================          ======
     53  *      POLLIN          0x0001                      0x0001
     54  *      POLLPRI         0x0002                      0x0002
     55  *      POLLOUT         0x0004 <-----+              0x0004
     56  *      POLLERR         0x0008        \             0x0008
     57  *      POLLHUP         0x0010         \            0x0010
     58  *      POLLNVAL        0x0020          \           0x0020
     59  *      POLLRDNORM      0x0040           \          0x0040
     60  *      POLLRDBAND      0x0080            \         0x0080
     61  *      POLLWRNORM      0x0100  -----------+<---->  0x0004
     62  *      POLLWRBAND      0x0200 <----------------->  0x0100
     63  *      POLLMSG         0x0400                      0x0400
     64  *      POLLREMOVE      0x1000                      0x1000
     65  *      POLLRDHUP       0x2000                      0x2000
     66  *
     67  *  The loss of the high priority notice for the polling
     68  *  of output data is likely minor as it was only being used
     69  *  in DECNet. Also, the poll system call and device poll
     70  *  implementations processes POLLOUT and POLLWRNORM event
     71  *  flags the same.
     72  */
     73 
     74 #if POLLWRNORM_PORTABLE==POLLWRNORM
     75 #error Bad build environment
     76 #endif
     77 
     78 static inline short mips_change_portable_events(short portable_events)
     79 {
     80     /* MIPS has different POLLWRNORM and POLLWRBAND. */
     81     if (portable_events & POLLWRNORM_PORTABLE) {
     82         portable_events &= ~POLLWRNORM_PORTABLE;
     83         portable_events |= POLLWRNORM;
     84     }
     85     if (portable_events & POLLWRBAND_PORTABLE) {
     86         portable_events &= ~POLLWRBAND_PORTABLE;
     87         portable_events |= POLLWRBAND;
     88     }
     89 
     90     return portable_events;
     91 }
     92 
     93 static inline short change_mips_events(short mips_events)
     94 {
     95     /*
     96      * MIPS POLLWRNORM equals MIPS POLLOUT, which is the same as POLLOUT_PORTABLE;
     97      * so we just map POLLWRBAND to POLLWRBAND_PORTABLE.
     98      */
     99     if (mips_events & POLLWRBAND) {
    100         mips_events &= ~POLLWRBAND;
    101         mips_events |= POLLWRBAND_PORTABLE;
    102     }
    103 
    104     return mips_events;
    105 }
    106 
    107 extern int poll(struct pollfd *, nfds_t, long);
    108 
    109 int WRAP(poll)(struct pollfd *fds, nfds_t nfds, long timeout)
    110 {
    111   nfds_t i;
    112   int ret;
    113 
    114   for (i = 0; i < nfds; i++)
    115       fds->events = mips_change_portable_events(fds->events);
    116 
    117   ret = REAL(poll)(fds, nfds, timeout);
    118 
    119   for (i = 0; i < nfds; i++) {
    120       fds->events = change_mips_events(fds->events);
    121       fds->revents = change_mips_events(fds->revents);
    122   }
    123 
    124   return ret;
    125 }
    126