Patch to remove segfault on the exiting of a service.
[openais.git] / exec / aispoll.c
blob71741a5bee25e2b108a88d7fabbe6d9425b5626f
1 /*
2 * Copyright (c) 2003-2004 MontaVista Software, Inc.
3 * Copyright (c) 2006 Sun Microsystems, Inc.
5 * All rights reserved.
7 * Author: Steven Dake (sdake@mvista.com)
9 * This software licensed under BSD license, the text of which follows:
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of the MontaVista Software, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
35 #include <errno.h>
36 #include <pthread.h>
37 #include <sys/poll.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
42 #include "aispoll.h"
43 #include "../include/list.h"
44 #include "../include/hdb.h"
45 #include "tlist.h"
47 typedef int (*dispatch_fn_t) (poll_handle poll_handle, int fd, int revents, void *data);
49 struct poll_entry {
50 struct pollfd ufd;
51 dispatch_fn_t dispatch_fn;
52 void *data;
55 struct poll_instance {
56 struct poll_entry *poll_entries;
57 struct pollfd *ufds;
58 int poll_entry_count;
59 struct timerlist timerlist;
60 void (*serialize_lock_fn) (void);
61 void (*serialize_unlock_fn) (void);
65 * All instances in one database
67 static struct hdb_handle_database poll_instance_database = {
68 .handle_count = 0,
69 .handles = 0,
70 .iterator = 0
73 poll_handle poll_create (
74 void (*serialize_lock_fn) (void),
75 void (*serialize_unlock_fn) (void))
77 poll_handle handle;
78 struct poll_instance *poll_instance;
79 unsigned int res;
81 res = hdb_handle_create (&poll_instance_database,
82 sizeof (struct poll_instance), &handle);
83 if (res != 0) {
84 goto error_exit;
86 res = hdb_handle_get (&poll_instance_database, handle,
87 (void *)&poll_instance);
88 if (res != 0) {
89 goto error_destroy;
92 poll_instance->poll_entries = 0;
93 poll_instance->ufds = 0;
94 poll_instance->poll_entry_count = 0;
95 poll_instance->serialize_lock_fn = serialize_lock_fn;
96 poll_instance->serialize_unlock_fn = serialize_unlock_fn;
97 timerlist_init (&poll_instance->timerlist);
99 return (handle);
101 error_destroy:
102 hdb_handle_destroy (&poll_instance_database, handle);
104 error_exit:
105 return (-1);
108 int poll_destroy (poll_handle handle)
110 struct poll_instance *poll_instance;
111 int res = 0;
113 res = hdb_handle_get (&poll_instance_database, handle,
114 (void *)&poll_instance);
115 if (res != 0) {
116 res = -ENOENT;
117 goto error_exit;
120 if (poll_instance->poll_entries) {
121 free (poll_instance->poll_entries);
123 if (poll_instance->ufds) {
124 free (poll_instance->ufds);
127 hdb_handle_destroy (&poll_instance_database, handle);
129 hdb_handle_put (&poll_instance_database, handle);
131 error_exit:
132 return (res);
135 int poll_dispatch_add (
136 poll_handle handle,
137 int fd,
138 int events,
139 void *data,
140 int (*dispatch_fn) (
141 poll_handle poll_handle,
142 int fd,
143 int revents,
144 void *data))
146 struct poll_instance *poll_instance;
147 struct poll_entry *poll_entries;
148 struct pollfd *ufds;
149 int found = 0;
150 int install_pos;
151 int res = 0;
153 res = hdb_handle_get (&poll_instance_database, handle,
154 (void *)&poll_instance);
155 if (res != 0) {
156 res = -ENOENT;
157 goto error_exit;
160 for (found = 0, install_pos = 0; install_pos < poll_instance->poll_entry_count; install_pos++) {
161 if (poll_instance->poll_entries[install_pos].ufd.fd == -1) {
162 found = 1;
163 break;
167 if (found == 0) {
169 * Grow pollfd list
171 poll_entries = (struct poll_entry *)realloc (poll_instance->poll_entries,
172 (poll_instance->poll_entry_count + 1) *
173 sizeof (struct poll_entry));
174 if (poll_entries == NULL) {
175 res = -ENOMEM;
176 goto error_put;
178 poll_instance->poll_entries = poll_entries;
180 ufds = (struct pollfd *)realloc (poll_instance->ufds,
181 (poll_instance->poll_entry_count + 1) *
182 sizeof (struct pollfd));
183 if (ufds == NULL) {
184 res = -ENOMEM;
185 goto error_put;
187 poll_instance->ufds = ufds;
189 poll_instance->poll_entry_count += 1;
190 install_pos = poll_instance->poll_entry_count - 1;
194 * Install new dispatch handler
196 poll_instance->poll_entries[install_pos].ufd.fd = fd;
197 poll_instance->poll_entries[install_pos].ufd.events = events;
198 poll_instance->poll_entries[install_pos].ufd.revents = 0;
199 poll_instance->poll_entries[install_pos].dispatch_fn = dispatch_fn;
200 poll_instance->poll_entries[install_pos].data = data;
202 error_put:
203 hdb_handle_put (&poll_instance_database, handle);
205 error_exit:
206 return (res);
209 int poll_dispatch_modify (
210 poll_handle handle,
211 int fd,
212 int events,
213 int (*dispatch_fn) (
214 poll_handle poll_handle,
215 int fd,
216 int revents,
217 void *data))
219 struct poll_instance *poll_instance;
220 int i;
221 int res = 0;
223 res = hdb_handle_get (&poll_instance_database, handle,
224 (void *)&poll_instance);
225 if (res != 0) {
226 res = -ENOENT;
227 goto error_exit;
231 * Find file descriptor to modify events and dispatch function
233 for (i = 0; i < poll_instance->poll_entry_count; i++) {
234 if (poll_instance->poll_entries[i].ufd.fd == fd) {
235 poll_instance->poll_entries[i].ufd.events = events;
236 poll_instance->poll_entries[i].dispatch_fn = dispatch_fn;
238 goto error_put;
242 res = -EBADF;
244 error_put:
245 hdb_handle_put (&poll_instance_database, handle);
247 error_exit:
248 return (res);
251 int poll_dispatch_delete (
252 poll_handle handle,
253 int fd)
255 struct poll_instance *poll_instance;
256 int i;
257 int res = 0;
259 res = hdb_handle_get (&poll_instance_database, handle,
260 (void *)&poll_instance);
261 if (res != 0) {
262 res = -ENOENT;
263 goto error_exit;
267 * Find dispatch fd to delete
269 res = -EBADF;
270 for (i = 0; i < poll_instance->poll_entry_count; i++) {
271 if (poll_instance->poll_entries[i].ufd.fd == fd) {
272 poll_instance->poll_entries[i].ufd.fd = -1;
273 poll_instance->poll_entries[i].ufd.revents = 0;
274 break;
279 hdb_handle_put (&poll_instance_database, handle);
281 error_exit:
282 return (res);
285 int poll_timer_add (
286 poll_handle handle,
287 int msec_duration, void *data,
288 void (*timer_fn) (void *data),
289 poll_timer_handle *timer_handle_out)
291 struct poll_instance *poll_instance;
292 int res = 0;
294 res = hdb_handle_get (&poll_instance_database, handle,
295 (void *)&poll_instance);
296 if (res != 0) {
297 res = -ENOENT;
299 goto error_exit;
302 if (timer_handle_out == 0) {
303 res = -ENOENT;
306 timerlist_add_duration (&poll_instance->timerlist,
307 timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
309 hdb_handle_put (&poll_instance_database, handle);
310 error_exit:
311 return (res);
314 int poll_timer_delete (
315 poll_handle handle,
316 poll_timer_handle timer_handle)
318 struct poll_instance *poll_instance;
319 int res = 0;
321 if (timer_handle == 0) {
322 return (0);
324 res = hdb_handle_get (&poll_instance_database, handle,
325 (void *)&poll_instance);
326 if (res != 0) {
327 res = -ENOENT;
328 goto error_exit;
331 timerlist_del (&poll_instance->timerlist, (void *)timer_handle);
333 hdb_handle_put (&poll_instance_database, handle);
335 error_exit:
336 return (res);
339 int poll_run (
340 poll_handle handle)
342 struct poll_instance *poll_instance;
343 int i;
344 unsigned long long expire_timeout_msec = -1;
345 int res;
346 int poll_entry_count;
348 res = hdb_handle_get (&poll_instance_database, handle,
349 (void *)&poll_instance);
350 if (res != 0) {
351 goto error_exit;
354 for (;;) {
355 for (i = 0; i < poll_instance->poll_entry_count; i++) {
356 memcpy (&poll_instance->ufds[i],
357 &poll_instance->poll_entries[i].ufd,
358 sizeof (struct pollfd));
360 expire_timeout_msec = timerlist_msec_duration_to_expire (&poll_instance->timerlist);
362 if (expire_timeout_msec != -1 && expire_timeout_msec > 0xFFFFFFFF) {
363 expire_timeout_msec = 0xFFFFFFFE;
366 retry_poll:
367 res = poll (poll_instance->ufds,
368 poll_instance->poll_entry_count, expire_timeout_msec);
369 if (errno == EINTR && res == -1) {
370 goto retry_poll;
371 } else
372 if (res == -1) {
373 goto error_exit;
376 poll_entry_count = poll_instance->poll_entry_count;
377 for (i = 0; i < poll_entry_count; i++) {
378 if (poll_instance->ufds[i].fd != -1 &&
379 poll_instance->ufds[i].revents) {
381 poll_instance->serialize_lock_fn();
382 res = poll_instance->poll_entries[i].dispatch_fn (handle,
383 poll_instance->ufds[i].fd,
384 poll_instance->ufds[i].revents,
385 poll_instance->poll_entries[i].data);
387 poll_instance->serialize_unlock_fn();
389 * Remove dispatch functions that return -1
391 if (res == -1) {
392 poll_instance->poll_entries[i].ufd.fd = -1; /* empty entry */
396 poll_instance->serialize_lock_fn();
397 timerlist_expire (&poll_instance->timerlist);
398 poll_instance->serialize_unlock_fn();
399 } /* for (;;) */
401 hdb_handle_put (&poll_instance_database, handle);
402 error_exit:
403 return (-1);
406 int poll_stop (
407 poll_handle handle);
409 #ifdef COMPILE_OUT
410 void poll_print_state (
411 poll_handle handle,
412 int fd)
414 struct poll_instance *poll_instance;
415 int i;
416 int res = 0;
417 res = hdb_handle_get (&poll_instance_database, handle,
418 (void *)&poll_instance);
419 if (res != 0) {
420 res = -ENOENT;
421 exit (1);
424 for (i = 0; i < poll_instance->poll_entry_count; i++) {
425 if (poll_instance->poll_entries[i].ufd.fd == fd) {
426 printf ("fd %d\n", poll_instance->poll_entries[i].ufd.fd);
427 printf ("events %d\n", poll_instance->poll_entries[i].ufd.events);
428 printf ("dispatch_fn %p\n", poll_instance->poll_entries[i].dispatch_fn);
433 #endif