1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
#include "apr_arch_poll_private.h"
19
#if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL)
21
static apr_int16_t get_event(apr_int16_t event)
25
if (event & APR_POLLIN)
27
if (event & APR_POLLPRI)
29
if (event & APR_POLLOUT)
31
if (event & APR_POLLERR)
33
if (event & APR_POLLHUP)
35
if (event & APR_POLLNVAL)
41
static apr_int16_t get_revent(apr_int16_t event)
61
#endif /* POLL_USES_POLL || POLLSET_USES_POLL */
66
#define SMALL_POLLSET_LIMIT 8
68
APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num,
70
apr_interval_time_t timeout)
74
/* XXX: I trust that this is a segv when insufficient stack exists? */
75
struct pollfd pollset[num];
76
#elif defined(HAVE_ALLOCA)
77
struct pollfd *pollset = alloca(sizeof(struct pollfd) * num);
81
struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT];
82
struct pollfd *pollset;
84
if (num <= SMALL_POLLSET_LIMIT) {
85
pollset = tmp_pollset;
88
/* This does require O(n) to copy the descriptors to the internal
91
pollset = malloc(sizeof(struct pollfd) * num);
92
/* The other option is adding an apr_pool_abort() fn to invoke
93
* the pool's out of memory handler
99
for (i = 0; i < num; i++) {
100
if (aprset[i].desc_type == APR_POLL_SOCKET) {
101
pollset[i].fd = aprset[i].desc.s->socketdes;
103
else if (aprset[i].desc_type == APR_POLL_FILE) {
104
pollset[i].fd = aprset[i].desc.f->filedes;
109
pollset[i].events = get_event(aprset[i].reqevents);
114
timeout /= 1000; /* convert microseconds to milliseconds */
117
i = poll(pollset, num_to_poll, timeout);
120
if (i > 0) { /* poll() sets revents only if an event was signalled;
121
* we don't promise to set rtnevents unless an event
124
for (i = 0; i < num; i++) {
125
aprset[i].rtnevents = get_revent(pollset[i].revents);
129
#if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA)
130
if (num > SMALL_POLLSET_LIMIT) {
136
return apr_get_netos_error();
145
#endif /* POLL_USES_POLL */
148
#ifdef POLLSET_USES_POLL
155
struct pollfd *pollset;
156
apr_pollfd_t *query_set;
157
apr_pollfd_t *result_set;
160
APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
165
if (flags & APR_POLLSET_THREADSAFE) {
170
*pollset = apr_palloc(p, sizeof(**pollset));
171
(*pollset)->nelts = 0;
172
(*pollset)->nalloc = size;
173
(*pollset)->pool = p;
174
(*pollset)->pollset = apr_palloc(p, size * sizeof(struct pollfd));
175
(*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
176
(*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
180
APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
185
APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
186
const apr_pollfd_t *descriptor)
188
if (pollset->nelts == pollset->nalloc) {
192
pollset->query_set[pollset->nelts] = *descriptor;
194
if (descriptor->desc_type == APR_POLL_SOCKET) {
195
pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
198
pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
201
pollset->pollset[pollset->nelts].events =
202
get_event(descriptor->reqevents);
208
APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
209
const apr_pollfd_t *descriptor)
213
for (i = 0; i < pollset->nelts; i++) {
214
if (descriptor->desc.s == pollset->query_set[i].desc.s) {
215
/* Found an instance of the fd: remove this and any other copies */
216
apr_uint32_t dst = i;
217
apr_uint32_t old_nelts = pollset->nelts;
219
for (i++; i < old_nelts; i++) {
220
if (descriptor->desc.s == pollset->query_set[i].desc.s) {
224
pollset->pollset[dst] = pollset->pollset[i];
225
pollset->query_set[dst] = pollset->query_set[i];
236
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
237
apr_interval_time_t timeout,
239
const apr_pollfd_t **descriptors)
247
rv = poll(pollset->pollset, pollset->nelts, timeout);
250
return apr_get_netos_error();
256
for (i = 0; i < pollset->nelts; i++) {
257
if (pollset->pollset[i].revents != 0) {
258
pollset->result_set[j] = pollset->query_set[i];
259
pollset->result_set[j].rtnevents =
260
get_revent(pollset->pollset[i].revents);
265
*descriptors = pollset->result_set;
269
#endif /* POLLSET_USES_POLL */