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