eh.c revision 2
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * signal_to_eh[] is pretty much useless, since the event handler is 2N/A * really a singleton (we pass iu_eh_t *'s around to maintain an 2N/A * abstraction, not to allow multiple event handlers to exist). we 2N/A * need some way to get back our event handler in post_signal(), 2N/A * and since the signal model is too lame to provide opaque pointers, 2N/A * we have to resort to global variables. 2N/A * iu_eh_create(): creates, initializes, and returns an event handler for use 2N/A * output: iu_eh_t *: the new event handler 2N/A * iu_eh_destroy(): destroys an existing event handler 2N/A * input: iu_eh_t *: the event handler to destroy 2N/A * notes: it is assumed all events related to this eh have been unregistered 2N/A * prior to calling iu_eh_destroy() 2N/A * iu_stop_handling_events(): informs the event handler to stop handling events 2N/A * input: iu_eh_t *: the event handler to stop. 2N/A * unsigned int: the (user-defined) reason why 2N/A * iu_eh_shutdown_t *: the shutdown callback. if it is NULL, 2N/A * the event handler will stop right away; 2N/A * otherwise, the event handler will not 2N/A * stop until the callback returns B_TRUE 2N/A * void *: data for the shutdown callback. it may be NULL 2N/A * notes: the event handler in question must be in iu_handle_events() 2N/A * grow_fds(): grows the internal file descriptor set used by the event 2N/A * input: iu_eh_t *: the event handler whose descriptor set needs to be grown 2N/A * int: the new total number of descriptors needed in the set 2N/A * output: int: zero on failure, success otherwise 2N/A * yow. one realloc failed, but the other succeeded. 2N/A * we will just leave the descriptor size at the 2N/A * original size. if the caller tries again, then the 2N/A * first realloc() will do nothing since the requested 2N/A * number of descriptors is already allocated. 2N/A * when increasing the file descriptor set size, how much to increase by: 2N/A * iu_register_event(): adds an event to the set managed by an event handler 2N/A * input: iu_eh_t *: the event handler to add the event to 2N/A * int: the descriptor on which to listen for events. must be 2N/A * a descriptor which has not yet been registered. 2N/A * short: the events to listen for on that descriptor 2N/A * iu_eh_callback_t: the callback to execute when the event happens 2N/A * void *: the argument to pass to the callback function 2N/A * output: iu_event_id_t: -1 on failure, the new event id otherwise 2N/A * the current implementation uses the file descriptor itself 2N/A * as the iu_event_id_t, since we know the kernel's gonna be 2N/A * pretty smart about managing file descriptors and we know 2N/A * that they're per-process unique. however, it does mean 2N/A * that the same descriptor cannot be registered multiple 2N/A * times for different callbacks depending on its events. if 2N/A * this behavior is desired, either use dup(2) to get a unique 2N/A * descriptor, or demultiplex in the callback function based 2N/A * iu_unregister_event(): removes an event from the set managed by an event 2N/A * input: iu_eh_t *: the event handler to remove the event from 2N/A * iu_event_id_t: the event to remove (from iu_register_event()) 2N/A * void **: if non-NULL, will be set to point to the argument passed 2N/A * into iu_register_event() 2N/A * output: int: zero on failure, success otherwise 2N/A * fringe condition: in case this event was about to be called 2N/A * back in iu_handle_events(), zero revents to prevent it. 2N/A * (having an unregistered event get called back could be 2N/A * disastrous depending on if `arg' is reference counted). 2N/A * iu_handle_events(): begins handling events on an event handler 2N/A * input: iu_eh_t *: the event handler to begin event handling on 2N/A * tq_t *: a timer queue of timers to process while handling events 2N/A * output: int: the reason why we stopped, -1 if due to internal failure 2N/A * we only unblock registered signals around poll(); this 2N/A * way other parts of the code don't have to worry about 2N/A * restarting "non-restartable" system calls and so forth. 2N/A * timeout occurred. we must have a valid tq pointer 2N/A * since that's the only way a timeout can happen. 2N/A /* file descriptors are lit; call 'em back */ 2N/A * turn off any descriptors that have gone 2N/A * bad. shouldn't happen, but... 2N/A /* TODO: issue a warning here - but how? */ 2N/A * post_signal(): posts a signal for later consumption in iu_handle_events() 2N/A * input: int: the signal that's been received 2N/A * iu_eh_register_signal(): registers a signal handler with an event handler 2N/A * input: iu_eh_t *: the event handler to register the signal handler with 2N/A * int: the signal to register 2N/A * iu_eh_sighandler_t *: the signal handler to call back 2N/A * void *: the argument to pass to the signal handler function 2N/A * output: int: zero on failure, success otherwise 2N/A * iu_eh_unregister_signal(): unregisters a signal handler from an event handler 2N/A * input: iu_eh_t *: the event handler to unregister the signal handler from 2N/A * int: the signal to unregister 2N/A * void **: if non-NULL, will be set to point to the argument passed 2N/A * into iu_eh_register_signal() 2N/A * output: int: zero on failure, success otherwise