xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/poll/os2/pollset.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  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 "apr.h"
18 #include "apr_poll.h"
19 #include "apr_arch_networkio.h"
20 
21 
22 
23 struct apr_pollset_t {
24     apr_pool_t *pool;
25     apr_uint32_t nelts;
26     apr_uint32_t nalloc;
27     int *pollset;
28     int num_read;
29     int num_write;
30     int num_except;
31     int num_total;
32     apr_pollfd_t *query_set;
33     apr_pollfd_t *result_set;
34 };
35 
36 
37 
apr_pollset_create(apr_pollset_t ** pollset,apr_uint32_t size,apr_pool_t * p,apr_uint32_t flags)38 APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
39                                              apr_uint32_t size,
40                                              apr_pool_t *p,
41                                              apr_uint32_t flags)
42 {
43     *pollset = apr_palloc(p, sizeof(**pollset));
44     (*pollset)->pool = p;
45     (*pollset)->nelts = 0;
46     (*pollset)->nalloc = size;
47     (*pollset)->pollset = apr_palloc(p, size * sizeof(int) * 3);
48     (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
49     (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
50     (*pollset)->num_read = -1;
51     return APR_SUCCESS;
52 }
53 
apr_pollset_create_ex(apr_pollset_t ** pollset,apr_uint32_t size,apr_pool_t * p,apr_uint32_t flags,apr_pollset_method_e method)54 APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
55                                                 apr_uint32_t size,
56                                                 apr_pool_t *p,
57                                                 apr_uint32_t flags,
58                                                 apr_pollset_method_e method)
59 {
60     return apr_pollset_create(pollset, size, p, flags);
61 }
62 
apr_pollset_destroy(apr_pollset_t * pollset)63 APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
64 {
65     /* A no-op function for now.  If we later implement /dev/poll
66      * support, we'll need to close the /dev/poll fd here
67      */
68     return APR_SUCCESS;
69 }
70 
71 
72 
apr_pollset_add(apr_pollset_t * pollset,const apr_pollfd_t * descriptor)73 APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
74                                           const apr_pollfd_t *descriptor)
75 {
76     if (pollset->nelts == pollset->nalloc) {
77         return APR_ENOMEM;
78     }
79 
80     pollset->query_set[pollset->nelts] = *descriptor;
81 
82     if (descriptor->desc_type != APR_POLL_SOCKET) {
83         return APR_EBADF;
84     }
85 
86     pollset->nelts++;
87     pollset->num_read = -1;
88     return APR_SUCCESS;
89 }
90 
91 
92 
apr_pollset_remove(apr_pollset_t * pollset,const apr_pollfd_t * descriptor)93 APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
94                                              const apr_pollfd_t *descriptor)
95 {
96     apr_uint32_t i;
97 
98     for (i = 0; i < pollset->nelts; i++) {
99         if (descriptor->desc.s == pollset->query_set[i].desc.s) {
100             /* Found an instance of the fd: remove this and any other copies */
101             apr_uint32_t dst = i;
102             apr_uint32_t old_nelts = pollset->nelts;
103             pollset->nelts--;
104 
105             for (i++; i < old_nelts; i++) {
106                 if (descriptor->desc.s == pollset->query_set[i].desc.s) {
107                     pollset->nelts--;
108                 }
109                 else {
110                     pollset->pollset[dst] = pollset->pollset[i];
111                     pollset->query_set[dst] = pollset->query_set[i];
112                     dst++;
113                 }
114             }
115 
116             pollset->num_read = -1;
117             return APR_SUCCESS;
118         }
119     }
120 
121     return APR_NOTFOUND;
122 }
123 
124 
125 
make_pollset(apr_pollset_t * pollset)126 static void make_pollset(apr_pollset_t *pollset)
127 {
128     int i;
129     int pos = 0;
130 
131     pollset->num_read = 0;
132     pollset->num_write = 0;
133     pollset->num_except = 0;
134 
135     for (i = 0; i < pollset->nelts; i++) {
136         if (pollset->query_set[i].reqevents & APR_POLLIN) {
137             pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
138             pollset->num_read++;
139         }
140     }
141 
142     for (i = 0; i < pollset->nelts; i++) {
143         if (pollset->query_set[i].reqevents & APR_POLLOUT) {
144             pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
145             pollset->num_write++;
146         }
147     }
148 
149     for (i = 0; i < pollset->nelts; i++) {
150         if (pollset->query_set[i].reqevents & APR_POLLPRI) {
151             pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes;
152             pollset->num_except++;
153         }
154     }
155 
156     pollset->num_total = pollset->num_read + pollset->num_write + pollset->num_except;
157 }
158 
159 
160 
apr_pollset_poll(apr_pollset_t * pollset,apr_interval_time_t timeout,apr_int32_t * num,const apr_pollfd_t ** descriptors)161 APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
162                                            apr_interval_time_t timeout,
163                                            apr_int32_t *num,
164                                            const apr_pollfd_t **descriptors)
165 {
166     int rv;
167     apr_uint32_t i;
168     int *pollresult;
169     int read_pos, write_pos, except_pos;
170 
171     if (pollset->num_read < 0) {
172         make_pollset(pollset);
173     }
174 
175     pollresult = alloca(sizeof(int) * pollset->num_total);
176     memcpy(pollresult, pollset->pollset, sizeof(int) * pollset->num_total);
177     (*num) = 0;
178 
179     if (timeout > 0) {
180         timeout /= 1000;
181     }
182 
183     rv = select(pollresult, pollset->num_read, pollset->num_write, pollset->num_except, timeout);
184 
185     if (rv < 0) {
186         return APR_FROM_OS_ERROR(sock_errno());
187     }
188 
189     if (rv == 0) {
190         return APR_TIMEUP;
191     }
192 
193     read_pos = 0;
194     write_pos = pollset->num_read;
195     except_pos = pollset->num_read + pollset->num_write;
196 
197     for (i = 0; i < pollset->nelts; i++) {
198         int rtnevents = 0;
199 
200         if (pollset->query_set[i].reqevents & APR_POLLIN) {
201             if (pollresult[read_pos++] != -1) {
202                 rtnevents |= APR_POLLIN;
203             }
204         }
205 
206         if (pollset->query_set[i].reqevents & APR_POLLOUT) {
207             if (pollresult[write_pos++] != -1) {
208                 rtnevents |= APR_POLLOUT;
209             }
210         }
211 
212         if (pollset->query_set[i].reqevents & APR_POLLPRI) {
213             if (pollresult[except_pos++] != -1) {
214                 rtnevents |= APR_POLLPRI;
215             }
216         }
217 
218         if (rtnevents) {
219             pollset->result_set[*num] = pollset->query_set[i];
220             pollset->result_set[*num].rtnevents = rtnevents;
221             (*num)++;
222         }
223     }
224 
225     if (descriptors) {
226         *descriptors = pollset->result_set;
227     }
228 
229     return APR_SUCCESS;
230 }
231