1 /* 2 * opq.h 3 * 4 * Code for handling an operation queue. 5 * 6 * Author: MontaVista Software, Inc. 7 * Corey Minyard <minyard@mvista.com> 8 * source@mvista.com 9 * 10 * Copyright 2002 MontaVista Software Inc. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Lesser General Public License 14 * as published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * You should have received a copy of the GNU Lesser General Public 30 * License along with this program; if not, write to the Free 31 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 32 */ 33 34 #ifndef OPENIPMI_OPQ_H 35 #define OPENIPMI_OPQ_H 36 37 #include <OpenIPMI/os_handler.h> 38 39 typedef struct opq_s opq_t; 40 41 #define OPQ_HANDLER_STARTED 0 42 #define OPQ_HANDLER_ABORTED 1 43 /* The callback to start an operation. If shutdown is true, then the 44 queue is being destroyed, and the callee should take appropriate 45 action. This should return either IPQ_HANDLER_STARTED if the 46 operation is started or OPQ_HANDLER_ABORTED if the operation does 47 not start for some reason. If this returns OPQ_HANDLER_ABORTED, 48 the opq will go on to the next operation. */ 49 typedef int (*opq_handler_cb)(void *cb_data, int shutdown); 50 51 /* The callback from opq done operations. If shutdown is true, then 52 the queue is being destroyed, and the callee should take 53 appropriate action. */ 54 typedef void (*opq_done_cb)(void *cb_data, int shutdown); 55 56 opq_t *opq_alloc(os_handler_t *os_hnd); 57 58 /* Call all the done handlers for everything in the queue, and free 59 all the elements and free the queue. */ 60 void opq_destroy(opq_t *opq); 61 62 /* A new operation is ready. If the opq is empty, the handler will be 63 called immediately and the opq will be set in use. Otherwise, the 64 operations will be queued. If "nowait" is true, then this will 65 return immediately with -1 if it would have been queued. Returns 1 66 on success, 0 on failure, or -1 if it would have been queued. */ 67 int opq_new_op(opq_t *opq, opq_handler_cb handler, void *cb_data, int nowait); 68 69 typedef struct opq_elem_s opq_elem_t; 70 opq_elem_t *opq_alloc_elem(void); 71 void opq_free_elem(opq_elem_t *elem); 72 73 /* Like opq_new_op, but allows the head or tail to be specified. The 74 interface is open to support real priorities, but there's no 75 requirement for that yet. Also allows an opq_elem_t to be passed 76 in; then the operation cannot fail. Note that if this succeeds, 77 you do *not* need to free the elem, and the elem must be allocated 78 with opq_alloc_elem(). */ 79 #define OPQ_ADD_HEAD 100 80 #define OPQ_ADD_TAIL 0 81 int opq_new_op_prio(opq_t *opq, opq_handler_cb handler, void *cb_data, 82 int nowait, int prio, opq_elem_t *elem); 83 84 /* A new operation is ready. If the opq is empty, the handler will be 85 called immediately and the opq will be set in use. Otherwise, the 86 operation is queued. When the operation is done, the done handler 87 for the operation is called, and any subsequent handlers registered 88 this way will have their done handler called. The handlers for the 89 subsequent operations with done will NOT be called, just the done 90 handlers. If an operation is registered without a done handler (or 91 with a NULL done handler) then it will "block" the queue, all the 92 ones with done handlers before it will be called, but the ones with 93 done handlers registered after this one will be call after the 94 "blocker" one runs. */ 95 int opq_new_op_with_done(opq_t *opq, 96 opq_handler_cb handler, 97 void *handler_data, 98 opq_done_cb done, 99 void *done_data); 100 101 /* Adds a "block" at the current point in the opq. Any "with done" 102 handlers that get called after a block is added will be held. This 103 way, the user can say "Anything new ops after now will have their 104 handler called. */ 105 void opq_add_block(opq_t *opq); 106 107 /* Must be called when an operation completes, this will cause all the 108 done handlers to run if there are any, then allow the next 109 operation to run, if there is one. */ 110 void opq_op_done(opq_t *opq); 111 112 /* Returns true if the queue has current working stuff, false if not. */ 113 int opq_stuff_in_progress(opq_t *opq); 114 115 #endif /* OPENIPMI_OPQ_H */ 116