4
* Code for handling an operation queue.
6
* Author: MontaVista Software, Inc.
7
* Corey Minyard <minyard@mvista.com>
10
* Copyright 2002,2003 MontaVista Software Inc.
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.
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.
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.
37
#include <OpenIPMI/os_handler.h>
39
#include <OpenIPMI/internal/ipmi_int.h>
40
#include <OpenIPMI/internal/ilist.h>
41
#include <OpenIPMI/internal/opq.h>
43
typedef struct opq_elem_s
46
opq_handler_cb handler;
50
struct opq_elem_s *next;
59
opq_done_cb done_handler;
68
opq->os_hnd->lock(opq->os_hnd, opq->lock);
72
opq_unlock(opq_t *opq)
75
opq->os_hnd->unlock(opq->os_hnd, opq->lock);
79
opq_alloc(os_handler_t *os_hnd)
84
opq = ipmi_mem_alloc(sizeof(*opq));
87
memset(opq, 0, sizeof(*opq));
91
opq->ops = alloc_ilist();
97
if (os_hnd->create_lock) {
98
rv = os_hnd->create_lock(opq->os_hnd, &(opq->lock));
100
free_ilist(opq->ops);
112
opq_destroy_item(ilist_iter_t *iter, void *item, void *cb_data)
114
opq_elem_t *elem = (opq_elem_t *) item;
116
elem->handler(elem->handler_data, 1);
121
opq_destroy(opq_t *opq)
123
ilist_iter(opq->ops, opq_destroy_item, NULL);
124
free_ilist(opq->ops);
126
opq->os_hnd->destroy_lock(opq->os_hnd, opq->lock);
131
opq_new_op(opq_t *opq, opq_handler_cb handler, void *cb_data, int nowait)
136
if (opq->in_handler) {
141
elem = ipmi_mem_alloc(sizeof(*elem));
144
elem->handler = handler;
146
elem->handler_data = cb_data;
148
if (! ilist_add_tail(opq->ops, elem, NULL)) {
157
opq->done_handler = NULL;
170
opq_new_op_with_done(opq_t *opq,
171
opq_handler_cb handler,
179
if (opq->in_handler) {
180
elem = ipmi_mem_alloc(sizeof(*elem));
183
elem->handler = handler;
184
elem->handler_data = handler_data;
186
elem->done_data = done_data;
187
elem->block = opq->blocked;
188
if (! ilist_add_tail(opq->ops, elem, NULL)) {
197
opq->done_handler = done;
198
opq->done_data = done_data;
200
handler(handler_data, 0);
211
opq_add_block(opq_t *opq)
219
opq_op_done(opq_t *opq)
223
opq_elem_t *list = NULL;
225
opq_elem_t **list_end = &list;
226
opq_done_cb done_handler;
229
/* First check for done handlers. */
231
ilist_init_iter(&iter, opq->ops);
233
elem = ilist_get(&iter);
234
while (elem && (!elem->block)) {
238
list_end = &(elem->next);
239
elem = ilist_get(&iter);
241
done_handler = opq->done_handler;
242
done_data = opq->done_data;
243
opq->done_handler = NULL;
244
if (done_handler || list) {
245
/* There are done handlers to call, unlock and call them. */
249
done_handler(done_data, 0);
252
list->done(list->done_data, 0);
258
/* During the time we were unlocked, handlers may have been
261
elem = ilist_get(&iter);
265
opq->done_handler = elem->done;
266
opq->done_data = elem->done_data;
268
elem->handler(elem->handler_data, 0);
271
/* The list is empty. */
278
opq_stuff_in_progress(opq_t *opq)
280
return opq->in_handler;