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