• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mips_change_portable_events(short portable_events)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 
change_mips_events(short mips_events)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, int);
108 
WRAP(poll)109 int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int 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